如何在Python中访问OpenCV的HoughCircles结果?

3 投票
3 回答
6052 浏览
提问于 2025-04-17 04:27

我正在开发一个与虹膜相关的生物识别算法的概念验证。我想在一系列图像上测试这个算法,但为了做到这一点,我需要知道虹膜的边界。根据这里的方法,我对图像进行了过滤和智能阈值处理(使用了Otsu的方法),这样我就只剩下了黑色的瞳孔圆圈。我尝试使用OpenCV的HoughCircles方法,但关于非C(++)的文档很少。以下是我目前在这一部分的代码:

# Convert PIL to openCV type
cvImage = cv.CreateImageHeader(inputImage.size, cv.IPL_DEPTH_8U, 1)
cv.SetData(cvImage, inputImage.tostring())

self.cvSize = cv.GetSize(cvImage)

# Create storage for circles (there should only be one)
storage = cv.CreateMat(50, 1, cv.CV_32FC3)

# Get circles (why doesn't this work?)
circles = cv.HoughCircles(cvImage,storage,cv.CV_HOUGH_GRADIENT,2,(self.cvSize[0])/4,200,100);

最后一行是我想问的地方。我在网上找了好几篇帖子(大多数是关于C/C++的,或者是5年以上的旧帖子),最终写出了这一行。它没有返回任何错误。那么我该如何访问结果呢?我应该访问circles还是storage?我该怎么访问它们?我试过这个问题中的建议,但正如提问者所说,cvMat类型是不可迭代的,所以这行不通。看起来写我自己的圆形霍夫变换会比处理这个库稀少的文档要简单,但我觉得我可能遗漏了一些简单的东西。

顺便问一下,我该如何优化参数,以便在合理的时间内总是返回一个适合瞳孔的圆?

3 个回答

2

一些解决方案:

grayImage = cv2.cvtColor(circleImage, cv.CV_BGR2GRAY)
circles = cv2.HoughCircles(grayImage, cv.CV_HOUGH_GRADIENT, 2, 80, None, 100, 100, 50, 150)

还有:

all_circles = circles[0]
    for circle in all_circles:
        #circle[0] - x
        #circle[1] - y
        #circle[2] - radius
2

你在用 OpenCV 2.3.x 吗?它的说明文档好像建议你可以这样做:

circles = cv2.HoughCircles(circleImage, cv.CV_HOUGH_GRADIENT, 2, 32, 200, 100);
for (x, y, radius) in circles:
    # do something with circle

注意: cv.HoughCircles 可能没有返回任何圆(这可能是因为参数设置太严格),所以你可以检查一下 circles 是否为空。

这里

希望这能帮到你!

3

这里提到的 cv.HoughLines2 的例子完全不同,因为它的内存存储方式是这样的:

storage2 = cv.CreateMemStorage(0)

HoughCircles 可不行。HoughCircles 只能处理 cvMat 类型的存储,比如:

storage = cv.CreateMat(image.width, 1, cv.CV_32FC3)

需要注意的是,它只能有一行,并且表示方式应该是32位浮点数,且有3个通道。

比如,你有以下这行代码:

circles=cv.HoughCircles(image,storage, cv.CV_HOUGH_GRADIENT, 100, 300,100,50)

由于使用了 cvMat,这个函数的返回值是 NULL,在Python中这意味着没有返回值(在C语言中也是一样,当存储是 cvMat 时没有返回)。

这意味着,唯一的输出就是存储的内容。你可以用numpy来解码这个结构:

np.asarray(storage)

这是我用来绘制圆圈的代码,圆心和半径是 HoughCircles 的结果。

for i in range(0,len(np.asarray(storage))):
        cv.Circle(image, ( int(np.asarray(storage)[i][0][0]), int(np.asarray(storage)[i][0][1]) ), int(np.asarray(storage)[i][0][2]), cv.CV_RGB(255, 0, 0), 2, 8, 0 )

不过我还有一个问题没解决:圆心的X、Y坐标和半径完全不准确,我不知道哪里出了问题,也许你能找到答案。

撰写回答