OpenCV 中用于虹膜检测的 HoughCircles 的正确用法/参数值是什么?

问题描述

我一直在阅读有关该主题的文章,但无法以简单的英语"了解 HoughCircles 的用法和参数(特别是 CV_HOUGH_GRADIENT 之后的那些).

I've been reading about the subject but cannot get the idea in "plain English" about the usage and parameters for HoughCircles (specially the ones after CV_HOUGH_GRADIENT).

什么是累加器阈值?100票"是正确的值吗?

What's an accumulator threshold? Are 100 "votes" a right value?

我可以找到并掩盖"瞳孔,并通过 Canny 函数工作,但我正在努力超越,我的问题是 HoughCircles 函数.似乎无法找到 Iris 的圈子,我不知道为什么.

I could find and "mask" the pupil, and worked my way through the Canny function, but I'm struggling beyond that and my problem is the HoughCircles function. There seems to be failing at finding the Iris' circle and I don't know why.

这是我正在处理的功能:

And this is the function I'm working on:

def getRadius(area):
    r = 1.0
    r = math.sqrt(area/3.14)
    return (r)

def getIris(frame):
    grayImg = cv.CreateImage(cv.GetSize(frame), 8, 1)
    cv.CvtColor(frame,grayImg,cv.CV_BGR2GRAY)
    cv.Smooth(grayImg,grayImg,cv.CV_GAUSSIAN,9,9)
    cv.Canny(grayImg, grayImg, 32, 2)
    storage = cv.CreateMat(grayImg.width, 1, cv.CV_32FC3)
    minRad = int(getRadius(pupilArea))
    circles = cv.HoughCircles(grayImg, storage, cv.CV_HOUGH_GRADIENT, 2, 10,32,200,minRad, minRad*2)
    cv.ShowImage("output", grayImg)
    while circles:
        cv.DrawContours(frame, circles, (0,0,0), (0,0,0), 2)
        # this message is never shown, therefore I'm not detecting circles
        print "circle!"
        circles = circles.h_next()
    return (frame)


解决方案

HoughCircles 可能有点棘手,我建议查看 这个线程.包括我在内的一群人;),讨论如何使用它.关键参数是param2,即所谓的accumulator threshold.基本上,它越高,你得到的圈子就越少.而且这些圆圈有更高的正确概率.每个图像的最佳价值都不同.我认为最好的方法是在 param2 上使用参数搜索.IE.继续尝试值,直到满足您的条件(例如:有 2 个圆圈,或不重叠的最大圆圈数等).我有一些对param2"进行二进制搜索的代码,所以它很快就满足了条件.

HoughCircles can be kind of tricky, I suggest looking through this thread. Where a bunch of people, including me ;), discuss how to use it. The key parameter is param2, the so-called accumulator threshold. Basically, the higher it is the less circles you get. And these circles have a higher probability of being correct. The best value is different for every image. I think the best approach is to use a parameter search on param2. Ie. keep on trying values until your criteria is met (such as: there are 2 circles, or max. number of circles that are non-overlapping, etc.). I have some code that does a binary search on 'param2', so it meet the criteria quickly.

另一个关键因素是预处理,尽量减少噪点并简化图像.模糊/阈值/canny的某种组合对此有好处.

The other crucial factor is pre-processing, try to reduce noise, and simplify the image. Some combination of blurring/thresholding/canny is good for this.

无论如何,我明白了:

从您上传的图片中,使用以下代码:

From your uploded image, using this code:

import cv
import numpy as np

def draw_circles(storage, output):
    circles = np.asarray(storage)
    for circle in circles:
        Radius, x, y = int(circle[0][3]), int(circle[0][0]), int(circle[0][4])
        cv.Circle(output, (x, y), 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
        cv.Circle(output, (x, y), Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)    

orig = cv.LoadImage('eyez.png')
processed = cv.LoadImage('eyez.png',cv.CV_LOAD_IMAGE_GRAYSCALE)
storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)
#use canny, as HoughCircles seems to prefer ring like circles to filled ones.
cv.Canny(processed, processed, 5, 70, 3)
#smooth to reduce noise a bit more
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)

cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, 550)
draw_circles(storage, orig)

cv.ShowImage("original with circles", orig)
cv.WaitKey(0)

更新

我意识到我有点看错了你的问题!您实际上想要找到 iris 边缘.他们没有像学生那样明确定义.所以我们需要尽可能地帮助HoughCircles.我们可以这样做:

I realise I somewhat miss-read your question! You actually want to find the iris edges. They are not so clearly defined, as the pupils. So we need to help HoughCircles as much as possible. We can do this, by:

  1. 指定虹膜的大小范围(我们可以根据瞳孔大小计算出一个合理的范围).
  2. 增加圆心之间的最小距离(我们知道两个虹膜永远不会重叠,因此我们可以安全地将其设置为我们的最小虹膜尺寸)

然后我们需要再次对 param2 进行参数搜索.将上述代码中的HoughCircles"行替换为:

And then we need to do a param search on param2 again. Replacing the 'HoughCircles' line in the above code with this:

cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 100.0, 30, 150,100,140)

告诉我们这个:

这还不错.

相关文章