OpenCV_提取直线、轮廓和区域

*提取直线、轮廓和区域

之前的二值边缘分布图有两个缺点。首先,检测到的边缘过厚,这导致更加难以识别物体的边界;第二,通常不能找到这样的阈值:低到足以检测到图像中的所有重要的边缘同时又避免产生太多无关紧要的边缘。Canny算法试图解决这样的问题。

使用cv::Canny()函数需要给出低阈值和高阈值两个阈值。canny算子通常是基于sobel算子,低阈值是宽松阈值,很多不需要的也被检测出来了;高阈值则界定重要轮廓边缘,canny算法结合这两种边缘分布图生成最优的轮廓分布图。

基于现在无人驾驶的火爆,我下载了一张道路图:


使用canny算子检测到的轮廓:


代码:

int main()
{
	cv::Mat image = cv::imread("road.jpg");
	cv::imshow("original image", image);
	cv::Mat contours;
	cv::Canny(image, contours, 350, 400);
	cv::imshow("Canny Image", contours);
	cvWaitKey();
}


*用霍夫变换检测直线

在霍夫变换中,用这个方程式表示直线:


参数rho是直线与图像原点(左上角)的距离,theta是直线与垂直线的角度。

基础霍夫变化:CV::HoughLines,它输入一个二值分布图,通常是一个已经生成的边缘分布图,例如用Canny算子生成的分布图,输出的是一个cv::Vec2f的向量,每个元素是一对浮点数,表示检测到直线的( rho, theta )

这个算法检测的是图像中的直线而不是线段,不会给出直线的端点。

检测结果:


代码:

int main()
{
	cv::Mat image = cv::imread("road2.jpg");
	cv::imshow("original image", image);
	cv::Mat contours;
	cv::Canny(image, contours, 350, 400);
	//用霍夫变换检测直线
	std::vector<cv::Vec2f> lines;
	cv::HoughLines(contours, lines,
		1, PI / 180,//步长
		60);//最小投票数
	std::vector<cv::Vec2f>::const_iterator it = lines.begin();
	while (it!=lines.end())
	{
		float rho = (*it)[0];
		float theta = (*it)[1];
		if (theta<PI / 4.0 || theta>3.0*PI / 4.0)
		{
			//直线与第一行的交叉点
			cv::Point pt1(static_cast<int>(rho / cos(theta)), 0.0);
			//直线与最后一行的交叉点
			cv::Point pt2(rho / cos(theta) - image.rows*sin(theta) / cos(theta), image.rows);
			cv::line(image, pt1, pt2, cv::Scalar(255,255,255), 1);
		}
		else
		{
			cv::Point pt1(0, rho / sin(theta));
			cv::Point pt2(image.cols, rho / sin(theta) - image.cols*cos(theta) / sin(theta));
			cv::line(image, pt1, pt2, cv::Scalar(255,255,255), 1);
		}
		it++;
	}
	cv::imshow
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值