OpenCV中文网站

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 安装 配置
楼主: wawa

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

  [复制链接]
发表于 2016-10-3 19:32:48 | 显示全部楼层
参考楼主和相关的资料,我进行了以下实现(jsxyhelu.cnblogs.com)
如何判断轮廓是否为圆?

   判断一个轮廓是否为圆?这看似简单的问题,在opencv中并没有现成的函数。当我真正想运用的时候,却发现还是有许多内容在里面的。
      
       比如这幅图片,由于瓶口是有缺陷的,造成找到的最大外轮廓不闭合。那么该如何判断这个轮廓是否是圆了。
     我认为从两点来考虑。
      一个是圆的定义:
   “平面上到定点的距离等于定长的所有点组成的图形叫做圆.定点称为圆心,定长称为半径.”
      那么就来判断当前轮廓到一个定点的距离是否为定长。这里这个定点就可以采用外接圆圆心。而这里的度量是标准差。
       经过试验发现,对于这些有缺陷的情况,其标准差都是比较大的(一般大于5),而对于没有缺陷的情况来说,其标准差都比较小(小于1)。
       但是这并不能完全地解决问题,比如存在这样的情况,其轮廓上所有点到定点的标准差也是不大的,但是这个轮廓没有构成一个闭合曲线,所以也没有构成圆。



  •    //根据轮廓点和圆心计算方差
  • float ComputeVariance(std::vector<cv:oint> theContour,Point2f theCenter)
  • {
  •     int a[65535],n;
  •     float aver,s;
  •     float sum=0,e=0;
  •     n = theContour.size();
  •     for(int i=0;i<n;i++)
  •     {
  •         a = GetDistance(theContour,theCenter);
  •         sum+=a;
  •     }
  •     aver=sum/n;
  •     for(int i=0;i<n;i++)
  •         e+=(a-aver)*(a-aver);
  •     e/=n-1;
  •     s=sqrt(e);
  •     return e;
  • }


        那么二点就是曲线闭合的定义.
      闭曲线:起点与终点重合的曲线。平面(或空间)中的闭曲线即为单位圆周到平面(或空间)中的连续映射的像。
      不是很好理解,但是可以这样简化,就是对于闭曲线中的任意一点,遍历闭曲线,都能够回到这一点。换句话说,就是不存在“端点”。这里可以再转换为这样的理解:
        “对于闭曲线中的所有点,除了它本身之外,和这个点距离为最小值(比如1)的点都有两个。”
  • //判断轮廓是否闭合。闭合曲线返回为0
  • intComputeClose(std::vector<cv:oint>MaxContour)
  • {
  • //TODO 计算第一个点和最后一个点相对于圆心的角度.最后变成计算这两点的距离
  • int itmp =0;
  • int iret =0;
  • for(int i=0;i<MaxContour.size();i++)
  • {
  • for(int j=0;j<MaxContour.size();j++)
  • {
  • if(i!=j)
  • {
  • if(GetDistance(MaxContour,MaxContour[j])<1)
  • {
  • itmp++;
  • }
  • }
  • }
  • if(itmp ==1)//存在端点
  • {
  • iret ++;
  • }
  • itmp=0;
  • }
  • return iret;
  • }



      小结一下:数学还是很强的,很多时候,借助定义本身,能够解决问题。

回复 支持 反对

使用道具 举报

发表于 2016-10-19 17:14:42 | 显示全部楼层
本帖最后由 君临天下的鱼 于 2016-10-19 17:16 编辑

崩溃了啊啊啊啊啊啊啊啊啊啊
回复 支持 反对

使用道具 举报

发表于 2016-10-24 23:05:18 | 显示全部楼层
亲爱的楼主你好,void ExtendCV::FindCircles(cv::InputArray _image, cv::vector<circle_found>& _circles, float dp, int min_dist,        int low_threshold, int high_threshold, int acc_threshold, int minRadius, int maxRadius,        float minScore, cv::InputArray _contour_image)有11个参数,而你的调用ExtendCV::FindCircles(testMat, found, 1, 1, 183, 332, 10, 68, 73, 0.5);只有10个,怎么得到的结果呀。
回复 支持 反对

使用道具 举报

发表于 2016-10-27 10:31:03 | 显示全部楼层
学习了,谢谢楼主
回复 支持 反对

使用道具 举报

发表于 2016-10-28 13:17:17 | 显示全部楼层
胡海兵 发表于 2016-10-24 23:05
亲爱的楼主你好,void ExtendCV::FindCircles(cv::InputArray _image, cv::vector& _circles, float dp, in ...

最后一个参数默认有值的
void FindCircles( cv::InputArray _image, vector<circle_found>& _circles,float dp, int min_dist,
        int low_threshold, int high_threshold,int acc_threshold,int minRadius, int maxRadius,
        float minScore, cv::InputArray _contour_image=cv::Mat() );
回复 支持 反对

使用道具 举报

发表于 2016-10-28 14:34:25 | 显示全部楼层
本帖最后由 hehainan86 于 2016-10-28 15:24 编辑
susanlt 发表于 2016-4-7 16:53
你好呀,想问下关于你的那个霍夫找圆的那个问题,就是我的事VS2015,OPENCV3.1.0我在看程序的时候,一直遇到 ...

opencv3.0的也找不到这个函数,干脆自己实现就好。

void icvHoughSortDescent32s(int* sort, int count, int* data)
{
         for (int i = 0; i < count; i++){
                 //寻找当前的最大值
                 int maxValue = data[sort];
                 int pos = i;
                 for (int j = i + 1; j < count; j++){
                         if (data[sort[j]] > maxValue){
                                 //交换
                                 maxValue = data[sort[j]];
                                 pos = j;
                         }
                 }
                 //如果有较大的值出现,交换
                 if (pos != i){
                         swap(sort, sort[pos]);
                 }
         }
}

*******************类似冒泡排序,但该方法就是比较耗时**************
回复 支持 反对

使用道具 举报

发表于 2016-10-30 15:19:30 | 显示全部楼层
计算量是很大~
回复 支持 反对

使用道具 举报

发表于 2016-10-30 21:36:45 | 显示全部楼层
jinq 发表于 2016-1-20 10:45
楼主,您好,我用VS2015+opencv2.4.10运行您的代码,FindCircles函数退出时出现
Invalid address specified ...

#include "stdafx.h" 这个没有呢 报错怎么运行的呢
回复 支持 反对

使用道具 举报

发表于 2016-11-8 14:43:56 | 显示全部楼层
wawa 发表于 2016-4-19 20:11
其实这个最优的精度也不是很高,只能减少明显找错的几率,如果需要非常高的精度,建议通过该算法粗定位, ...

请问 你说的筛选检测到的圆的边缘,具体怎么做法  网上查找好像没有相关解答
回复 支持 反对

使用道具 举报

发表于 2016-11-10 13:12:33 | 显示全部楼层
学习了,支持
回复 支持 反对

使用道具 举报

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

本版积分规则

手机版|OpenCV中文网站  

GMT+8, 2019-12-10 07:33 , Processed in 0.045672 second(s), 15 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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