【问题标题】:Detecting silver and reflecting balls with OpenCV使用 OpenCV 检测银球和反射球
【发布时间】:2026-01-30 02:00:02
【问题描述】:

我正在尝试使用 OpenCV 检测反映环境的银球:

用黑球,我通过检测圆圈成功做到了:

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

gray = cv2.GaussianBlur(gray,(5,5),0);
gray = cv2.medianBlur(gray,5)

gray = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,3.5)

kernel = np.ones((3,3),np.uint8)

gray = cv2.erode(gray,kernel,iterations = 1)

gray = cv2.dilate(gray,kernel,iterations = 1)

circles = cv2.HoughCircles(gray, cv.CV_HOUGH_GRADIENT, 1, 260, \
                    param1=30, param2=65, minRadius=0, maxRadius=0)

但是当使用带有银球的程序时,我们没有得到任何结果。

查看程序计算的边缘时,球的边缘非常锋利。但是代码没有识别任何球。

如何提高银球的检出率?我想到了两种方法: - 改进边缘计算 - 使圆形检测接受边缘不清晰的图像 那可能吗?这样做的最佳方式是什么?

非常感谢您的帮助。

【问题讨论】:

  • 如果您拥有的背景具有代表性,那么您可能需要尝试检测特定颜色,这将为您提供相当数量的球开始。 1. 转换为 HSV。为您的特定颜色范围使用 InRagnge
  • 您的参数是否匹配相同大小的合成圆?您是否尝试过其他边缘检测方法来获得更好的闭合轮廓? (minimal reproducible example)

标签: python opencv hough-transform


【解决方案1】:

您必须调整参数。 HoughCircles 函数在检测圆圈(即使有间隙)方面做得很好。请注意,HoughCircles 使用精明的边缘检测执行内部二值化。因此,您不必进行阈值处理。

鉴于您上面的图片,代码

import cv2
from matplotlib import pyplot as plt
import numpy as np

PATH = 'path/to/the/image.jpg'    

img = cv2.imread(PATH, cv2.IMREAD_GRAYSCALE)
plt.imshow(img, cmap='gray')
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 20, param1=130, param2=30, minRadius=0, maxRadius=0)
if circles is not None:
    for x, y, r in circles[0]:
        c = plt.Circle((x, y), r, fill=False, lw=3, ec='C1')
        plt.gca().add_patch(c)
plt.gcf().set_size_inches((12, 8))
plt.show()

产生结果

不同的参数是什么意思?

函数签名定义为

cv.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]])

imagecircles 是不言自明的,将被跳过。

方法

指定内部使用的霍夫算法的变体。如documentation 中所述,只有HOUGH_GRADIENT 支持atm。此方法利用21HT (p.2, THE 2-1 HOUGH TRANSFORM) 算法。此变体的主要优点在于减少内存使用。使用霍夫变换检测圆的标准方法需要在 3D 霍夫空间(x、y 和半径)中进行搜索。但是,使用 21HT,您的霍夫空间减少到只有 2 个维度,这大大降低了内存消耗。

dp

dp 参数设置逆累加器分辨率。可以在here 找到一个很好的解释。请注意,此解释使用标准霍夫变换作为示例。但是21HT的效果是一样的。 21HT 的累加器与标准 HT 的累加器略有不同。

minDist

只需指定圆心之间的最小距离。在上面的代码示例中,它设置为 20,这意味着两个检测到的圆的中心必须彼此相距至少 20 像素。我不确定opencv是如何过滤掉圆圈的,但是扫描源代码它看起来像匹配度较低的圆圈被丢弃了。

参数1

指定传递给Canny Edge 算法的阈值。基本上它被称为cv2.Canny(image, param1 / 2, param1)

参数2

这一段应该由更熟悉opencv源代码的人来验证。 param2 指定累加器阈值。这个值决定了一个圆必须如何完成才能算作一个有效的圆。我不确定参数是在哪个单位给出的。但是(再次扫描源代码)它看起来像是一个绝对投票阈值(意味着它直接受不同半径的影响)。 下图显示了不同的圆圈(或可以识别为圆圈的圆圈)。越往右走,阈值就越低才能检测到那个圆圈。

minRadius 和 maxRadius

仅将圆搜索限制在半径范围 [minRadius, maxRadius] 内。如果您可以近似(或知道)您正在搜索的圆圈的大小,这很有用(并且可以提高性能)。

【讨论】:

  • 您介意发布这些参数的文档链接吗? (或者更好:解释一下?)谢谢。
  • 你读过cv2.HoughCirclesofficial documentation吗?我想我们会在那里解释,但如果你不明白,我可以更详细地说明。
  • 如果你能更详细一点就好了,我想我没有完全理解文档。