利用逆透视变换获取车载图象的鸟瞰图

近年来在人工智能潮流下,各行各业对无人驾驶技术的发展投来了越来越多的关注。在智能驾驶系统的研究中,车道线检测的研究是非常重要的一环;鉴于绝大多数城市道路交通环境特性和车道线本身特性,当前车道线检测研究使用的绝大部分方法都是基于计算机视觉的方法,近几年深度学习方法的发展非常迅猛,但是由于深度学习依赖巨量的训练数据和其成本高昂的硬件需求,当前市场上使用的大多数智能驾驶产品都没有引入基于深度学习的视觉解决方案,以结合基于图象处理算法的视觉与雷达传感器结合的智能驾驶产品居多。

逆透视变换是当前国内外车道线检测研究使用得比较多的一个方法,逆透视变换从原理层面上与透视变换并没有本质的区别,透视变换能够将图象投影到一个新的视平面,关于透视变换的原理网上有很多博客,这里也就不多说了。Opencv中提供了透视变换的接口,通过在分别原图和结果图上设定4个点,这八个点就确定了原图到逆透视图的转换矩阵,并且这两组点在原图和逆透视图上是像素对应的

其实无论是透视变换还是逆透视变换,最重要的还是两组对应点的选取,这两组四个点,总共八个点关系透视变换的最终效果。这里使用的是车载摄像头的标定信息来选取对应点。

车载摄像头的标定信息

下面的代码是智能驾驶系统项目中的源码,这里把Opencv中的接口稍微封装了一下,其中有些与逆透视变换无关的参数,可以忽略不管;比较重要的一点是:这里的原图的四个点是通过车载摄像头的标定信息计算出来的,可以通过车载摄像头的标定信息计算出车载摄像头的消失点,找到消失点之后,四个点的选取就比较容易了;逆透视图的四个点就更好选取了,只要需要保证四个点构成一个正矩形就行了,四个点之间的像素距离可以根据标定信息计算,这样能够最大程度上让鸟瞰图的尺寸比例更接近现实世界的尺寸比例关系。

//参数为原图像、逆透视图、四个原图上的对应点
bool IpmTransform::executeipm(Mat& img,Mat& dst,Point2d P1,Point2d P2,Point2d P3,Point2d P4)
{
    if (img.data)
    {
        Point2f corners[4];//原图四个点
        Point2f corners_trans[4];//逆透视图四个点

        //**车载场景图象的其他参数**//
        float roi_x0=0;
        float roi_y0=228;
        float ROI_HEIGHT=30000;
        float ROI_WIDTH=3750;
        //************************//

        corners[0] = P2;
        corners[1] = P3;
        corners[2] = P1;
        corners[3] = P4;

        //设定逆透视图的宽度
        float IPM_WIDTH=500;
        float N=5;
        //保证逆透视图的宽度大概为N个车头宽
        float sacale=(IPM_WIDTH/N)/ROI_WIDTH;
        float IPM_HEIGHT=ROI_HEIGHT*sacale;

        //逆透视图初始化
        dst=Mat::zeros(IPM_HEIGHT+50,IPM_WIDTH,img.type());

        corners_trans[0] = Point2f(IPM_WIDTH/2-IPM_WIDTH/(2*N),0);  //P2
        corners_trans[1] = Point2f(IPM_WIDTH/2+IPM_WIDTH/(2*N),0);  //P3
        corners_trans[2] = Point2f(IPM_WIDTH/2-IPM_WIDTH/(2*N),IPM_HEIGHT);   //P1
        corners_trans[3] = Point2f(IPM_WIDTH/2+IPM_WIDTH/(2*N),IPM_HEIGHT);   //P4

        //计算原图到逆透视图和逆透视图到原图的变换矩阵
        warpMatrix_src2ipm = getPerspectiveTransform(corners, corners_trans);
        warpPerspective(img, dst, warpMatrix_src2ipm, dst.size());
        //标出两组点
        for(int i=0;i<4;i++)
            circle(img,corners[i],5,Scalar(0,255,255),4);
        for(int i=0;i<4;i++)
            circle(dst,corners_trans[i],5,Scalar(0,255,255),4);

        imshow("img",img);
        imshow("dst",dst);
    }
    else
    {
        cout << "NO IMAGE!!!" << endl;
        return false;
    }

    return true;
}

这里的变换截取了车载图象的一部分作为ROI区域来进行逆透视变换,这里在原图以及逆透视图上将两组对应点都用黄色点标了出来:

利用逆透视变换获取车载图象的鸟瞰图_第1张图片 原图及对应四个点

经过逆透视变换之后的图:(在鸟瞰图上的车道线远近粗细一样,这样为车道线检测提供了一个非常重要的特征

利用逆透视变换获取车载图象的鸟瞰图_第2张图片 逆透视图及对应四个点

同样在弯道的车道上也可以应用这种变换方法:

利用逆透视变换获取车载图象的鸟瞰图_第3张图片 原图及对应四个点

逆透视图:

利用逆透视变换获取车载图象的鸟瞰图_第4张图片 逆透视图及对应四个点

 

详细代码可见于LDW车道偏离预警源码:

https://github.com/cz152417312/ADAS/tree/master/LDW

你可能感兴趣的:(图像处理,计算机视觉,opencv)