基于opencv实现车道线检测
程序员文章站
2022-05-22 14:26:04
基于opencv的车道线检测,供大家参考,具体内容如下原理:算法基本思想说明:传统的车道线检测,多数是基于霍夫直线检测,其实这个里面有个很大的误区,霍夫直线拟合容易受到各种噪声干扰,直接运用有时候效果...
基于opencv的车道线检测,供大家参考,具体内容如下
原理:
算法基本思想说明:
传统的车道线检测,多数是基于霍夫直线检测,其实这个里面有个很大的误区,霍夫直线拟合容易受到各种噪声干扰,直接运用有时候效果不好,更多的时候通过霍夫直线检测进行初步的筛选,然后再有针对性的进行直线拟合,根据拟合的直线四个点坐标,绘制出车道线,这种方式可以有效避免霍夫直线拟合不良后果,是一种更加稳定的车道线检测方法,在实际项目中,可以选择两种方法并行,在计算出结果后进行叠加或者对比提取,今天分享的案例主要是绕开了霍夫直线检测,通过对二值图像进行轮廓分析与几何分析,提取到相关的车道线信息、然后进行特定区域的像素扫描,拟合生成直线方程,确定四个点绘制出车道线,对连续的视频来说,如果某一帧无法正常检测,就可以通过缓存来替代绘制,从而实现在视频车道线检测中实时可靠。
原理图:
代码:
#include <opencv2/opencv.hpp> #include <iostream> #include <cmath> using namespace cv; using namespace std; /** **1、读取视频 **2、二值化 **3、轮廓发现 **4、轮廓分析、面积就算,角度分析 **5、直线拟合 **6、画出直线 ** */ point left_line[2]; point right_line[2]; void process(mat &frame, point *left_line, point *right_line); mat fitlines(mat &image, point *left_line, point *right_line); int main(int argc, char** argv) { //读取视频 videocapture capture("e:/opencv/road_line.mp4"); 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 << height<<" "<< width<< " " <<count<< " " <<fps << endl; //循环读取视频 mat frame; while (true) { int ret = capture.read(frame); if (!ret) { break; } imshow("input", frame); process(frame, left_line, right_line); 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); //threshold(gray, binary, ); //边缘检测 canny(gray, binary, 150, 300); //imshow("canny", 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; } } imshow("binary", binary); //寻找轮廓 vector<vector<point>> contours; findcontours(binary, contours, retr_external, chain_approx_simple); mat out_image = mat::zeros(gray.size(), gray.type()); for (int i = 0; i < contours.size(); i++) { //计算面积与周长 double length = arclength(contours[i], true); double area = contourarea(contours[i]); //cout << "周长 length:" << length << endl; //cout << "面积 area:" << area << endl; //外部矩形边界 rect rect = boundingrect(contours[i]); int h = gray.rows - 50; //轮廓分析: if (length < 5.0 || area < 10.0) { continue; } if (rect.y > h) { continue; } //最小包围矩形 rotatedrect rrt = minarearect(contours[i]); //cout << "最小包围矩形 angle:" << rrt.angle << endl; double angle = abs(rrt.angle); //angle < 50.0 || angle>89.0 if (angle < 20.0 || angle>84.0) { continue; } if (contours[i].size() > 5) { //用椭圆拟合 rotatedrect errt = fitellipse(contours[i]); //cout << "用椭圆拟合err.angle:" << errt.angle << endl; if ((errt.angle<5.0) || (errt.angle>160.0)) { if (80.0 < errt.angle && errt.angle < 100.0) { continue; } } } //cout << "开始绘制:" << endl; drawcontours(out_image, contours, i, scalar(255), 2, 8); imshow("out_image", out_image); } mat result = fitlines(out_image, left_line, right_line); imshow("result", result); mat dst; addweighted(frame, 0.8, result, 0.5,0, dst); imshow("lane-lines", dst); } //直线拟合 mat fitlines(mat &image, point *left_line, point *right_line) { int height = image.rows; int width = image.cols; mat out = mat::zeros(image.size(), cv_8uc3); int cx = width / 2; int cy = height / 2; vector<point> left_pts; vector<point> right_pts; vec4f left; for (int i = 100; i < (cx-10); i++) { for (int j = cy; j < height; j++) { int pv = image.at<uchar>(j, i); if (pv == 255) { left_pts.push_back(point(i, j)); } } } for (int i = cx; i < (width-20); i++) { for (int j = cy; j < height; j++) { int pv = image.at<uchar>(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; }
结果图片:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 大数据激发行业数据新能量
推荐阅读
-
人脸检测识别opencv+python实现(Haar分类器)
-
Java+opencv3.2.0实现hough直线检测
-
Java+opencv3.2.0实现hough圆检测功能
-
Java+opencv3.2.0实现人脸检测功能
-
Python基于opencv调用摄像头获取个人图片的实现方法
-
Android 中使用 dlib+opencv 实现动态人脸检测
-
Python+OpenCV目标跟踪实现基本的运动检测
-
python opencv实现运动检测
-
Android 中使用 dlib+opencv 实现动态人脸检测功能
-
基于jupyter notebook的python编程(Win10通过OpenCv-3.4.1进行人脸口罩数据集的模型训练并进行戴口罩识别检测)