matlab车道线检测_OpenCV与图像处理实战之车道线检测!无人驾驶第一步

一、效果展示

对车辆所在车道的车道线检测效果:

5d26e4440fe8c9beff4b5bff1f4e39ab.png

二、基本思路

如下图所示,实现车道线的 基本流程 如下:

  1. 输入原图或视频。
  2. 使用Canny()进行边缘检测。
  3. 提取感兴趣区域。
  4. 提取轮廓,同时过滤掉不是车道线的轮廓。
  5. 对轮廓内点进行直线拟合。
  6. 在原图上画出检测到的车道线。
c402013e81a229b7d51cb5b506db5b0b.png

三、实战讲解

3.1 主函数

在主函数中,我们需要读取视频,对每一帧都进行车道线检测处理。

int main(){VideoCapture cap("road.mp4");int height = cap.get(CAP_PROP_FRAME_HEIGHT); //480int width = cap.get(CAP_PROP_FRAME_WIDTH);  //856int count = cap.get(CAP_PROP_FRAME_COUNT);int fps = cap.get(CAP_PROP_FPS);//cout << height << " " << width << " " << count << " " << fps;while (1){Mat frame;cap >> frame;//imshow("原图", frame);detect_line(frame);waitKey(30);}return 0;}

3.2 直线拟合

当我们得到了每一个车道线轮廓时,需要对轮廓内的点进行直线拟合。这样得到的车道线鲁棒性会更好。(前提是,车道线本身是直的)

//直线拟合Mat fitLines(Mat &img){Mat img_fitLines = Mat::zeros(img.size(), CV_8UC3);int height = img.rows;int width = img.cols;int h_center = height / 2;int w_center = width / 2;vector leftLine;vector rightLine;//左车道线for (size_t i = 100; i < w_center ; i++)       //100-428(左){for (size_t j = h_center; j < height; j++)  //240-480(下){if (img.at(j, i) == 255) //白色leftLine.push_back(Point(i, j));}}if (leftLine.size() > 2){Vec4f left_para; //直线拟合输出参数Point point_l; //直线上的一点fitLine(leftLine, left_para, DIST_L1, 0, 0.01, 0.01);  //直线拟合double kl = left_para[1] / left_para[0];  //直线斜率point_l.x = left_para[2];point_l.y = left_para[3];int y1 = height / 2 + 60;int x1 = (y1 - point_l.y) / kl + point_l.x;int y2 = height - 40;int x2 = (y2 - point_l.y) / kl + point_l.x;left_start = Point(x1, y1);left_end = Point(x2, y2);line(img_fitLines, left_start, left_end, Scalar(0, 0, 255), 8, 8, 0);left_start_last = left_start;left_end_last = left_end;x2_last = x2;}else{line(img_fitLines, left_start_last, left_end_last, Scalar(0, 0, 255), 8, 8, 0);}//右车道线for (size_t i = w_center; i < width; i++)   //428-856(右){for (size_t j = h_center; j < height; j++)  //240-480(下){if (img.at(j, i) == 255)rightLine.push_back(Point(i, j));}}if (rightLine.size() > 2){Point right_start = rightLine[0];Point right_end = rightLine[rightLine.size() - 1];line(img_fitLines, right_start, right_end, Scalar(0, 0, 255), 8, 8, 0);}return img_fitLines;}

3.3 车道线检测

这个函数是主要功能函数,主要的执行步骤如下:

  • 将原图转为灰度图,然后采用Canny()进行边缘检测。
  • 提取感兴趣区域,过滤掉天空和旁景。
  • 寻找处理后图像中的轮廓,过滤掉不是车道线的轮廓。
  • 调用直线拟合函数fitLines(),对轮廓中的点进行直线拟合,最后在原图上显示车道线。
void detect_line(Mat &frame){Mat gray, binary;cvtColor(frame, gray, COLOR_BGR2GRAY); //转灰度图Canny(gray, binary, 150, 300); //边缘检测//imshow("边缘检测", binary);/********************过滤掉天空与旁景色********************/for (size_t i = 0; i < (gray.rows / 2 + 40); i++){for (size_t j = 0; j < gray.cols; j++){binary.at(i, j) = 0;}}for (size_t i = 450; i < gray.rows; i++){for (size_t j = 0; j < gray.cols; j++){binary.at(i, j) = 0;}}imshow("过滤后", binary);/*********************************************************/    //寻找轮廓vector> contours;  //向量中是若干个点的集合,每一个集合代表一个轮廓,包含若干个点findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //获取外轮廓,且仅保存轮廓的拐点信息Mat img_output = Mat::zeros(gray.size(), gray.type());/*****************************轮廓分析(筛选)***************************    1.排除轮廓(长度小于5、面积不足10的,同时矩形的高不能太大)    2.排除最小外切矩形角度太小的或者太大的(20,84)    3.排除椭圆拟合角度过小的***********************************************************************/for (size_t i = 0; i < contours.size(); i++){    //计算每个轮廓的面积和周长double length = arcLength(contours[i],true);double area = contourArea(contours[i]);//cout << "轮廓" << i << "的周长是:" << length << " " << "面积是" << area << endl;//得到包覆此轮廓的最小正矩形Rect rect = boundingRect(contours[i]);//最小包围矩形(斜)RotatedRect mAR = minAreaRect(contours[i]);double angle = abs(mAR.angle);  //倾斜角度if (length < 5.0 || area < 10.0)continue;//if (rect.y > gray.rows - 50)//continue;if (angle > 84.0 || angle < 20.0)  //去掉角度大的边线continue;drawContours(img_output, contours, i, Scalar(255), 2, 8);imshow("排除部分轮廓后", img_output);}Mat dst;Mat roadLines = fitLines(img_output);addWeighted(frame, 0.9, roadLines, 0.5, 0, dst);imshow("最终车道线显示", dst);}

温馨提示: 该方法只适合对直道检测,同时在检测过程中:要根据自己视频或图像的大小,选择合适的感兴趣区域,同时调整相关参数,方能获得不错的检测效果!

源代码或者视频教程后台私信小编01

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值