美文网首页
C++ opencv-3.4.1 车道线的提取

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

作者: yanghedada | 来源:发表于2019-06-20 23:13 被阅读0次

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

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

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

    #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

    相关文章

      网友评论

          本文标题:C++ opencv-3.4.1 车道线的提取

          本文链接:https://www.haomeiwen.com/subject/uotsqctx.html