Irregular shape detection using python houghcircle opencv function

Currently, I am making circle detection on images look like this, but some of the droplets merge and form some irregular shapes (red marks in the original image). I use the houghcircle function in opencv to detect circles. For these irregular shapes, the function can detect them only as a few small circles, but I really want the program to consider the irregular shape as a whole large shape and get a big circle, as I draw in my output image.

Source image

Output image

My code will detect all circles and get their diameters.

Here is my code:

def circles(filename, p1, p2, minR, maxR): # print(filename) img = cv2.imread(filename, 0) img = img[0:1000, 0:1360] l = len(img) w = len(img[1]) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 25, param1 = int(p1) ,param2 = int(p2), minRadius = int(minR), maxRadius = int(maxR)) diameter = open(filename[:-4] + "_diamater.txt", "w") diameter.write("Diameters(um)\n") for i in circles[0,:]: diameter.write(str(i[2] * 1.29 * 2) + "\n") count = 0 d = [] area = [] for i in circles[0,:]: cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2) cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) count += 1 d += [i[2]*2] area += [i[2]*i[2]*pi*1.286*1.286] f = filename.split("/")[-1] cv2.imwrite(filename[:-4] + "_circle.jpg", cimg) # cv2.imwrite("test3/edge.jpg", edges) print "Number of Circles is %d" % count diaM = [] for i in d: diaM += [i*1.286] bWidth = range(int(min(diaM)) - 10, int(max(diaM)) + 10, 2) txt = ''' Sample name: %s Average diameter(um): %f std: %f Drop counts: %d Average coverage per drop(um^2): %f std: %f ''' % (f, np.mean(diaM), np.std(diaM), count, np.mean(area), np.std(area)) fig = plt.figure() fig.suptitle('Histogram of Diameters', fontsize=14, fontweight='bold') ax1 = fig.add_axes((.1,.4,.8,.5)) ax1.hist(diaM, bins = bWidth) ax1.set_xlabel('Diameter(um)') ax1.set_ylabel('Frequency') fig.text(.1,.1,txt) plt.savefig(filename[:-4] + '_histogram.jpg') plt.clf() print "Total area is %d" % (w*l) print "Total covered area is %d" % (np.sum(area)) rt = "Number of Circles is " + str(count) + "\n" + "Coverage percent is " + str(np.divide(np.sum(area), (w*l))) + "\n" return rt 
+5
source share
3 answers

If you still want to use the HoughCircles function, you can simply see if the two circles overlap and draw a new circle from them.

+1
source

You can use minEnclosingCircle for this. Find the contours of your image, then use the function to determine the shapes in circles.

The following is a simple C ++ code example. In your case, I feel that you should use a combination of Hough circles and minEnclosingCircle, as some of the circles in your image are very close to each other, it is possible that they can be detected as a single outline.

input image:

input

circumference:

output

 Mat im = imread("circ.jpg"); Mat gr; cvtColor(im, gr, CV_BGR2GRAY); Mat bw; threshold(gr, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); for(int idx = 0; idx >= 0; idx = hierarchy[idx][0]) { Point2f center; float radius; minEnclosingCircle(contours[idx], center, radius); circle(im, Point(center.x, center.y), radius, Scalar(0, 255, 255), 2); } 
+1
source

When you have such beautiful well-separated and contrasting patterns, the easiest way is to use form indexes. See this document or this poster . In both cases, you have a list of form indexes.

Thanks to the form indices you can:

  • duplicates image
  • Labeling connected components to separate each template
  • calculate form indices (most of them use basic measures)
  • classify the template according to the values โ€‹โ€‹of the form indices.

As in your particular case, round shapes are perfectly round, I would use the following shape indices:

  • Circularity => using only the radii, which are the easiest to calculate and improve in your case.
  • Expanding / Extending / Stretching with Radii => Ideal in your case, but calculating a mini-ball is not available in all libraries.
  • Iso-perimetric deficit => itโ€™s really easy to calculate, but a little less stable than the perimeter circuit.

Also work in your case:

  • Mortise Disc with Clearance
  • Morton Spread
  • Deficit
  • Diameter expansion
0
source

All Articles