【问题标题】:How to improve accuracy of CV2's HoughCircles如何提高 CV2 的 HoughCircles 的准确性
【发布时间】:2026-01-27 05:35:01
【问题描述】:

为了学习新知识,我一直在涉足 OpenCV,我提议自己做的一个项目(如朋友建议的那样)是在抗菌谱敏感性测试中确定药丸产生的圆圈的直径. An example of one can be found here. 在寻找实现这一点的方法时,我发现了 CV2 的 HoughCircles 的存在,所以我开始了一段漫长的阅读之旅,同时也只是通过反复试验来获得某种体面的结果。到目前为止,我想说我对函数的工作原理有了“体面”的了解,但是,我绝对不知道如何充分利用它。

输入我目前的代码:

import numpy
import cv2

image = cv2.imread("antibiograma.png")
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.blur(gray, (20,30), cv2.BORDER_DEFAULT)
height, width = blur.shape[:2]

minR = round(width/65)
maxR = round(width/11)
minDis = round(width/7)

circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.3, minDis, param1=23, param2=72, minRadius=minR, maxRadius=maxR)

if circles is not None:
    circles = numpy.round(circles[0, :]).astype("int")
    for (x, y, r) in circles:
        cv2.circle(output, (x, y), r, (0, 255, 0), 2)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("result", numpy.hstack([image, output]))
cv2.waitKey()

其中大部分是从我在试图了解它的工作原理时查找的一些资源中复制的,大多数参数都经过修改以更好地适应我正在使用的图像。

结果……不是很好。它似乎标记了圆圈的大致位置,but not very accurately。大多数圆圈都有一些令人讨厌的偏移,比它们应该的要大一些,特别是有一个(最左边的)几乎完全错误。更不用说这些数字中的一些(尤其是 dp 和 param2)也可能是 ma​​gic numbers,我对此不太满意,而且我很确定我的代码将会消亡当我决定将其应用于不同的抗菌谱敏感性测试时写道(我必须添加,我打算这样做)。

编辑:我还决定对图像进行一些调整并应用以下变换:

im4 = 255.0 * (im/255.0)**2

获取 MatPlotLib 生成的图形并通过 HoughCircles 运行(使用不同的参数):

circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 2.3, minDis, param1=1250, param2=50, maxRadius=maxR)

Which gave me this result。然而,更准确的说法是,除了忽略最左边的药丸之外,还会出现幻数问题。

所以,归结为两件事:

  1. 如何更好地提高函数的准确性?
  2. 如何确定一组适用于多张图片的参数?

如果这些看起来很愚蠢和基本,我深表歉意,我对整个事情还很陌生,所以我很感激任何帮助。

干杯!

【问题讨论】:

  • 抛弃霍夫,因为你的圈子可能不是非常圆。你可以试试SimpleBlobDetector
  • 我会尝试一下,但是,在我沉浸在该函数的文档中之前,它是否返回了足够的信息来确定斑点的直径?我猜是的,但我不妨问问。
  • 我对其结果的回忆很模糊。它返回一些“大小”的度量,但我从未检查过它是否对应于以像素为单位的区域,或直径,或其他任何东西。有一些在线使用示例(learnopencv.com 是一个可靠的站点,当然还有 docs.opencv.org)

标签: python opencv geometry hough-transform


【解决方案1】:

对于 OpenCV 开箱即用的算法结果,该测试示例实际上看起来不错。总有改进的余地。

这是我能够做到的:

import numpy
import cv2

image = cv2.imread("bact.png")
output = image.copy()

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

hist = cv2.equalizeHist(gray)

blur = cv2.GaussianBlur(hist, (31,31), cv2.BORDER_DEFAULT)
height, width = blur.shape[:2]

minR = round(width/65)
maxR = round(width/11)
minDis = round(width/7)

circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 1, minDis, param1=14, param2=25, minRadius=minR, maxRadius=maxR)

if circles is not None:
    circles = numpy.round(circles[0, :]).astype("int")
    for (x, y, r) in circles:
        cv2.circle(output, (x, y), r, (0, 255, 0), 2)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("result", numpy.hstack([image, output]))
cv2.waitKey()

我能想到的一些建议可以帮助改进或找到更好的参数:

  1. 将模糊图像传递给HoughCircles 函数。目前,您传递的是图像的灰度版本,而不是模糊的。

  2. 模糊大小和类型。 Blurrier images can help downstream algorithms。对于内核,大小也往往是相同的形状,例如 (20,20),使用 (20,30) 可能会产生不同的结果。

  3. Consider contrast correction 类似于 equalizeHist 或 CLAHE - 它可以帮助对对比度低或边缘褪色的图像进行边缘检测。

  4. Magic numbers.According to the docs,param2 可以变大以消除误报,因此请尝试一下。至于 param1 和 dp,您可能需要置换一些组合,看看哪种组合效果最好。如果您进入比较具有不同照明条件的多个图像集的世界,您可能必须首先考虑对图像进行归一化。幻数似乎是开箱即用算法的重要组成部分,因此找到有效方法的最佳方法是一次性排列输入和输出图像以查看有效方法,然后进行微调。

祝您在与生物学相关的 OpenCV 之旅中好运 :)

【讨论】:

  • 天哪,我从来没有意识到我仍然在通过灰度版本而不是模糊版本。非常感谢您的回答!真的很有用。