花老湿学习OpenCV:霍夫圆变换与圆检测

引言:

霍夫圆变换的基本思路是认为图像上每一个非零像素点都有可能是一个潜在的圆上的一点,跟霍夫线变换一样,也是通过投票,生成累积坐标平面,设置一个累积权重来定位圆。

 

标准Hough圆变换:

在笛卡尔坐标系中圆的方程为:

其中(a,b)是圆心,r是半径,也可以表述为:

所以在abr组成的三维坐标系中,一个点可以唯一确定一个圆。而在笛卡尔的xy坐标系中经过某一点的所有圆映射到abr坐标系中就是一条三维的曲线:  

经过xy坐标系中所有的非零像素点的所有圆就构成了abr坐标系中很多条三维的曲线。在xy坐标系中同一个圆上的所有点的圆方程是一样的,它们映射到abr坐标系中的是同一个点,所以在abr坐标系中该点就应该N条曲线相交(N为该点在xy坐标系中对应圆的总像素数)。通过判断abr中每一点的相交(累积)数量,大于一定阈值的点就认为是圆。

以上是标准霍夫圆变换实现算法,问题是它的累加面试一个三维的空间,意味着比霍夫线变换需要更多的计算消耗。

Opencv霍夫圆变换对标准霍夫圆变换做了运算上的优化。它采用的是“霍夫梯度法”。

霍夫梯度法:

可以参考:https://blog.csdn.net/qq_37059483/article/details/77916655

 第一阶段:检测圆心

1.1、对输入图像边缘检测;

1.2、计算图形的梯度,并确定圆周线,其中圆周的梯度就是它的法线;

1.3、在二维霍夫空间内,绘出所有图形的梯度直线,某坐标点上累加和的值越大,说明在该点上直线相交的次数越多,也就是越有可能是圆心;

1.4、在霍夫空间的4邻域内进行非最大值抑制;

1.5、设定一个阈值,霍夫空间内累加和大于该阈值的点就对应于圆心。

第二阶段:检测圆半径

2.1、计算某一个圆心到所有圆周线的距离,这些距离中就有该圆心所对应的圆的半径的值,这些半径值当然是相等的,并且这些圆半径的数量要远远大于其他距离值相等的数量;

2.2、设定两个阈值,定义为最大半径和最小半径,保留距离在这两个半径之间的值,这意味着我们检测的圆不能太大,也不能太小;

2.3、对保留下来的距离进行排序;

2.4、找到距离相同的那些值,并计算相同值的数量;

2.5、设定一个阈值,只有相同值的数量大于该阈值,才认为该值是该圆心对应的圆半径;

2.6、对每一个圆心,完成上面的2.1~2.5步骤,得到所有的圆半径。

 

API:

image为输入图像,要求是灰度图像

circles为输出圆向量,每个向量包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径

method为使用霍夫变换圆检测的算法,只实现了霍夫梯度法CV_HOUGH_GRADIENT

dp为第一阶段所使用的累加器的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推

minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心

param1为边缘检测时使用Canny算子的高阈值

param2为步骤1.5和步骤2.5中所共有的阈值

minRadius和maxRadius为所检测到的圆半径的最小值和最大值
 

代码实例:
 

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("F:\\visual studio\\Image\\circle2.png");
	if (src.empty())
	{
		cout << "Can't load the image" << endl;
		return -1;
	}
	imshow("src", src);
	//高斯模糊或者中值模糊
	Mat blursrc;
	//GaussianBlur(src, blursrc, Size(3, 3), 0, 0);
	medianBlur(src, blursrc, 3);
	//转化为灰度图
	Mat graysrc;
	cvtColor(blursrc, graysrc, COLOR_BGR2GRAY);
	//进行霍夫圆检测
	vector<Vec3f> circles;
	HoughCircles(graysrc, circles, HOUGH_GRADIENT, 1, 10, 200, 50, 1, 50);

	Mat dst;
	src.copyTo(dst);
	for (int i = 0; i < circles.size(); i++)
	{
		Vec3f cir = circles[i];
		circle(dst, Point(cir[0], cir[1]), cir[2], Scalar(255, 0, 0), 2, LINE_AA);
		circle(dst, Point(cir[0], cir[1]), 2 , Scalar(255, 0, 0), FILLED, LINE_AA);
	}
	imshow("dst", dst);
	waitKey(0);

}

 

                                                                       

 

疑问:

霍夫梯度法 1.3 1.4步的二维霍夫空间指的是什么? 坐标为(a,b)吗??

还有此例中,同心圆该如何检测?

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值