车道检测

 

 

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;
}

 

posted @ 2021-12-31 11:39  量子与太极  阅读(44)  评论(0编辑  收藏  举报