opencv 十一 霍夫圆检测原理及高级使用案例(含优化步骤)

霍夫圆检测能检测出目标图像中存在的圆,但在实际使用中,参数调节存在很大的困难,故在本博文中对霍夫圆检测的原理、参数列表、优化经验进行分析总结。详细的列出了各个参数的调节依据,实现了在复杂背景下的霍夫圆检测。

1. 原理介绍

1.1 基本原理

相关知识:
霍夫圆检测与霍夫变换密切相关,霍夫变换是基于极坐标系(是由半径与夹角所描述的一种坐标系)与笛卡尔坐标系(普通的平面坐标系)的相互转变而实现的。笛卡尔坐标系上的一个点,变换到极坐标系上就变成了一条线;反之亦然。
在这里插入图片描述

然而,基于霍夫变换的霍夫圆检测方法计算量极大,不适合实际应用。在opencv的实现中,是使用霍夫梯度算法进行圆检测。
参考链接:https://www.cnblogs.com/bjxqmy/p/12333022.html

1.2 霍夫梯度法的原理

1.把原图做一次 Canny 边缘检测,得到边缘检测的二值图。
2.对原始图像执行一次 Sobel 算子,计算出所有像素的邻域梯度值。
3.初始化圆心空间 N(a,b),令所有的 N(a,b)=0。若要求圆心在图像中,则a,b值的范围分别对应图像的宽高,N(a,b)表示一共有a*b个。
4.遍历 Canny 边缘二值图中的所有非零像素点,沿着梯度方向 (切线的垂直方向,根据Sobel 算子计算出的垂直梯度及水平梯度得来)固定搜索半径范围画线,将线段经过的所有累加器中的点 (a,b) 的 N(a,b)+=1。
在这里插入图片描述

5.统计排序 N(a,b),得到可能的圆心(N(a,b) 越大,越有可能是圆心)。
在这里插入图片描述
参考链接:https://zhuanlan.zhihu.com/p/427270299

1.3 霍夫梯度法缺点

1.在霍夫梯度法中,使用 Sobel 导数来计算局部梯度,那么随之而来的假设是,其可以视作等同于一条基于几个局部点的切线,并这个不是一个数值稳定的做法。在大多数情况下,这样做会得到正确的结果,但或许会在输出中产生一些噪声。

2.在边缘图像中的整个非0像素集被看做每个中心的候选部分,若没有合理设置梯度方向的搜索半径范围,则会导致计算量巨大。

3.因为霍夫梯度算法通过圆弧切线的垂直线进行圆心累加检测,当存在同心圆时,会累加到同一个圆心,这导致只会选择到累加值最大的圆。

1.4 参数详情

霍夫圆检测的使用代码如下

method=cv2.HOUGH_GRADIENT
circles=cv2.HoughCircles(image, method, dp=1, minDist=10, param1=None, param2=None, minRadius=None, maxRadius=None)

其参数列表详情如下:

Circles:用来存储HoughCircles的结果,类型为list,list中对象格式为x,y,r;
image:输入图像,即源图像,8位单通道图像,如果使用彩色图像,需要先转换成灰度图像;
method:定义检测图像中圆的方法。目前唯一实现的方法是cv2.HOUGH_GRADIENT;
dp:图像像素分辨率与参数空间分辨率的比值(官方文档上写的是图像分辨率与累加器分辨率的比值,它把参数空间认为是一个累加器,毕竟里面存储的都是经过的像素点的数量),dp=1,则参数空间与图像像素空间(分辨率)一样大,dp=2,参数空间的分辨率只有像素空间的一半大;#通过设置dp可以减少计算量
minDist:检测到的圆中心(x,y)坐标之间的最小距离。如果minDist太小,则会保留大部分圆心相近的圆。如果minDist太大,则会将圆心相近的圆进行合并(若两圆心距离 < minDist,则认为是同一个圆)。
param1:canny 边缘检测的高阈值,低阈值被自动置为高阈值的一半,默认为 100。;
param2:累加平面某点是否是圆心的判定阈值。大于该阈值才判断为圆。当值设置的很小是,检测到的圆越多。默认值为 100;
minRadius:半径的最小大小(以像素为单位)默认为 0;
maxRadius:半径的最大大小(以像素为单位)默认为 0。

2. 实际应用

2.1 基本运行代码

以下代码,实现了读取图像进行霍夫圆检测,试图检测出下图车辆中的车轮。但其参数设置有待调整优化。

import cv2
import numpy as np
import time
if __name__ == "__main__":
    name="test.jpg"
    img = cv2.imread(name)
    t1=time.time()
    GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, 40, param1=70, param2=30, minRadius=0,maxRadius=0)
    t2=time.time()
    print("运行时间:",t2-t1)

    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        x,y,r=i[0],i[1],i[2]
        #draw the outer circle
        cv2.circle(img,(x,y),r,(0,255,0),2)
        cv2.circle(img,(x,y),2,(0,0,255),3)
    cv2.imshow("img",img)
    cv2.waitKey()

原始图像内容如下:
请添加图片描述

2.2 优化方案

在运行以上代码时,因计算量巨大,电脑直接卡死。(原因1:图像缺乏处理优化、原因2:霍夫圆参数不合理、)

2.2.1 图像优化

图像优化是为了减少霍夫圆检测过程中的干扰点,因为3个点就可以构成一个圆。

边缘噪声滤除

1、对图像进行中值|均值滤波优化,减少图像中存在的边缘噪声。
所增加的代码如下,在16s内终于出了结果

    #GrayImage= cv2.medianBlur(GrayImage,7)#中值滤波 滤除背景噪声
    GrayImage= cv2.blur(GrayImage,(7,7))#均值滤波 滤除背景噪声

在这里插入图片描述

计算量削减

2、对图像size进行优化,因为进行霍夫圆检测时,图像size对检测精度影响不大。但对图像进行下采样(缩小后)可以大幅度减少计算量。
所增加的代码如下,在0.76s内出了结果,但也不是很准。若缩放到0.25倍,则可在0.06秒内跑出结果

    GrayImage=cv2.resize(GrayImage,None,fx=0.5,fy=0.5)

在这里插入图片描述

正圆保持

此步骤非必须。
在某些特殊情况,如钢卷的圆心检测,由于重力作用,钢卷的侧面圆被压成了椭圆,需要对其y方向(垂直方向)进行拉伸。如以下代码,将图像在y方向拉伸了1.2倍,此时钢卷的侧面椭圆被拉伸成了正圆。
img=cv2.resize(img,None,fx=1,fy=1.2)

2.2.2 检测参数优化

检索半径优化

通过对上图分析,发现检测到的圆太多了,且初步预估车轮的像素半径范围为20-80(通过多次设置范围,确定车轮像素在20~80之间)。
此时的霍夫圆检测参数如下:minRadius=20,maxRadius=80

circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=40, param1=70, param2=30, minRadius=20,maxRadius=80)

此时检测效果如下,代码仅在0.03秒内跑出结果(比原先快了20倍),因此限定了霍夫圆检索半径。
在这里插入图片描述

圆心累加优化

经过上个步骤优化后,仍有实际中不存在的圆被检测出来。这是因为累加圆心(圆弧上的在圆心上的累加值,累加值超过该阈值则被认为是一个圆)设置不合理所导致的。
此时的霍夫圆检测参数如下:param2=50, minRadius=20,maxRadius=80

circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=4, param1=70, param2=50, minRadius=20,maxRadius=80)

此时检测效果如下,仅在0.03秒内跑出结果(跟上一步骤相同),因此限定了霍夫圆检索半径
在这里插入图片描述

圆心距离优化

通过上述步骤后,发现针对某些圆会检测出多个圆心距离很近的圆。原先的圆心距设置很合理,但为了出优化效果,故将上一步的圆心距离设置的很小。这是由于检测步骤中的最小圆心距离设置不合理所导致的。
此时的霍夫圆检测参数如下:minDist=20, param2=50, minRadius=20,maxRadius=80
此时检测效果如下,已经能较好的定位到车轮区域。
在这里插入图片描述

最优完整代码

额外说明:若对检测到的圆效果存在疑惑时,可以自行对原图进行cany求边缘,以校验参数param1设置的是否合理,既根据cany运算的效果来调整param1的值(其为canny 边缘检测的高阈值),通常该值不需要进行调整,因为该值对效果影响不大。

import cv2
import numpy as np
import time
if __name__ == "__main__":
    name="test.jpg"
    img = cv2.imread(name)
    t1=time.time()
    img=cv2.resize(img,None,fx=0.5,fy=0.5)
    GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #GrayImage= cv2.medianBlur(GrayImage,7)#中值滤波 滤除背景噪声
    GrayImage= cv2.blur(GrayImage,(7,7))#均值滤波 滤除背景噪声
    circles = cv2.HoughCircles(GrayImage, cv2.HOUGH_GRADIENT, 1, minDist=20, param1=70, param2=50, minRadius=20,maxRadius=80)
    t2=time.time()
    print("运行时间:",t2-t1)#只统计霍夫圆检测时间
	
	#这里进行圆绘制
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        x,y,r=i[0],i[1],i[2]
        #draw the outer circle
        cv2.circle(img,(x,y),r,(0,255,0),2)
        cv2.circle(img,(x,y),2,(0,0,255),3)
    cv2.imshow("img1",img)
    cv2.waitKey()
  • 21
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
霍夫圆检测是一种用于检测图像中圆形的算法。在OpenCV中,霍夫圆检测是基于图像梯度的实现。具体原理如下: 1. 首先,对图像进行中值滤波,以减少噪声的影响\[1\]。 2. 接下来,通过检测边缘来发现可能的圆心。这一步使用图像梯度的方法来计算边缘\[1\]。 3. 在第一步的基础上,从候选圆心开始计算最佳半径大小。这一步使用霍夫变换的方法来确定圆的半径\[1\]。 在OpenCV中,可以使用cv::HoughCircles函数来实现霍夫圆检测。该函数的参数包括输入图像、输出结果、方法、尺度因子、最短距离、Canny边缘检测的低阈值、中心点累加器阈值、最小半径和最大半径\[3\]。 总结来说,霍夫圆检测通过对图像进行中值滤波和边缘检测,然后使用霍夫变换来确定圆的位置和半径。这种方法可以有效地检测图像中的圆形物体。 #### 引用[.reference_title] - *1* [OpenCvSharp 学习笔记21-- 霍夫变换 - 圆检测 (Hough Circle transform)](https://blog.csdn.net/weixin_41049188/article/details/92422241)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [OpenCV 霍夫圆检测](https://blog.csdn.net/qq_44989881/article/details/116135750)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [OpenCV20---霍夫圆检测](https://blog.csdn.net/qq_45646174/article/details/105086711)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼的机器猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值