使用houghCircles检测小圆圈(OpenCV)

时间:2017-05-08 15:50:35

标签: python opencv image-processing hough-transform

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

这是结果图片: enter image description here

这是我的代码:

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

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

2 个答案:

答案 0 :(得分:5)

如果您尝试更改参数而不了解它们的作用,则需要很长时间才能解决此问题。

此说明来自here

  

minDist :检测到的圆圈的中心(x,y)坐标之间的最小距离。如果minDist太小,那么多个圆圈   可以(错误地)检测到与原始相同的邻域。如果   minDist太大,可能根本检测不到一些圆圈。

     

param1 :用于处理Yuen等人的边缘检测的梯度值。方法

     

param2 :cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,圆圈越多   检测到(包括假圆圈)。阈值越大,   可能会返回更多圈子。

     

minRadius :半径的最小尺寸(以像素为单位)。

     

maxRadius :半径的最大尺寸(以像素为单位)。

您可以清楚地看到图像中的圆圈具有固定的半径并且具有将它们分开的最小距离。如果设置这两个,则可以改善结果。所以阅读文档非常重要。

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

如果没有必要使用霍夫圈,我建议你改用轮廓。因为它更健壮,并且可以很好地适用于不同的图像。这是我使用轮廓的结果。圆圈看起来更小,因为我已经使用了6次迭代的侵蚀和仅3次迭代的扩张。

finding circles using contours

这是我使用的代码。

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)

希望这有帮助:)

答案 1 :(得分: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]