目录

一、前言

二、逆透视

1.逆透视讲解 (个人理解)

2、逆透视数组获取

3、样图

三、灰度图像获得

四、逆透视数组使用

1、实现逆透视

2、逆透视求实际角度

3、逆透视图像处理元素

4、边线逆透视变换

五、对于逆透视的观点


一、前言

        本文主要讲解智能车赛中逆透视应用和实现。

        注:本文逆透视文件即源码接来自于b站开源博主“__苏格拉没有底___”,此处仅是讲解其用法

        摄像头角度和高度固定好以后,再去使用逆透视,使用固定的逆透视变换数组以后,角度和高度不要再改变,若更改角度或高度,需重新求取逆透视变换数组。

二、逆透视

1.逆透视讲解 (个人理解)

        逆透视具体原理不需理解很透彻,因摄像头斜视(─━ _ ─━✧),导致所获得的图像并非是实际的图像,当我们需要实际的真实图像时,可对原图像进行逆透视变换,即将原斜视图像变换为上帝视角,可以在一定程度上精确元素判断。

        同时可获得变换3 * 3矩阵,可以直接对拐点进行逆透视,然后求出实际角度,对锐角,直角,钝角判定有很好的效果。

示例:

2、逆透视数组获取

       1. 首先要确定自己要处理的图像大小,之后尽量不做更改。

       2. 先下载MATLAB,内存有点大,至于收费问题,懂的都懂(可以去b站找)整套操作不需要MATLAB基础。
       3. 按照路径:求逆透视相关—>透视处理—>图像透视处理2,打开文件中图像透视处理法2(文件可由文章附带文件下载,若平台收费,可在b站找“__苏格拉没有底___”下载文件)

        4.在安装好MATLAB的前提下,jiaozhen文件会变为MATLAB可读文件,双击它打开:

    

        5.之后打开  “图像透视处理法1”  文件,同时点开step1,step2,即和jiaozhen一同在MATLAB页面内, 如下所示(注意图像路径更改)

         6.左侧会有   图像透视处理法1  中的所有照片,其中huandao1,shizi1,wandao1是作者本人导入的实际图片,可将这三个图片替换为自己的照片,在后面有介绍图片获得方式

        7.然后在文件“jiaozhen.m”和“Step2.m”中更改你的测试图片路径(以下为“jiaozhen.m”文件的路径,另一文件与此相同) 注意照片格式要和文件中一致

        

        8.然后先调数组大小,要将文件内所有的60,80改为自己图像的Image_Y,Image_X。快速更改方法:双击60,按“Ctrl + F”调出查找替换框,选中“全字匹配”,将替换框内搞好自己的数值后,点击“全部替换”。另一数值重复此操作。

        

        9.之后就是调参(参数全部在“jiaozhen.m”文件中),首先是   桶形畸变 因为使用总钻风130无畸变摄像头,故不存在桶形畸变,根据注释将k1,k2设为0即可

        10.接着是梯形畸变矫正 虽然是无畸变摄像头,但是有梯形畸变,具体可以查阅资料,然后这里有三个参数:

① h: 单位是米,将自己车放到平地上,拿尺子测摄像头高度,不需那么准确,但越准确越好,将得到的值替换h,我这里是30.5cm

②alpha:注释里的东西不用管,这个参数可以自己调出来,先大致调,再细调,自己试一下,随着数加一减一变化都很明显,可以    很快得到最适合的值,那么什么时候合适呢,就是你看着图像的高最顺眼的时候(黑色无效区域较少,原图像内东西大多存在),这个没有难度,每调一次,按F5运行一次,看输出的图像

补充一下:正确运行代码会得到三张输出结果,其中Figure1为桶形畸变矫正结果,因为值为0,所以和原图像无异;Figure3为逆透视图像,是重点关注图像;Figure4为反逆透视图像(将逆透视后图像再次运算,反向求出原图像),可以和原图像比对

③beta:注释里东西也不用管,和alpha方法相同,几下就能调出来,也是看着最顺眼的时候就可以

        11.接下来调整拉展与平移,也是自己调,调一次运行一次看看效果,很快就能调出来,也是自己看着最顺眼的时候就可以了

3、样图

这里放入我最终输出的几张样图:

        逆透视不可避免的会丢失部分信息,同时会出现三角黑边 。此时我已经调好参数,得到观感较好的逆透视图像,调试上述三个参数时可以参考我的效果。

三、灰度图像获得

        方法有很多,但都必须有上位机,将自己摄像头的图像发送到上位机上,截屏,修改尺寸(尺寸与循迹时处理的图像长宽一致 。如本人代码中就是Find_Line_Image,长为80,宽为60),WIFI图传我在另一文档有介绍,本人使用逐飞WiFi图传模块搭配逐飞助手获取图像。

        然后从上位机获得如下图像(自己推着车去实地取图),注意截屏时一定要细致,不可多不可少,就描着传过来的图像截屏,不要截到多余外部,然后进行压缩。

样例:

还是再补充下压缩图像吧:

①找到你的截图,双击打开

②右键,选择“改尺寸”

③选择“等比缩放”,配置好相关参数,然后点保存,就获得了一个摄像头原图像,将此图像导入MATLAB(即放入”图像透视处理法2“文件)

四、逆透视数组使用

1、实现逆透视

        根据上述流程调试好参数,运行代码后,会在文件“图像透视处理1”中得到四个数组文件:

        四个数组为:逆透视X坐标变换矩阵、逆透视Y坐标变换矩阵、返逆透视X坐标变换矩阵、返逆透视Y坐标变换矩阵。

        打开车赛开发软件,新建文件,并定义两个数组存放得到的逆透视坐标变换矩阵:

        之后写函数进行逆透视变换即可:

/**
* 函数功能:      求逆透视图像
* 特殊说明:      使用MATLAB中得到的逆透视矩阵实现
* 形  参:        uint8(*source_image)[Image_X]        要进行逆透视变换的矩阵
*                uint8 (*target_image)[Image_X]        逆透视变换后的图像
*
* 示例:          Get_Inverse_Perspective_Image(Find_Line_Image, I_Perspective_Image);
* 返回值:        无
*/
void Get_Inverse_Perspective_Image(uint8(*source_image)[Image_X], uint8 (*target_image)[Image_X])          //835us
{
    uint8 i = 0, j = 0;
    for(j = 0; j < Image_Y; j ++)
    {
        for(i = 0; i < Image_X; i ++)
        {
              target_image[j][i] = source_image[Inverse_Matrix_Col[j * Image_X + i]][Inverse_Matrix_Row[j * Image_X + i]];
        }
    }
}

        反逆透视变换:

//求逆透视的反逆透视图像
/**
* 函数功能:      求逆透视的反逆透视图像
* 特殊说明:      使用MATLAB中得到的反逆透视矩阵实现
* 形  参:        uint8(*Source_Image)[Image_X]        要进行反逆透视的逆透视图像
*                uint8(*target_image)[Image_X]         存储反逆透视变换后的图像
*
* 示例:          Get_Back_Inverse_Perspective_Image(I_Perspective_Image, Back_I_Perspective_Image);
* 返回值:        无
*/
void Get_Back_Inverse_Perspective_Image(uint8(*Source_Image)[Image_X], uint8(*target_image)[Image_X])
{
    uint8 i = 0, j = 0;
    for(j = 0; j < Image_Y; j ++)
    {
        for(i = 0; i < Image_X; i ++)
        {
            target_image[j][i] = Source_Image[Back_Inverse_Matrix_Col[j * Image_X + i]][Back_Inverse_Matrix_Row[j * Image_X + i]];
        }
    }
}

        这里要注意逆透视矩阵在数组内的定位。

2、逆透视求实际角度

求原图像拐角的实际角度(将角三点逆透视过来求角度)

//-------------------------------------------------------------------------------------------------------------------
//  @brief      逆透视知三点求形成的角度
//  @param      Ax,Ay      下边点
//  @param      Bx,By      要求角度的一点
//  @param      Cx,Cy      上边点
//  @return
//  @since      v1.0
//  Sample usage:
//  注:使用时传入原图像的三个点,不可传入逆透视图像的三个点
//-------------------------------------------------------------------------------------------------------------------
float Get_Turn_Point_Angle(uint8 Ax, uint8 Ay, uint8 Bx, uint8 By, uint8 Cx, uint8 Cy)
{

    float BA = 0.00;//向量BA的模
    float BC = 0.00;
    float SBA_BC = 0.00;//向量点乘的值
    float Angle = 0.00;

    uint8 AX = Inverse_Matrix_Row[Ay * Image_X + Ax];
    uint8 AY = Inverse_Matrix_Col[Ay * Image_X + Ax];
    uint8 BX = Inverse_Matrix_Row[By * Image_X + Bx];
    uint8 BY = Inverse_Matrix_Col[By * Image_X + Bx];
    uint8 CX = Inverse_Matrix_Row[Cy * Image_X + Cx];
    uint8 CY = Inverse_Matrix_Col[Cy * Image_X + Cx];

    BA = sqrt((float)((AX-BX)*(AX-BX)+(AY-BY)*(AY-BY)));
    BC = sqrt((float)((CX-BX)*(CX-BX)+(CY-BY)*(CY-BY)));

    SBA_BC = (float)((AX-BX)*(CX-BX)+(AY-BY)*(CY-BY));

    Angle =  acos(SBA_BC * 1.00/ (BA * BC));

    return Angle * 57.3f;
}

逆透视图相关拐点求角度:

//逆透视后的图像拐点求角度
float I_Get_Turn_Point_Angle(uint8 Ax, uint8 Ay, uint8 Bx, uint8 By, uint8 Cx, uint8 Cy)
{
    float BA = 0.00;//向量BA的模
    float BC = 0.00;
    float SBA_BC = 0.00;//向量点乘的值
    float Angle = 0.00;

    BA = sqrt((float)((Ax-Bx)*(Ax-Bx)+(Ay-By)*(Ay-By)));
    BC = sqrt((float)((Cx-Bx)*(Cx-Bx)+(Cy-By)*(Cy-By)));

    SBA_BC = (float)((Ax-Bx)*(Cx-Bx)+(Ay-By)*(Cy-By));

    Angle =  acos(SBA_BC * 1.00/ (BA * BC));

    return Angle * 57.3f;
}

        以上方法求出来的角度并非百分百准确,而是要有一定误差范围,比如找九十度直角,那么80° ~ 110°都可认为是直角。

3、逆透视图像处理元素

        逆透视不论是对于拐点找寻还是元素判断等,其实与原图像的判断、找寻、处理方法类似,属于触类旁通了。对于原图像的元素判断和处理等,会在后续文章讲解。

4、边线逆透视变换

        也是使用得到的逆透视变换矩阵进行处理,可将原图像得到的边线进行逆透视变换得到实际的赛道边线。处理方式与图像逆透视极其相似,只是将每个图像点的遍历更改为每个边线点的遍历,所以就不过多讲述,理解上述代码后相必很快自己就能敲出来这部分代码。

        这样变换会存在噪点和断点,至于怎么处理,就需读者自行发挥了。

五、对于逆透视的观点

        对于车赛来说,其实逆透视并不是必须的,特别是对于逆透视后的图像来说,赛道边线会存在非常多噪点,使用爬线算法提取会遇到非常多的问题。同时这些噪点的干扰并非简单的处理就可以解决的。使用高斯模糊等又会消耗非常多的算力。之前本人有尝试将高斯模糊与自适应迷宫算法相结合,即只将需要使用的点进行高斯模糊处理,效果也不甚理想。

        对于逆透视图像,更适合最长白直列向左右扫线求取边线的算法。

        但本人并没有过多尝试逆透视的应用和处理,至于怎样达到更好的效果,需要读者花费更多时间精力去探索,对于车赛来说,处理原图像绝对是够用的。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐