圆形霍夫变换错过了圆圈 [英] Circular Hough Transform misses circles

查看:150
本文介绍了圆形霍夫变换错过了圆圈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've read a lot about the Circular Hough transform on Stack Overflow, but I seem to be missing something. I wrote a program that is supposed to detect the circles of a "Bull's Eye" target. However, even after playing with the parameters, the algorithm is quite bad - it ignores most of the circles and one time it finds a circle but seems to "wander off". I've even tried applying an "Unsharp Mask" to no avail. I have added my code, the image I started with and the output. I hope someone can point me at the right direction.

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检测圆圈,然后绘制靠近中心的圆圈(我发现其他圆圈是假圆圈)。

Quick explanation: I load the image, apply Unsharp Mask, use the Hough Transfrom to detect circles, then draw the circles that are close to the center (I found that the other circles are false circles).

我试过玩参数,这是我得到的最好的。我觉得这是一个足够简单的问题,让我得以缓解。我欢迎任何帮助。

I tried playing with the parameters, and this is the best I got. I feel like this is a simple enough problem which has me buffled. I appriciate any help.

我的输入图片:

我的输出图片:

推荐答案

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

As I mentioned in my comment, you'll need to run successive iterations of cv2.HoughCircles for different range of radii to ensure that you get all of the circles. With the way the Circular Hough Transform works, specifying a minimum and maximum radius that has quite a large range will be inaccurate and will also be slow. They don't tell you this in the documentation, but for the Circular Hough Transform to work successfully, the following two things need to be valid:

maxRadius < 3*minRadius
maxRadius - minRadius < 100

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

With the above, blindly making the minimum radius very small and the maximum radius very large won't give you great results. Therefore, what you could do is start at... say...radius=1, then iterate up to radius=300 in steps of 20. Between each chunk of 20, run cv2.HoughCircles and update your image with these contours.

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

Doing this requires very little modification to your code. BTW, I removed the unsharp masking it because I was getting poor results with it. I also changed a couple of parameters in cv2.HoughCircles slightly to get this to work as best as possible given your situation:

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

我得到这个数字:

< img src =https://i.stack.imgur.com/GQzDU.pngalt =在此输入图像说明>

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

Unfortunately it isn't perfect as it doesn't detect all of the circles. You'll have to play around with the cv2.HoughCircles function until you get good results.

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

However, I wouldn't recommend using cv2.HoughCircles here. May I suggest using cv2.findContours instead? This finds all of the contours in the image. In this case, these will be the black circles. However, you need to reverse the image because cv2.findContours assumes non-zero pixels are object pixels, so we can subtract 255 from the image assuming a np.uint8 type:

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

这就是我得到的:

这篇关于圆形霍夫变换错过了圆圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆