OpenCV與影象處理實戰之車道線檢測!無人駕駛第一步!
阿新 • • 發佈:2020-09-02
一、效果展示
對車輛所在車道的車道線檢測效果:
二、基本思路
如下圖所示,實現車道線的基本流程如下:
- 輸入原圖或視訊。
- 使用Canny()進行邊緣檢測。
- 提取感興趣區域。
- 提取輪廓,同時過濾掉不是車道線的輪廓。
- 對輪廓內點進行直線擬合。
- 在原圖上畫出檢測到的車道線。
三、實戰講解
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); }
溫馨提示:該方法只適合對直道檢測,同時在檢測過程中:要根據自己視訊或影象的大小,選擇合適的感興趣區域,同時調整相關引數,方能獲得不錯的檢測效果!
原始碼或者視訊教程加群:1136192749
原作者:
AI 菌
如有侵權聯絡刪除