【opencv-python】霍夫圆检测

霍夫变换检测直线的原理是利用累加器找到最大的 ( ρ , θ ) (ρ,θ) (ρ,θ)数对,如文章所述。圆形的数学表达式为 ( x − x c e n t e r ) 2 + ( y − y c e n t e r ) 2 = r 2 (x-x_{center})^2+(y-y_{center})^2=r^2 (xxcenter)2+(yycenter)2=r2,其中 ( x c e n t e r , y c e n t e r ) (x_{center},y_{center}) xcenter,ycenter为圆心坐标, r r r为圆的直径。因此可知一个圆需要 x c e n t e r , y c e n t e r , r x_{center},y_{center},r xcenter,ycenter,r三个参数确定,如果采用霍夫直线相同的原理,则需要围绕被探测点对全域点进行搜索,进而获取可能的圆心坐标,然后再通过圆心坐标计算该点相对应的半径,构成 ( x c e n t e r , y c e n t e r , r ) (x_{center},y_{center},r) (xcenter,ycenter,r)数对,再利用累加方法对下一些像素点进行相同处操作,最后看哪个数对位置中的累加出的数值最大,即代表过这一簇点的圆。但是这种操作的计算量过大,效率比较低。于是H.K.YUEN等大神提出了一种优化算法,利用边缘点的梯度法向为路径进行圆心点搜索,可以大大缩小圆心点搜索范围,提高效率。

在opencv-python中,我们使用函数cv2.HoughCircles函数来解决圆识别问题,函数说明如下图所示:
在这里插入图片描述
每个参数的含义如下图所示:

  • image:8位待处理灰度图像;
  • circles:输出被检测到的圆,以三元素浮点型向量表示 ( x , y , r a d i u s ) (x,y,radius) (x,y,radius)
  • method:探测方法。当前的实现是用的CV_HOUGH_GRADIENT方法;
  • dp:累加器分辨率与图像分辨率的反比。例如,如果dp=1,累加器的分辨率与输入图像相同。如果dp=2,则累加器的宽度和高度为原来的一半;
  • minDist:检测到的圆中心之间的最小距离。如果参数太小,除了一个真实的圆外,还可能错误地检测到多个相邻圆,如果太大可能会错过一些圆;
  • param1:第一个特定参数。对于CV_HOUGH_GRADIENT方法,它是传递给Canny()边缘检测器的两个阈值中较高的阈值(较低的阈值小两倍);
  • param2:第二个特定参数。对于CV_HOUGH_GRADIENT方法,它是检测阶段圆心的累加器阈值。它越小,可能检测到的假圆越多(因为满足累加器上限的条件变多了)。与累加器最大数值结果代表的圆将被首先返回。
  • minRadius:最小圆半径;
  • maxRadius:最大圆半径。

基于上文所述,霍夫圆检测的效果进行测试,待处理原图如下图所示:
在这里插入图片描述
处理代码如下所示:

img = cv2.imread('singlecircle.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,minDist=20,param1=50,param2=30,minRadius=0,maxRadius=0)
print('circles1:', circles)
circles = np.uint16(np.around(circles))
print('circles2:', circles)

for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

运行结果如下:
在这里插入图片描述
此时我们发现程序显示了很多圆形,并非是我们想要的结果,此时我们调整霍夫变换函数的参数,调整“minDist=20”为“minDist=100”,之后程序的运行效果为:

在这里插入图片描述
肉眼可见效果明显好了很多。从函数功能定义来看,输出circle变量应该包含形如 ( x c e n t e r , y c e n t e r , r ) (x_{center},y_{center},r) (xcenter,ycenter,r)形式的数对,我们将circle变量内容打印出来,如下图所示:
在这里插入图片描述
此处,我们可以思考一下,为什么圆心坐标最后都是.5的形式呢?当然,我们也可以通过改变其他参数的形式去达到只识别一个圆的目的,比如我们将"param2=30"修改为"param2=100"效果如下:
在这里插入图片描述
对于多个圆,我们也可以通过cv2.HoughCircles()函数进行识别,被处理原图如下图所示:
在这里插入图片描述
程序运行结束后效果如下图所示:
在这里插入图片描述
可见效果比较明显,但还没有达到比较规整的效果,通过调整函数中的参数可以实现我们想要的识别效果。在参数中,dp参数值得深入分析,其与累加器分辨率成反比,如果dp=1,累加器属正常状态,如果dp=2,则按照2倍执行累加,所以dp值越大,累加器累加速度越快,因此在上限阈值以上的被检测圆数量也就越多。为了测试,我们将dp调整为2,其他参数保持不变,观察函数的执行效果:

在这里插入图片描述可见检测出来的圆多了好多。我们再看一个实例,如下图所示:
在这里插入图片描述
在这里插入图片描述
如果我想把这两张图片的圆孔对应中心对应位置匹配起来,我需要先对圆环进行检测并获取圆环中心位置,经过霍夫圆变换,程序执行效果如下图所示:
在这里插入图片描述

实现上述功能需要对霍夫圆变换函数参数进行精确调整,我所采用的参数如下所示:

circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1, minDist=30, param1=10,param2=20,minRadius=10,maxRadius=15)

整个图片的尺寸比较小,shape只有(217,309),所以最小圆心间距、最小半径等参数也要做合理适配。然后参数和图像之间的关联性较高,也就是说这一组参数如果适用于这张图像,很难适应其他图像,比如对同一目标的右视相机拍摄图像,如果还用这一组参数,识别效果如下图所示:
在这里插入图片描述
可见有些圆形是没法很好的识别出来,因此还是需要再对参数进行调优,更改参数如下:

circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1, minDist=25, param1=10,param2=20,minRadius=9,maxRadius=15)#LL

修改参数之后识别效果为:
在这里插入图片描述
欢迎大家在评论区留言评论,感谢大家的关注!
在这里插入图片描述

  • 11
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hunter206206

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

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

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

打赏作者

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

抵扣说明:

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

余额充值