Defining a filled circle using CV2 in Python?

I am trying to detect all circles in images like this.

I have many different images like this, but in all circles there will be black (or almost black) and the same size (+/- a pair of pixels). I believe that in every image there are exactly 2,943 circles. These conditions never change. Perhaps I can not control the size of the circles in the images (usually they are from 15 to 45 pixels in radius). The above sample image has radii of 20-21 pixels.

I need to be able to accurately and accurately determine the exact location of the centers of these circles (if possible, the radii too).

I tried to use the function cv2.HoughCirclesto do this, but got very inconsistent and unreliable results. Here is the code I used:

from pylab import *
import sys, cv2

filename = sys.argv[1];
img = cv2.imread(filename,0);
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR);
circles = cv2.HoughCircles(img,cv2.cv.CV_HOUGH_GRADIENT,2,15,param1=100,param2=30,minRadius=15,maxRadius=25);
circles = np.uint16(np.around(circles));
for i in circles[0,:]:
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),1);
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3);
cv2.imwrite('1-%s'%(filename),cimg)
print "%d circles found."%(len(circles[0]));

The result is this image and this result:2806 circles found.

There are many false circles, and many of the true circles have been skipped / ignored.

I'm starting to believe that a method is HoughCirclenot the best way to go if all my circles are identical in the same image, and there might be some better method of detecting an object.

What do you suggest that I use to determine each circle accurately and precisely on thousands of images if I can control the properties of the circles quite strongly?

+3
source share
1 answer

, , , 2943 , , . , (, ):

Crop of the resulting image

, ( ).

, .

import cv2
import numpy as np

original = cv2.imread("test.jpg", cv2.CV_LOAD_IMAGE_GRAYSCALE)
retval, image = cv2.threshold(original, 50, 255, cv2.cv.CV_THRESH_BINARY)

el = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
image = cv2.dilate(image, el, iterations=6)

cv2.imwrite("dilated.png", image)

contours, hierarchy = cv2.findContours(
    image,
    cv2.cv.CV_RETR_LIST,
    cv2.cv.CV_CHAIN_APPROX_SIMPLE
)

drawing = cv2.imread("test.jpg")

centers = []
radii = []
for contour in contours:
    area = cv2.contourArea(contour)

    # there is one contour that contains all others, filter it out
    if area > 500:
        continue

    br = cv2.boundingRect(contour)
    radii.append(br[2])

    m = cv2.moments(contour)
    center = (int(m['m10'] / m['m00']), int(m['m01'] / m['m00']))
    centers.append(center)

print("There are {} circles".format(len(centers)))

radius = int(np.average(radii)) + 5

for center in centers:
    cv2.circle(drawing, center, 3, (255, 0, 0), -1)
    cv2.circle(drawing, center, radius, (0, 255, 0), 1)

cv2.imwrite("drawing.png", drawing)

,

+5

All Articles