【C++】OpenCV:车道线检测原理与实现示例 您所在的位置:网站首页 opencv边缘检测直线拟合 【C++】OpenCV:车道线检测原理与实现示例

【C++】OpenCV:车道线检测原理与实现示例

2024-06-06 04:53| 来源: 网络整理| 查看: 265

文章目录 车道线检测原理图片读取视频读取

车道线检测原理

车道线检测是自动驾驶和驾驶辅助系统中的关键任务之一。OpenCV是一个广泛使用的计算机视觉库,可以用来进行车道线检测。

车道线检测的基本原理是通过图像处理和计算机视觉技术在图像或视频帧中提取出车道线的位置信息。以下是一种常见的基于OpenCV的车道线检测方法:

1.图像预处理:首先,将彩色图像转换为灰度图像,可以使用OpenCV中的cvtColor函数来实现。灰度图像有利于减少计算量并突出车道线的特征。

2.边缘检测:利用Canny边缘检测算法,可以通过OpenCV的Canny函数来实现。Canny算法能够检测图像中的边缘,并输出一个二值图像,其中只包含边缘点。

3.区域兴趣提取ROI:车道线通常在图像的下半部分出现,因此需要定义一个感兴趣的区域来提取车道线。可以通过OpenCV的fillPoly函数创建一个多边形mask,将非感兴趣区域的像素设为0。

4.霍夫变换:使用霍夫变换来检测直线,可以通过OpenCV的HoughLinesP函数实现。霍夫变换将图像中的直线表示为参数空间中的点,通过对参数空间进行累加,可以找到足够长的直线。

5.直线拟合:通过拟合检测到的直线,可以得到车道线的位置和方向。可以使用最小二乘法或RANSAC等算法来拟合直线,OpenCV提供了fitLine函数来实现。

6.可视化:将检测到的车道线在原始图像上进行可视化,可以使用OpenCV的line函数来绘制检测到的直线。

最终,可以采用OpenCV读取视频,进行灰度化处理,然后用canny算子进行边缘检测,分析轮廓,然后进行直线拟合处理,最后对直线添加权重分析,得到最终的车道线检测结果。

图片读取

一个示例:

#include #include using namespace std; using namespace cv; int main() { // 读取图像 Mat image = imread("input.png"); // 图像预处理 Mat gray; cvtColor(image, gray, COLOR_BGR2GRAY); GaussianBlur(gray, gray, Size(5, 5), 0); // 边缘检测 Mat edges; Canny(gray, edges, 50, 150); // 区域兴趣提取 Mat mask = Mat::zeros(edges.size(), CV_8UC1); Point points[4] = { Point(100, image.rows), Point(400, 350), Point(600, 350), Point(image.cols - 100, image.rows) }; fillConvexPoly(mask, points, 4, Scalar(255)); bitwise_and(edges, mask, edges); // 霍夫变换 std::vector lines; HoughLines(edges, lines, 1, CV_PI / 180, 100); cout //读取视频 VideoCapture capture("test.avi"); int height = capture.get(CAP_PROP_FRAME_HEIGHT); int width = capture.get(CAP_PROP_FRAME_WIDTH); int count = capture.get(CAP_PROP_FRAME_COUNT); int fps = capture.get(CAP_PROP_FPS); //初始化 left_line[0] = Point(0, 0); left_line[1] = Point(0, 0); right_line[0] = Point(0, 0); right_line[1] = Point(0, 0); cout break; } //imshow("input", frame); //显示视频 process(frame, left_line, right_line); //调用process char c = waitKey(5); if (c == 27) { break; } } } // 图像处理(参数:视频、左车道、右车道) void process(Mat &frame, Point *left_line, Point *right_line) { Mat gray, binary; /**灰度化*/ cvtColor(frame, gray, COLOR_BGR2GRAY); //canny算子边缘检测 Canny(gray, binary, 150, 300); //imshow("Canny", binary); for (size_t i = 0; i binary.at(i, j) = 0; } } imshow("binary", binary); //显示二值化结果 //寻找轮廓 vector contours; findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); Mat out_image = Mat::zeros(gray.size(), gray.type()); for (int i = 0; i continue; } if (rect.y > h) { continue; } //最小包围矩形 RotatedRect rrt = minAreaRect(contours[i]); //角度问题:https://blog.csdn.net/weixin_41887615/article/details/91411086 //cout //用椭圆拟合 RotatedRect errt = fitEllipse(contours[i]); //cout continue; } } } //cout for (int j = cy; j left_pts.push_back(Point(i, j)); } } } for (int i = cx; i int pv = image.at(j, i); if (pv == 255) { right_pts.push_back(Point(i, j)); } } } if (left_pts.size() > 2) { fitLine(left_pts, left, DIST_L1, 0, 0.01, 0.01); double k1 = left[1] / left[0]; double step = left[3] - k1 * left[2]; int x1 = int((height - step) / k1); int y2 = int((cx - 25)*k1 + step); Point left_spot_1 = Point(x1, height); Point left_spot_end = Point((cx - 25), y2); line(out, left_spot_1, left_spot_end, Scalar(0, 0, 255), 8, 8, 0); left_line[0] = left_spot_1; left_line[1] = left_spot_end; } else { line(out, left_line[0], left_line[1], Scalar(0, 0, 255), 8, 8, 0); } if (right_pts.size() > 2) { Point spot_1 = right_pts[0]; Point spot_end = right_pts[right_pts.size() - 1]; int x1 = spot_1.x; int y1 = spot_1.y; int x2 = spot_end.x; int y2 = spot_end.y; line(out, spot_1, spot_end, Scalar(0, 0, 255), 8, 8, 0); right_line[0] = spot_1; right_line[1] = spot_end; } else { line(out, right_line[0], right_line[1], Scalar(0, 0, 255), 8, 8, 0); } return out; }

运行结果如下:

在这里插入图片描述

在这里插入图片描述

以上。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有