车道检测
https://blog.csdn.net/wjinjie/article/details/108283008
// road_line_detect.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <opencv.hpp> using namespace cv; using namespace std; void detect_line(Mat &frame); Mat fitLines(Mat &img); int main() { //********video //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; //video //imshow("原图", frame); frame=imread("D:/image/road_line.jpg"); //imshow("frame",frame); detect_line(frame); waitKey(0); } return 0; } void detect_line(Mat &frame) { Mat gray, binary; cvtColor(frame, gray, COLOR_BGR2GRAY); //转灰度图 //imshow("灰度图",gray); Canny(gray, binary, 100, 150); //边缘检测 imshow("边缘检测", binary); //********************过滤掉天空与旁景色********************/ for (size_t i = 0; i < (gray.rows *1/ 3 + 50 ); 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); } //直线拟合 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)); } } Point left_start_last, left_end_last; 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; Point left_start = Point(x1, y1); Point 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; int 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; }