车道线端点检测

        最近在学习进行车道线的端点检测,网上较多的为车道线检测,而缺少端点检测这一方面的内容,于是决定将自己的一些尝试的方法记录下来。

使用图像

        读取图片非常简单,只需要直接调用opencv读取图片的函数就可以,读取车道线图片后首先进行图片灰度化与边缘检测。

 边缘检测

    Mat gray, binary;
	cvtColor(frame, gray, COLOR_BGR2GRAY); //转灰度图
	Canny(gray, binary, 150, 300); //边缘检测

        关于两个函数做一下简单的解释:

        cv::cvtColor()用于将图像从一个颜色空间转换到另一个颜色空间的转换(目前常见的颜色空间均支持),并且在转换的过程中能够保证数据的类型不变,即转换后的图像的数据类型和位深与源图像一致。

void cv::cvtColor(
      cv::InputArray src, // 输入序列
      cv::OutputArray dst, // 输出序列
      int code, // 颜色映射码
      int dstCn = 0 // 输出的通道数 (0='automatic')
     );

参数解释:

InputArray src: 输入图像即要进行颜色空间变换的原图像

OutputArray dst: 输出图像即进行颜色空间变换后存储图像

int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片

int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定

void Canny(InputArray image,OutputArray edges, 
           double threshold1, double threshold2, 
           int apertureSize=3,bool L2gradient=false )

 

第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。

第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。

第三个参数,double类型的threshold1,第一个滞后性阈值。

第四个参数,double类型的threshold2,第二个滞后性阈值。

第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。

第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。

        边缘检测后,对原图像提取感兴趣区域。因为车道线拍摄图片一般由车载摄像头所拍摄,图像下一半靠近中间部分为车道线,图像上面与两侧一般为天空与绿化带,可以将天空及图像两边去除,余下部分即为感兴趣区域。

 提取感兴趣区域

	/********************过滤掉天空与旁景色********************/
	for (size_t i = 0; i < (gray.rows / 2) + 15; i++)
	{
		for (size_t j = 0; j < gray.cols; j++)
		{
			binary.at<uchar>(i, j) = 0;
		}
	}


	for (size_t i = 385; i < gray.rows; i++)
	{
		for (size_t j = 0; j < gray.cols; j++)
		{
			binary.at<uchar>(i, j) = 0;
		}
	}
	imshow("提取感兴趣区域后", binary);
	/*********************************************************/

        提取感兴趣区域后,即可以进行轮廓提取,这里需要调用findContours函数。

//寻找轮廓
	vector<vector<Point>> contours;  //向量中是若干个点的集合,每一个集合代表一个轮廓,包含若干个点
	findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //获取外轮廓,且仅保存轮廓的拐点信息
findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset=Point());

第一个参数是输入的二值图

第二个参数是检测到的轮廓(vector<<vector>Point>contours),第一个<>里面的vector是一个轮廓所有点的向量数组,外面的vector是检测到的所有轮廓向量(以单个轮廓作为向量元素)

第三个参数是 轮廓检索模式

CV_RETR_EXTERNAL=0-----表示只检测最外层轮廓--常用

CV_RETR_LIST=1------提取所有轮廓并放置在list中, 轮廓不建立等级关系

CV_RETR_CCOMP=2------提取所有轮廓并组织为双层结构

CV_RETR_TREE=3------提取所有轮廓并重新建立网状轮廓结构

第四个参数是 轮廓近似方法

CHAIN_APPROX_NONE--常用--提取连续的轮廓线

 CHAIN_APPROX_SIMPLE--只显示线段端点

第五个参数是偏移量,可以不设置

        轮廓后可能会检测到一些我们所不需要的干扰项,这时还需要对提取的轮廓进行筛选,可以根据自己的图像设置排除轮廓周长、面积、倾斜角不符合的轮廓,剩余车道线轮廓。接下来就非常简单,对车道线轮廓检索,找到每个轮廓的顶点与底点就可以了。

 筛选轮廓后

for (int j = 0; j<contours[i].size(); ++j)
		{
			if (contours[i][j].y > max.y)
			{
				max.y = contours[i][j].y;
				max.x = contours[i][j].x;
			}
			if (contours[i][j].y < min.y)
			{
				min.y = contours[i][j].y;
				min.x = contours[i][j].x;
			}
		}

        为了便于观察,还可以用circle函数在原图像中标记处车道线端点。

 检测结果

circle(frame, max, 4, Scalar(0, 255, 255));

        这种方法做的车道线端点检测比较受限,当有车压在车道线上方或者车道线较模糊时,检测结果比较差,不过省去了进行车道线直线拟合的步骤。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值