圆形霍夫变换错过了圆圈

时间:2015-08-29 14:18:37

标签: python opencv image-processing hough-transform

我已经阅读了很多关于Stack Overflow上的Circular Hough变换的内容,但我似乎错过了一些东西。我写了一个程序,该程序应该能够检测到公牛眼中的圆圈"目标。然而,即使在使用参数之后,算法也非常糟糕 - 它忽略了大多数圆圈,有一次它找到了一个圆圈,但似乎“徘徊”#34;。我甚至试过使用"钝化面膜"无济于事。我添加了我的代码,我开始使用的图像和输出。我希望有人能指出我正确的方向。

import cv2
import cv2.cv as cv
import numpy as np
import math
# Load Image
img = cv2.imread('circles1.png',0)
# Apply Unsharp Mask
tmp = cv2.medianBlur(img,5)
img = cv2.addWeighted(img,1.5,tmp,-0.5,0)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

# Hough Transform
circles = cv2.HoughCircles(img,cv.CV_HOUGH_GRADIENT,1,5,
                            param1=100,param2=100,minRadius=0,maxRadius=0)

circles = np.uint16(np.around(circles))

# Go over circles, eliminating the ones that are not cocentric enough
height, width = img.shape
center = (width/2,height/2)
for i in circles[0,:]:
    # draw the outer circle
    if math.sqrt((center[0]-i[0])**2 + (center[1]-i[1])**2) < 15:
        cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),1)
        # draw the center of the circle
        cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.imshow('detected circles',cimg)

cv2.waitKey(0)
cv2.destroyAllWindows()

快速解释:我加载图像,应用USM锐化,使用Hough Transfrom检测圆圈,然后绘制靠近中心的圆圈(我发现其他圆圈是假圆圈)。

我试着玩参数,这是我得到的最好的。我觉得这是一个足够简单的问题,让我得以缓解。我赞不绝口。

我的输入图片:

Input image

我的输出图片:

Output image

1 个答案:

答案 0 :(得分:5)

正如我在评论中提到的,您需要针对不同的半径范围运行cv2.HoughCircles的连续迭代,以确保获得所有圆圈。通过循环霍夫变换的工作方式,指定具有相当大范围的最小和最大半径将是不准确的并且也将是慢的。他们没有在文档中告诉你,但是为了使Circular Hough Transform能够成功运行,以下两件事需要有效:

maxRadius < 3*minRadius
maxRadius - minRadius < 100

有了上述内容,盲目地使最小半径非常小,最大半径非常大,不会给你带来很好的效果。因此,你可以做的是从...说... radius=1,然后以20为步骤迭代到radius=300。在每个20块之间,运行cv2.HoughCircles并更新这些轮廓的图像。

这样做只需要对代码进行很少的修改。顺便说一句,我删除了不清晰的掩盖它,因为我的结果很糟糕。我还稍微更改了cv2.HoughCircles中的几个参数,以便根据您的情况尽可能地使其工作:

import cv2
import cv2.cv as cv
import numpy as np
import math
# Load Image
img = cv2.imread('circles1.png',0)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

# Specify different radii
radii = np.arange(0,310,10)

# For each pair of radii...
for idx in range(len(radii)-1):
    # Get the minimum and maximum radius
    # Note you need to add 1 to each minimum
    # as the maximum of the previous pair covers this new minimum
    minRadius = radii[idx]+1
    maxRadius = radii[idx+1]

    # Hough Transform - Change here
    circles = cv2.HoughCircles(img,cv.CV_HOUGH_GRADIENT,1,5,
                               param1=25,param2=75,minRadius=minRadius,maxRadius=maxRadius)

    # Skip if no circles are detected - Change here
    if circles is None:
        continue

    circles = np.uint16(np.around(circles))

    # Go over circles, eliminating the ones that are not cocentric enough
    height, width = img.shape
    center = (width/2,height/2)
    for i in circles[0,:]:
        # draw the outer circle
        if math.sqrt((center[0]-i[0])**2 + (center[1]-i[1])**2) < 15:
            cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),1)
            # draw the center of the circle
            cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.imshow('detected circles',cimg)

cv2.waitKey(0)
cv2.destroyAllWindows()

我得到这个数字:

enter image description here

不幸的是,它并不完美,因为它没有检测到所有的圆圈。您必须使用cv2.HoughCircles函数,直到获得良好的结果。

但是,我不建议在这里使用cv2.HoughCircles。我建议您使用cv2.findContours吗?这可以找到图像中的所有轮廓。在这种情况下,这些将是黑色圆圈。但是,您需要反转图像,因为cv2.findContours假定非零像素是对象像素,因此我们可以假设np.uint8类型从图像中减去255:

# Make copy of original image
cimg2 = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# Find contours
contours,_ = cv2.findContours(255 - img, cv2.RETR_LIST, cv.CV_CHAIN_APPROX_NONE)

# Draw all detected contours on image in green with a thickness of 1 pixel
cv2.drawContours(cimg2, contours, -1, color=(0,255,0), thickness=1)

# Show the image
cv2.imshow('detected circles', cimg2)
cv2.waitKey(0)
cv2.destroyAllWindows()

这就是我得到的:

enter image description here

相关问题