C++ opencv-3.4.1 车道线的提取

翻贾志刚的github发现一个比较新奇的demo,使用opencv进行车道线的检测。
使用的方法都比较简单,但是效果看起来确实高端,可以和最新的无人驾驶相结合了。

  1. 读取视频
  2. 对视频的每一帧进行处理
  3. 首先截取本车道线的视角,保证只存在本车道线的区域
  4. 进行二值化处理
  5. 查找轮廓
  6. 通过角度过滤轮廓
  7. 确定直线方向

每个处理都很简洁,但是用在车道线检测上立马看起来不一样了。

#include 
#include 
#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 > contours;
    vector 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);
}

原始摄像头的视角

C++ opencv-3.4.1 车道线的提取_第1张图片

裁剪之后的视角

C++ opencv-3.4.1 车道线的提取_第2张图片

二值化

C++ opencv-3.4.1 车道线的提取_第3张图片

轮廓查找

C++ opencv-3.4.1 车道线的提取_第4张图片

参考:

贾志刚的git
视频链接:https://pan.baidu.com/s/1Ifkq9vZmIF9tEf8Johy_Og
提取码:li5y

你可能感兴趣的:(C++ opencv-3.4.1 车道线的提取)