How to find the diameter of objects using image processing in Python?
Question: Given an image with some irregular objects in it, I want to find their
individual diameter.

[Thanks to this answer](http://stackoverflow.com/questions/33707095/how-to-
locate-a-particular-region-of-values-in-a-2d-numpy-array?answertab=active#tab-
top), I know how to identify the objects. **However, is it possible to measure
the maximum diameter of the objects shown in the image?**

I have looked into the `scipy-ndimage` documentation and haven't found a
dedicated function.

Code for object identification:

    
    
    import numpy as np
    from scipy import ndimage
    from matplotlib import pyplot as plt
    
    # generate some lowpass-filtered noise as a test image
    gen = np.random.RandomState(0)
    img = gen.poisson(2, size=(512, 512))
    img = ndimage.gaussian_filter(img.astype(np.double), (30, 30))
    img -= img.min()
    img /= img.max()
    
    # use a boolean condition to find where pixel values are > 0.75
    blobs = img > 0.75
    
    # label connected regions that satisfy this condition
    labels, nlabels = ndimage.label(blobs)
    
    # find their centres of mass. in this case I'm weighting by the pixel values in
    # `img`, but you could also pass the boolean values in `blobs` to compute the
    # unweighted centroids.
    r, c = np.vstack(ndimage.center_of_mass(img, labels, np.arange(nlabels) + 1)).T
    
    # find their distances from the top-left corner
    d = np.sqrt(r*r + c*c)
    
    # plot
    fig, ax = plt.subplots(1, 2, sharex=True, sharey=True, figsize=(10, 5))
    ax[0].imshow(img)
    ax[1].hold(True)
    ax[1].imshow(np.ma.masked_array(labels, ~blobs), cmap=plt.cm.rainbow)
    for ri, ci, di in zip(r, c, d):
        ax[1].annotate('', xy=(0, 0), xytext=(ci, ri),
                       arrowprops={'arrowstyle':'<-', 'shrinkA':0})
        ax[1].annotate('d=%.1f' % di, xy=(ci, ri),  xytext=(0, -5),
                       textcoords='offset points', ha='center', va='top',
                       fontsize='x-large')
    for aa in ax.flat:
        aa.set_axis_off()
    fig.tight_layout()
    plt.show()
    

Image: [![enter image description
here](http://i.stack.imgur.com/yOznb.png)](http://i.stack.imgur.com/yOznb.png)


Answer: You could use `skimage.measure.regionprops` to determine the bounding box of
all the regions in your image. For roughly circular blobs the diameter of the
minimum enclosing circle can be approximated by the **largest side of the
bounding box**. To do so you just need to add the following snippet at the end
of your script:

    
    
    from skimage.measure import regionprops
    N = 20
    img_dig = np.digitize(img, np.linspace(0, 1, N))
    properties = regionprops(img_dig)
    print 'Label \tLargest side'
    for p in properties:
        min_row, min_col, max_row, max_col = p.bbox
        print '%5d %14.3f' % (p.label, max(max_row - min_row, max_col - min_col))
    

It is important to note that it is necessary to digitize `img` since
`regionprops` does not accept arrays of float values. In the example above
`img` was quantized into `N = 20` bins (each bin is uniquely identified by an
integer index). You may want to test other values of `N` to better fit your
needs.

And this is the output you get:

    
    
    Label   Largest side
        1        251.000
        2        270.000
        3        368.000
        4        512.000
        5        512.000
        6        512.000
        7        512.000
        8        512.000
        9        512.000
       10        512.000
       11        512.000
       12        512.000
       13        512.000
       14        512.000
       15        512.000
       16        512.000
       17        457.000
       18        419.000
       19         58.000
       20          1.000
    

