OpenCV与图像处理实战(一):车道线检测

大家好,我是【AI 菌】。本专栏以实战为主,分享一些用opencv进行图像处理的实用案例。本专栏会持续更新,欢迎关注和交流!

文章目录一、效果展示二、基本思路三、实战讲解3.1 主函数3.2 直线拟合3.3 车道线检测

还没有搭建环境的小伙伴,戳戳这篇:VS2015 + OpenCV3.1 环境配置与项目搭建(C++版)

一、效果展示

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

OpenCV与图像处理实战(一):车道线检测

二、基本思路

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

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

OpenCV与图像处理实战(一):车道线检测

三、实战讲解
3.1 主函数

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

int main()
{
VideoCapture cap("road.mp4");

int height = cap.get(CAP_PROP_FRAME_HEIGHT); //480
int width = cap.get(CAP_PROP_FRAME_WIDTH); //856
int 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<Point> leftLine;
vector<Point> 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<uchar>(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<uchar>(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<uchar>(i, j) = 0;
}
}

for (size_t i = 450; i < gray.rows; i++)
{
for (size_t j = 0; j < gray.cols; j++)
{
binary.at<uchar>(i, j) = 0;
}
}
imshow("过滤后", binary);
/*********************************************************/

//寻找轮廓
vector<vector<Point>> 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);
}

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

如果您需要完整代码测试视频,可关注我的公众号,回复:车道线。更多精彩等着你哦!

OpenCV与图像处理实战(一):车道线检测

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

OpenCV与图像处理实战(一):车道线检测

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » OpenCV与图像处理实战(一):车道线检测
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏