OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 128511|回复: 130

找圆算法((HoughCircles)总结与优化

  [复制链接]
发表于 2015-1-30 00:46:36 | 显示全部楼层 |阅读模式
本帖最后由 wawa 于 2016-4-19 20:40 编辑

    找圆算法((HoughCircles)总结与优化

    Opencv内部提供了一个基于Hough变换理论的找圆算法,HoughCircle与一般的拟合圆算法比起来,各有优势:优势:HoughCircle对噪声点不怎么敏感,并且可以在同一个图中找出多个圆;反观拟合圆算法,单纯的拟合结果容易受噪声点的影响,且不支持一个输入中找多个圆
缺点:原始的Hough变换找圆,计算量很大,而且如果对查找圆的半径不加控制,不但运算量巨大,而且精度也不足,在输入噪声点不多的情况下,找圆效果远不如拟合找圆;为了提高找圆精度,相比拟合法,需要提供更多的参数加以控制,参数要求比较严格,且总体稳定性不佳
    OpenCV内的HoughCircles对基础的Hough变换找圆做了一定的优化来提高速度,它不再是在参数空间画出一个完整的圆来进行投票,而只是计算轮廓点处的梯度向量,然后根据搜索的半径R在该梯度方向距离轮廓点距离R的两边各投一点,最后根据投票结果图确定圆心位置,其示意图如图1

理想情况

理想情况
图1是比较理想的情况,轮廓点1-6的梯度方向都经过了点7,因此都给点7投了一票,点7得分最高,也正是我们所要找的圆心;同时由此可以看出基于参数空间投票法来确定圆心,8-12点就算有投票,但由于投票太散,对整个投票结果也几乎不存在干扰,因而其天生抗干扰能力要比拟合法好
不过在这种思想优化下,也存在致命的缺陷,如图2:

实际情况

实际情况


实际情况是该点算出的梯度方向其实总是有误差的,有时因为图像原因或结构原因,偏差甚至超过30度;图2中由于梯度方向不精确,7点基本没有获得投票,反而不如ABC点。因此实际使用中HoughCircle的效果并没有想象中的理想,情况往往如下列所述:
(参与投票的轮廓点如图3的右图,噪点非常多,比想要查找的轮廓本身还多,而且断断续续的,显然这种情况拟合法不适用)
1、半径范围限定不好时,如图3,可能找到的圆非常多且杂乱无章
半径限制不好.jpg 轮廓图.jpg
2、在此情况下,如果只输出一个圆(Opencv的HoughCircle会默认按照投票结果的累加值排序,最好的圆是这样的,竟然差这么多

半径没限定默认最好圆

半径没限定默认最好圆


3、假设我们找的东西的半径我们是知道的,变化不大(+-8%),现在限定下半径。。。找出的排的靠前的圆是这样的;再看下默认最好的圆。。。

限定了半径范围

限定了半径范围
限定半径后默认最好的圆.jpg 半径好像接近了一点,还是好坑爹啊。。。

4、常规来说,使用该函数的时候,为避免找到太多的几乎重合的圆,找圆的最小距离都设在一个比较合理的值(比如大于半径1/5),这样在找多个圆的时候,就不会找出太多重合的圆了;不过这里我试下不限制最小距离,如下,默认排序下得分最高的几个圆如左图:

限定半径开放圆距离

限定半径开放圆距离

限定半径开放圆距离最好圆

限定半径开放圆距离最好圆
貌似默认最好的圆并没有任何改善

    很多初次使用该函数的看到这,或许就就觉得HoughCircles效果不咋地。。。本人刚开始使用时也感觉Opencv提供的这个算法太不稳定了,只能对某一个图调出相对好一点的效果,换一个图或者只改动其中某一个参数,找出来的圆就不知道跑哪去了,而且变化太大了。。。
    观察细心的可能发现了,第4步中的左图找出的众多圆其实已经比前面找出的圆靠谱很多了,而且这么多圆必定有一个圆就是我想要找的圆,只是按照投票分数排序下,最好的圆偏差较大。
    但究其算法优化本身,轮廓梯度定位出来的圆心投票本来精度就低(如图2),自然找出来的圆会有很多是错误的,但如果轮廓点足够多,找出的正确的圆必定也是存在的,只是按照票数方法来评价可能排序会比较靠后,但毕竟也是出现了的;此处只需做个小小的优化,改下评价方法,优化下排序,结果就很接近了
   

最终优化结果

最终优化结果
这是经过优化排序方法后找出的最好的圆
    找出来的圆中与实际轮廓重合度最高的圆一般就是我们要找的圆;因此我们可以通过HoughCircles来找出一批差不多的圆(如步骤4),然后画出这些圆,和实际轮廓比对一下,按实际重合像素的总数排序,这时分数最高的圆就如上面的结果图!HoughCircles优化一下还是很给力的!

    附件为本算法优化源码,有兴趣的可以一起来进一步优化(qq:970117454)
    注:如果编译通过,但运行时崩溃,通常原因是库版本不对!一般OpenCV官方给出的库版本分x86,x64,而每个平台下又有vc10,vc11,vc12,分别对应VS2010,VS2012,VS2013;其下还分debug版和release版,必须严格与编译环境和使用的配置相对应,否则会在运行过程中出错,且非常不好排查原因
     另该优化目前只能做到减少HoughCirlcles找错圆且错的比较离谱的几率,但无法真正提高精度,找出来的圆与实际圆稍有偏差还是有可能的;若需要高精度定位,建议采用该方法做粗定位,采用拟合圆做精定位(类似各商业算法中的环形区域找圆)










最终优化结果

最终优化结果

测试原图

测试原图

ExtendHoughCircle.cpp

13.8 KB, 下载次数: 23589

ExtendHoughCircle.h

965 Bytes, 下载次数: 16997

Main.cpp

547 Bytes, 下载次数: 16156

回复

使用道具 举报

发表于 2015-3-13 17:16:06 | 显示全部楼层
谢谢楼主~~使用你的算法后结果的确更准确,耗时也没有增加多少;
楼主,你程序中的FindCircles函数是做什么的?感觉接口函数cvFindCircles没有用到它啊?
回复 支持 1 反对 0

使用道具 举报

发表于 2015-1-30 08:56:24 | 显示全部楼层
顶一个!
看看发布时间,凌晨00:54
感动!
回复 支持 反对

使用道具 举报

发表于 2015-1-30 09:25:15 | 显示全部楼层
顶!学习了
回复 支持 反对

使用道具 举报

发表于 2015-1-30 09:36:04 | 显示全部楼层
借您的源码学习下!楼主是好人
回复 支持 反对

使用道具 举报

发表于 2015-1-30 21:55:54 | 显示全部楼层
谢谢楼主分享~
回复 支持 反对

使用道具 举报

发表于 2015-1-31 09:33:20 | 显示全部楼层
本帖最后由 qw173874546 于 2015-1-31 09:35 编辑

QQ截图20150131093041.bmp opencv的HoughCircles参数调对也可以找出来,这个是param1=140,param2=120左右
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-1-31 12:18:17 | 显示全部楼层
qw173874546 发表于 2015-1-31 09:33
opencv的HoughCircles参数调对也可以找出来,这个是param1=140,param2=120左右

直接用是可以,只是不怎么稳定
回复 支持 反对

使用道具 举报

发表于 2015-1-31 21:22:01 | 显示全部楼层
学习一下
回复 支持 反对

使用道具 举报

发表于 2015-2-2 08:45:51 | 显示全部楼层
刚学习,支持一下
回复 支持 反对

使用道具 举报

发表于 2015-2-3 23:09:08 | 显示全部楼层
支持楼主
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-3-29 15:58 , Processed in 0.014457 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表