C++OpenCV系统学习(9)——霍夫变换

1.霍夫直线变换

 1.1概述

Hough Line Transform用来做直线检测,前提条件是边缘检测已经完成(Canny边缘检测),它是由平面空间到极坐标空间转换。

1.2霍夫直线变换原理

       他是通过把图像上的所有像素点都变成极坐标空间,然后形成一条一条的曲线,如果所有的曲线都相交在一个点,那么这个点对应的\theta和r值就表示直线的角度。这就说明在屏幕坐标上的直线,在极坐标空间找到了,我们拿到了\theta和r重新反算到平面空间。

1.3补充

         对于任意一条直线上的所有点来说,变换到极坐标中,从[0,360]空间,可以得到r的大小,属于同一条直线上点在极坐标空(r,theta)必然在一个点上有最强的信号出现,跟几乎此反算到屏幕坐标中就可以得到直线上个点的像素坐标,从而得到直线。

 1.4 相关的API

  • 标准的霍夫变换cv::HoughLines从平面坐标转换到霍夫空间,最终输出(\theta,r)表示极坐标空间
  • 霍夫变换直线概率,cv::HoughLinesP最终输出的是直线的两个点(x0,y0,x1,y1)

下面的API不建议使用:

 建议使用的API:

 1.5 霍夫直线检测案例

void MyApi::HoughTranslate(Mat& image)
{
	//做边缘检测首先要进行高斯边缘模糊,如果利用Canny高斯边缘模糊Canny会帮我们做
	Mat image_gray, dst;
	Canny(image, image_gray, 150, 200);//100,200分别是低阈值和高阈值输出二值图
	imshow("edge_image", image_gray);
	cvtColor(image_gray, dst, COLOR_GRAY2BGR);

	vector<Vec4f> plines;//吧每个像素点的平面坐标转化为极坐标产生的曲线放入集合中
	HoughLinesP(image_gray, plines, 1, CV_PI / 180.0, 10, 0, 10);//从平面坐标转换到霍夫空间,最终输出的是直线的两个点(x0,y0,x1,y1)
	Scalar color = Scalar(0, 0, 255);
	for (size_t i = 0; i < plines.size(); i++)
	{
		Vec4f hline = plines[i];
		line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
	}
	imshow("hough_line_detection", dst);

}

结果如下所示:

上图分别是输入图像、边缘检测结果、以及霍夫直线检测的结果 

 2.霍夫圆检测

 2.1霍夫圆检测原理

 

        从平面坐标圆上的点到极坐标转换的三个参数C(x0,y0,r)其中x0,y0是圆心,r 取一固定值时theta扫描360度,x y 跟着变化, 若多个边缘点对应的三维空间曲线交于一点,则他们在共同圆上,在圆心处有累积最大值,也可以用同样的阈值的方法来判断一个圆是否被检测到。

 注:

        因为霍夫圆检测对噪声比较敏感,所以首先要对图像做滤波(模糊降噪)。(比如椒盐噪声用中值滤波,其他的也可以用高斯模糊)

        基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度(霍夫梯度法, 也叫2-1霍夫变换(21HT))的实现,分为两步(已封装到HoughCircles):

        第一步: Canny检测边缘,发现可能的圆心。圆心一定是在圆上的每个点的模向量上, 这些圆上点模向量的交点就是圆心, 霍夫梯度法的第一步就是找到这些圆心, 这样三维的累加平面就又转化为二维累加平面。

        第二步:基于第一步的基础上从候选圆心开始计算最佳半径大小。第二步根据所有候选中心的边缘非0像素对其的支持程度来确定半径。

HoughCircles(
InputArray image, // 输入图像 ,必须是8位的单通道灰度图像,8位可以有4个通道,每个通道是8位,可以使RGB。
OutputArray circles, // 输出结果,发现的圆信息(数组)
Int method, // 选梯度方法 - HOUGH_GRADIENT
Double dp, // dp = 1,原图尺度(2的话比原图小一半来寻找,速度快了)
Double mindist, // 10 半径最短距离-可以分辨是两个圆的,否则认为是半径不同的同心圆- src_gray.rows/8
Double param1, // canny边缘检测的低阈值canny edge detection low threshold
Double param2, // 中心点累加器阈值 – 候选圆心
Int minradius, // 圆最小半径
Int maxradius//圆最大半径(范围越大,速度越慢)
)

2.2案例分析

void MyApi::HoughCircleTranslate(Mat& image)
{
	Mat m_image,m_gray_image,dst;
	//首先需要中值滤波
	medianBlur(image, m_image,3);
	cvtColor(m_image, m_gray_image, COLOR_BGR2GRAY);

	//霍夫圆检测
	vector<Vec3f>pcircles;//把可能的圆放进容器
	HoughCircles(m_gray_image, pcircles, HOUGH_GRADIENT, 1, 10, 100,30,5,50);
	image.copyTo(dst);
	for (size_t i = 0; i < pcircles.size(); i++)
	{
		Vec3f cc = pcircles[i];//找到第i个圆,然后我们需要在dst图上画出来
		//绘制圆
		circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA);
		//标准圆心的颜色
		circle(dst, Point(cc[0], cc[1]), 2, Scalar(98, 23, 255), 2, LINE_AA);

	}
	imshow("输出结果", dst);
}

 原始图像和输出结果如上图所示,圆形被检测出来

  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AI炮灰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值