翻贾志刚的github发现一个比较新奇的demo,使用opencv进行车道线的检测。
使用的方法都比较简单,但是效果看起来确实高端,可以和最新的无人驾驶相结合了。
- 读取视频
- 对视频的每一帧进行处理
- 首先截取本车道线的视角,保证只存在本车道线的区域
- 进行二值化处理
- 查找轮廓
- 通过角度过滤轮廓
- 确定直线方向
每个处理都很简洁,但是用在车道线检测上立马看起来不一样了。
#include <opencv2/opencv.hpp>
#include <iostream>
#define PI 3.1415926
using namespace cv;
using namespace std;
RNG rng(12345);
void find_Lanes(Mat &frame);
int main() {
String win_title = "input frame";
namedWindow(win_title, CV_WINDOW_AUTOSIZE);
VideoCapture capture("images/lane.avi");
if (!capture.isOpened()) {
printf("could not load video file");
return -1;
}
int i = 0;
Mat frame;
while (capture.read(frame)) {
imshow(win_title, frame);
find_Lanes(frame);
char c = waitKey(10);
if (c == 27) {
break;
}
}
waitKey(0);
return 0;
}
void find_Lanes(Mat &frame) {
// 裁剪出本车道需要的车道线
int offx = frame.cols / 5;
int offy = frame.rows / 3;
Rect rect;
rect.x = offx;
rect.y = frame.rows - offy;
rect.width = frame.cols - offx * 2;
rect.height = offy - 50;
// 得到本车道的车道线
Mat copy = frame(rect).clone();
imshow("copy", copy);
// 对车道进行二值化
GaussianBlur(copy, copy, Size(3, 3), 0);
Mat gray, binary;
cvtColor(copy, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
Mat mask = Mat::zeros(frame.size(), CV_8UC1);
binary.copyTo(mask(rect));
imshow("binary", binary);
// 查找轮廓
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(mask, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
Mat drawing = Mat::zeros(mask.size(), CV_8UC3);
for (size_t i = 0; i< contours.size(); i++)
{
// 使用角度过滤轮廓
RotatedRect rrt = minAreaRect(contours[i]);
int angle = abs(rrt.angle);
if (angle < 20 || angle > 160 || angle == 90)
continue;
printf("rrt.angle: %.2f\n", rrt.angle);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//drawContours(frame, contours, (int)i, color, 2, 8, hierarchy, 0, Point());
Point pt1(-1, -1);
Point pt2(-1, -1);
int miny = 100000;
int maxy = 0;
// 取得最大轮廓的两个端点
for (int p = 0; p < contours[i].size(); p++) {
Point onep = contours[i][p];
if (miny > onep.y) {
miny = onep.y;
pt1.y = onep.y;
pt1.x = onep.x;
}
if (maxy < onep.y) {
maxy = onep.y;
pt2.y = onep.y;
pt2.x = onep.x;
}
}
if (pt1.x < 0 || pt2.x< 0)
continue;
// printf("line Point1 (x = %d, y = %d) to Point2 (x=%d, y=%d)\n", pt1.x, pt1.y, pt2.x, pt2.y);
line(frame, pt1, pt2, Scalar(255, 0, 0), 3, 8);
}
imshow("mask", mask);
imshow("lane-lines", frame);
}
原始摄像头的视角
裁剪之后的视角
二值化
轮廓查找
参考:
贾志刚的git
视频链接:https://pan.baidu.com/s/1Ifkq9vZmIF9tEf8Johy_Og
提取码:li5y
网友评论