如何在含噪声图像中通过OpenCV HoughCircles准确检测圆形
OpenCV HoughCircles 检测不准的优化方案
预处理流程修正
你当前的预处理逻辑有明显问题,直接调整:
- 高斯模糊不要放在直方图均衡化后面,先模糊压噪声再做均衡化,不然均衡化会把噪声一起放大,直接干扰霍夫圆依赖的边缘检测结果。针对半径50-60像素的目标,模糊核用
(7,7)、sigma取1.5-2就够,核太大会把圆边缘糊没。 - 检测结果不要画在均衡化后的图上,均衡化会改变原图灰度,可视化校验的时候在裁剪后的原图上画,避免判断失误。
- 正式跑检测前,先用
cv2.Canny对预处理后的图提一次边缘,确认目标圆的边缘是连续、没有被噪声打断的,要是边缘都碎成一段段的,先调预处理参数,别着急改霍夫圆的参数。
参数修正(针对你当前的检测目标)
你现在用的参数错了好几个,按下面的逻辑改:
minDist=6完全不合理:这个参数是两个有效圆心之间的最小间隔,你的目标圆半径都到50-60了,设6会导致同一个圆周围冒出一堆重复的假检测结果,直接改成70左右,和你设的最小半径匹配就行。param2=200太高:这个是霍夫空间的累加器阈值,值越高要求构成圆的边缘点投票数越多才会被判定为有效圆,200的阈值对于边缘不是绝对锐利的实际图像太容易漏检,先从30开始往上加,每次加5,直到假圆消失就停,一般这类图40左右就够用。param1=150偏高:这个是内部调用Canny边缘检测的高阈值,低阈值默认是它的一半,150会把圆上的弱边缘直接滤掉,导致投票数不够漏检,降到70-90区间试。dp=1.1问题不大,追求精度就设成1,想提速可以升到1.5。- 半径范围别拍脑袋设,先手动在图上量一下目标圆的实际像素半径,上下留3-5像素余量就行,范围设太宽很容易把背景里的类圆结构误检出来。
改完的参考代码:
# 预处理顺序调整:先裁剪 -> 高斯模糊 -> 直方图均衡化 blur = cv2.GaussianBlur(cropped_original_img, (7, 7), 1.8) eq = cv2.equalizeHist(blur) detected_circles = cv2.HoughCircles( eq, cv2.HOUGH_GRADIENT, dp=1, minDist=70, param1=80, param2=40, minRadius=48, maxRadius=62 ) # 结果画在原图副本上 show_img = cropped_original_img.copy() if detected_circles is not None: detected_circles = np.uint16(np.around(detected_circles)) for pt in detected_circles[0, :]: x, y, r = pt # 画圆轮廓 cv2.circle(show_img, (x, y), r, (0, 255, 0), 2) # 画圆心方便校验位置 cv2.circle(show_img, (x, y), 2, (255, 0, 0), 3) plt.rc('figure', figsize=(10, 10)) plt.imshow(show_img, cmap='gray') plt.show()
备选方案
如果霍夫圆调参始终达不到预期,可以换轮廓拟合的方案,抗噪声能力更强:
- 预处理后用大津法做二值化
- 用
cv2.findContours提取所有轮廓 - 对每个轮廓用
cv2.minEnclosingCircle做圆拟合 - 计算轮廓实际面积和拟合圆面积的比值,比值在0.85-1.15区间的判定为有效圆形目标。
内容的提问来源于stack exchange,提问作者Bernardo Cecchetto
相关产品推荐
相关产品推荐

