使用 houghCircles (OpenCV) 检测小圆圈

detecting small circles using houghCircles (OpenCV)

我正在尝试使用 houghcircles() 检测此裁剪图像中的小圆圈。我试图更改它的参数,但是当我将 param2 增加到 50 以上时它会出错,而当它的值小于 100 时 maxRadius 也会出错。现在它运行但性能不佳 这是原始图像:

这是结果图片:

这是我的代码:

from imutils.perspective import four_point_transform
from imutils import contours
import numpy as np
import argparse
import imutils
import cv2

im = cv2.imread('crop.png')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray, 200, 255,cv2.THRESH_BINARY)
cimg = cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR)

c = cv2.HoughCircles(thresh, cv2.HOUGH_GRADIENT, 0.5, 41, param1=70, 
param2=30, minRadius=10,maxRadius=175)
c = np.uint16(np.around(c))

for i in c[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.namedWindow('img',cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 800,800)
cv2.imshow('img',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

请问,我应该如何更改参数?

如果您在不了解参数的作用的情况下尝试改变参数,您将需要很长时间才能解决这个问题。

此描述来自here

minDist: Minimum distance between the center (x, y) coordinates of detected circles. If the minDist is too small, multiple circles in the same neighborhood as the original may be (falsely) detected. If the minDist is too large, then some circles may not be detected at all.

param1: Gradient value used to handle edge detection in the Yuen et al. method.

param2: Accumulator threshold value for the cv2.HOUGH_GRADIENT method. The smaller the threshold is, the more circles will be detected (including false circles). The larger the threshold is, the more circles will potentially be returned.

minRadius: Minimum size of the radius (in pixels).

maxRadius: Maximum size of the radius (in pixels).

您可以清楚地看到图像中的圆圈具有固定的半径,并且它们之间的距离最小。如果你设置这两个,你可以提高你的结果。所以阅读文档很重要。

关于您的问题,如果您有使用 Houghcircles 的特殊需要,请继续进行微调。您可以做的改进是,使用 gaussianblur 进行预处理,使用自适应阈值而不仅仅是阈值。

如果没有必要使用霍夫圆,我建议你使用等高线代替。因为它更健壮并且可以很好地泛化到不同的图像。这是我使用轮廓得到的结果。圆圈看起来更小,因为我使用了 6 次迭代的腐蚀和 3 次迭代的膨胀。

这是我使用的代码。

import numpy as np
import cv2

image_color= cv2.imread("Ye3gs.png")
image_ori = cv2.cvtColor(image_color,cv2.COLOR_BGR2GRAY)

lower_bound = np.array([0,0,10])
upper_bound = np.array([255,255,195])

image = image_color

mask = cv2.inRange(image_color, lower_bound, upper_bound)

# mask = cv2.adaptiveThreshold(image_ori,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
#             cv2.THRESH_BINARY_INV,33,2)

kernel = np.ones((3, 3), np.uint8)

#Use erosion and dilation combination to eliminate false positives. 
#In this case the text Q0X could be identified as circles but it is not.
mask = cv2.erode(mask, kernel, iterations=6)
mask = cv2.dilate(mask, kernel, iterations=3)

closing = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)[0]
contours.sort(key=lambda x:cv2.boundingRect(x)[0])

array = []
ii = 1
print len(contours)
for c in contours:
    (x,y),r = cv2.minEnclosingCircle(c)
    center = (int(x),int(y))
    r = int(r)
    if r >= 6 and r<=10:
        cv2.circle(image,center,r,(0,255,0),2)
        array.append(center)

cv2.imshow("preprocessed", image_color)
cv2.waitKey(0)

希望这对您有所帮助 :)

在 OpenCV 3 中,findContours 的签名已更改。 要返回轮廓,您需要更改此行:

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

至此

contours = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]