opencv圆形检测,霍夫变换不稳定

opencv基于轮廓的圆形检测方法,霍夫变换不稳定

霍夫变换的原理网上很多,这里就不仔细讲了,实践证明,霍夫圆变换只能检测一些简单情形下的圆形,并且检测不出椭圆,由于之前做一个项目需要用到圆形检测(可能不是标准的圆),所以想出了一个基于轮廓的圆形检测方法。

首先对原图进行canny边缘检测,然后用findContours查找轮廓,遍历轮廓上的每一个点,

可以得到轮廓上距离最远的两个点,他们的中点可以假定为圆心,这两点间距离可假定为直径,

如果轮廓上每个点到这个中点距离在这个半径附近波动,则认为是一个圆(这里最好归一化处理,因为直径大的波动范围,和直径小的波动范围肯定不能用一个阈值),

当然还有一种方法是,根据直径所对的圆周角是直角,计算最远两点,和圆上(除这两点之外的)任意一点,的直径所对的那个角是否在90度左右,也可以确定。个人喜欢第二种,因为第二种准确率更高些。识别结果


角度计算函数:

double angle1( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
{
    double dx1 = pt1->x - pt0->x;
    double dy1 = pt1->y - pt0->y;
    double dx2 = pt2->x - pt0->x;
    double dy2 = pt2->y - pt0->y;//
    double angle_line = (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);//余弦值
    return acos(angle_line)*180/3.141592653;
}

下面仅是部分代码,

  CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * onetourlength);    
  //printf("seqlength:%dn",seqlength);   
  CvSeqReader reader;       //-- 读其中一个轮廓序列
  CvPoint pt = cvPoint(0,0);   
  cvStartReadSeq(contours,&reader);       //开始提取   
  for(int i = 0 ;i < onetourlength; i++){   
CV_READ_SEQ_ELEM(pt,reader);     //--读其中一个序列中的一个元素点
points[i] = pt;    
                }   
//   printf("%d-%d\n",points[0],points[0].y);
long length,max=0;
long pos;
bool isc=true;
for(int i=1;i<onetourlength;i++)
{
length=(points[i].x-points[0].x)*(points[i].x-points[0].x)+(points[i].y-points[0].y)*(points[i].y-points[0].y);
if(max<length)
{
max=length;
pos=i;
}
}
                s = 0;      
max=sqrt(max*1.0);   
for(int j=2;j<onetourlength;j++)
{
                t = fabs(angle1( &points[0],&points[pos],&points[j]));  
if((t< 70 || t > 130 )&&j!=pos)  
{
isc=false;
break;
}
}         
// printf("%f\n",t);

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值