1

Given an input image for example a jpg with some circular objects (coins for example), I want to find their individual diameters.

Thanks to this question (How to find the diameter of objects using image processing in Python?) , I know how to identify the objects, but I wanted to measure the diameter of the images inserted by me and not generate randomly with methods. How can I do it?

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()

I am new here so I do not know how to play very well, the images that this code generates are in the link of the question where I am based.

  • You've switched to Spanish for a bit in the question, could you please set the full question in english? I believe the core of your question to be there but I do not understand it. Thank you. – Luca Cappelletti Jul 27 '18 at 05:44
  • You are looking for a blob detection algorithm. Check out example of blob detection in [scikit-image package](http://scikit-image.org/docs/dev/auto_examples/features_detection/plot_blob.html). – the-lay Jul 27 '18 at 09:13
  • the-lay, I already do this blob detection through the ORB algorithm, but thanks for the suggestion. I really wanted to find the diameter of these blobs found. – Michel Madruga Jul 27 '18 at 16:46
  • Thanks for the comment Luca Cappelletti, I corrected. This code is calculating the diameter of a random generated image (poisson), wanted to know how can I modify this code so that I insert an image (for example png) instead of generating it in the code? – Michel Madruga Jul 27 '18 at 16:48

2 Answers2

0

A simple approximation could be to assume perfectly circular objects, then the radius is the square root of the area (i.e. number of pixels) divided by pi:

def radius(A):
    return np.sqrt( A/np.pi )

def max_bounding_box(labels, k):
    idx, idy = np.where( labels==k )
    Sx = max(idx) - min(idx)
    Sy = max(idy) - min(idy)
    return max(Sx, Sy)/2

for k in range(1, nlabels):
    A = len( np.nonzero( labels==k )[0] )
    print(k, radius(A), max_bounding_box(labels, k)


1 41.32472068116174 52.5
2 31.040683392579073 37.0
3 34.37391885593249 39.0
4 26.986904594423443 27.5
5 73.79677393164606 80.0
6 15.012108426804138 17.0

Otherwise, the radius is not well defined: size of the bounding box?, arc having max length?

edit: I added the evaluation of the largest size of the bounding box

xdze2
  • 3,986
  • 2
  • 12
  • 29
0

You could use the OpenCV2-function cv2.connectedComponentsWithStats(blobs).This functions returns the leftmost (x) coordinate which is the inclusive start of the bounding box in the horizontal direction, The topmost (y) coordinate which is the inclusive start of the bounding box in the vertical direction, The horizontal size of the bounding box, The vertical size of the bounding box, the total area (in pixels) of the connected component.To use these function you have to convert blobs.dtype='uint8'. With the area and assuming a perfectly circular object you could calculate the diameter or you use the sizes of the bounding box as suggested.

startpy
  • 36
  • 3