This answer explains how to find the thickest part of a contour. There are four steps to this answer. You have already accomplished some of these steps, for clarity I will reiterate them in this answer.
Step 1: Detect the skeleton
import cv2
import numpy as np
import math
# Read image
src = cv2.imread('/home/stephen/Desktop/banana.png')
img = src.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
mask = np.zeros_like(gray)
# Find contours in image
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[1]
# Draw skeleton of banana on the mask
img = gray.copy()
size = np.size(img)
skel = np.zeros(img.shape,np.uint8)
ret,img = cv2.threshold(img,5,255,0)
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
done = False
while( not done):
eroded = cv2.erode(img,element)
temp = cv2.dilate(eroded,element)
temp = cv2.subtract(img,temp)
skel = cv2.bitwise_or(skel,temp)
img = eroded.copy()
zeros = size - cv2.countNonZero(img)
if zeros==size: done = True
kernel = np.ones((2,2), np.uint8)
skel = cv2.dilate(skel, kernel, iterations=1)
skeleton_contours, _ = cv2.findContours(skel, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
largest_skeleton_contour = max(skeleton_contours, key=cv2.contourArea)
Step 2: Elongate the contour to the edges of the image
# Extend the skeleton past the edges of the banana
points = []
for point in largest_skeleton_contour: points.append(tuple(point[0]))
x,y = zip(*points)
z = np.polyfit(x,y,7)
f = np.poly1d(z)
x_new = np.linspace(0, img.shape[1],300)
y_new = f(x_new)
extension = list(zip(x_new, y_new))
img = src.copy()
for point in range(len(extension)-1):
a = tuple(np.array(extension[point], int))
b = tuple(np.array(extension[point+1], int))
cv2.line(img, a, b, (0,0,255), 1)
cv2.line(mask, a, b, 255, 1)
mask_px = np.count_nonzero(mask)
Step 3: Find distance between points in the contour, only look at distances that cross the skeleton line
# Find the distance between points in the contour of the banana
# Only look at distances that cross the mid line
def is_collision(mask_px, mask, a, b):
temp_image = mask.copy()
cv2.line(temp_image, a, b, 0, 2)
new_total = np.count_nonzero(temp_image)
if new_total != mask_px: return True
else: return False
def distance(a,b): return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
distances = []
for point_a in cnt[:int(len(cnt)/2)]:
temp_distance = 0
close_distance = img.shape[0] * img.shape[1]
close_points = (0,0),(0,0)
for point_b in cnt:
A, B = tuple(point_a[0]), tuple(point_b[0])
dist = distance(tuple(point_a[0]), tuple(point_b[0]))
if is_collision(mask_px, mask, A, B):
if dist < close_distance:
close_points = A, B
close_distance = dist
cv2.line(img, close_points[0], close_points[1], (234,234,123), 1)
distances.append((close_distance, close_points))
cv2.imshow('img',img)
cv2.waitKey(1)
Step 4: Find the maximum distance:
max_thickness = max(distances)
a, b = max_thickness[1][0], max_thickness[1][1]
cv2.line(img, a, b, (0,255,0), 4)
print("maximum thickness = ", max_thickness[0])