
Some notes on my solution:
(0) It accepts a binary image as input.
(1) It finds it for all regions in the image.
(2) It finds the greatest diameter of the convex hull of the region. I think this is a reasonable thing to do, but you can adjust the implementation if you like.
(3) I use the skimage.data "coins" image so you can reproduce yourself.
import sys
# To find the diameters
from skimage.measure import regionprops, label
from sklearn.metrics import pairwise_distances
from scipy import ndimage as ndi
import numpy as np
# To generate test data
from skimage import data
from skimage.filters import sobel
from skimage.morphology import watershed
# For visualization
import matplotlib.pyplot as plt
STREL_4 = np.array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]], dtype=np.bool)
def get_border_image(region):
convex_hull_mask = region.convex_image
eroded_image = ndi.binary_erosion(convex_hull_mask, STREL_4, border_value=0)
border_image = np.logical_xor(convex_hull_mask, eroded_image)
return border_image
def get_region_diameters(img):
assert img.dtype == np.bool and len(img.shape) == 2
label_img = label(img, connectivity=img.ndim)
for region in regionprops(label_img):
border_image = get_border_image(region)
perimeter_coordinates = np.transpose(np.nonzero(border_image))
pairwise_distances_matrix = pairwise_distances(perimeter_coordinates)
i, j = np.unravel_index(np.argmax(pairwise_distances_matrix), pairwise_distances_matrix.shape)
ptA, ptB = perimeter_coordinates[i], perimeter_coordinates[j]
region_offset = np.asarray([region.bbox[0], region.bbox[1]])
ptA += region_offset
ptB += region_offset
yield pairwise_distances_matrix[i, j], ptA, ptB
if __name__ == "__main__":
# Create a segmentation of the coins image, for testing purposes.
# You should create a binary image
coins = data.coins()
elevation_map = sobel(coins)
markers = np.zeros_like(coins)
markers[coins < 30] = 1
markers[coins > 150] = 2
segmentation = (watershed(elevation_map, markers) > 1)
for distance, ptA, ptB in get_region_diameters(segmentation):
plt.imshow(segmentation)
x1, x2, y1, y2 = ptA[1], ptB[1], ptA[0], ptB[0]
plt.plot([x1, x2], [y1, y2], color='k', linestyle='-', linewidth=2)
print(distance, ptA, ptB)
plt.show()