去畸变请参考:图像处理去畸变教程_LoseHu的博客-CSDN博客

去畸变+逆透视请参考:​​​​​​​​​​​​​​​​​​​​​智能车去畸变+逆透视教程_LoseHu的博客-CSDN博客

逆透视:如下

1.简介

对于初做车的同学,看见摄像头图像神奇的侧视角难免会有些烦躁,我刚开始也是如此,所以在此,想详细的分享一下我们的透视变换方案。(实战教学)

先上各种效果图。

优点:

        使用指针映射透视变换数组,只需要初始化映射一次,后续不需要时间​​​​​​​

通用性强,可移植性高

       还可以已知原图坐标情况下求透视后坐标

2.摄像头环境

硬件:总钻风摄像头(由于多车组使用沁恒芯片,修改过硬件适应dvp)

镜头:140度镜头,畸变小于5%

摄像头分辨率:120*188(长*宽)

透视图分辨率:100*114(长*宽)

摄像头高度:30cm左右

总钻风是很常见的智能车摄像头,之所以选用140度镜头,是因为其角度大,且畸变率非常小,完全不影响图像处理,可以省去去畸变的烦恼,摄像头120*188是因为其比例可以使视野最大。

3.逆透视简单原理

众所周知,对于十字这个元素,标准赛道(不算路肩、黑胶带),它是一个宽度为45cm的标准正方形。但是因为摄像头角度问题,十字的正方形在图片中是一个梯形。

那嚒我们所要做的,就是根据图片中的这一块梯形(实则是正方形),这一个信息,将图片进行拉伸变换,使之成为标准的俯视图。

公式:

w与w’在二维图中为1

已知结果图中坐标,通过上述公式就能在原图中找到对应的坐标。

那么这个3*3矩阵就是我们需要使用上位机求取的。

4.通过上位机求取矩阵

环境准备:

拍摄的十字图像(或正方形图像),灰度与二值化图均可,要能完全展示出正方形部分,如:

图像中可以显示出车头,因为在后续的透视过程中可以通过图像修改参数平移去除。

那么,根据图中的假正方形,就可以进行后续操作。

上位机操作:

 结果图宽高:得到的透视图像的宽高。

方形中心距顶部像素:在结果图中,正方形的中心,距离图像最上端多少个像素行(值越大,图像越向下平移)。

方形像素边长:在结果图中,正方形的边长相当于多少个像素(值越大,图片就会被放大更多,如果是45,就是一像素对应1cm距离)。

四个XY值:图中方形四个顶点的坐标,通过鼠标右键在图中点击就可以自动输入(点击顺序:左下---右下---左上---右上)。

逆透视上位机操作

     最终矩阵会复制到您的剪切板中,如:

{{-10.603578,4.261626,-292.576700},
{0.665623,6.708527,-1508.674551},
{0.000570,0.016935,-2.741442}};

注意事项:

1.图片经过逆透视操作后得到的结果图,因为对图片进行了拉伸,底边两个角落可能会出现无内容部分(如下图),使用时应当避免.可通过修改结果图大小,或者增大方形中心距顶部像素来对图形进行平移去除。

2.鼠标点击顺序要符合左下---右下---左上---右上。

         有些图片打开失败,请检查图片后缀,有的是jpg格式,后缀却是bmp。

5.在智能车上使用矩阵:

原理说明:

求得矩阵后,就可根据矩阵,和结果图的坐标,计算出结果图中的某个点,在原图中的坐标。

但如果每获取到一帧图像,都进行一次映射,非常耗费时间。所以我们使用指针。

在初始化时只需要对指针地址进行一次映射,以后只需要调用指针数组,就可以获取到透视后的图。(需要注意的是,和图像一样的大的指针数组可能会导致您的内存溢出,所以建议将透视图尺寸缩小,即减小RESULT_ROW与RESULT_COL也可以避免黑边出现

change_un_Mat[3][3] 是你通过上位机求取的矩阵,在您的剪切板中。

ImageUsed[0][0]代表图像左上角的值

PER_IMG    为用来透视变换的图片,如果使用灰度图,那么ImageUsed就是灰度图的逆透视图,

如果使用二值化图,那么ImageUsed就是二值化的逆透视图

BlackColor的值为没有内容部分的灰度值。

只需要初始化时调用一次ImagePerspective_Init()函数,只需要初始化时调用一次!!!!一次就行!!!!!!!

//
// Created by RUPC on 2022/9/20.
//
#define RESULT_ROW 100//结果图行列
#define RESULT_COL 114
#define         USED_ROW                120  //用于透视图的行列
#define         USED_COL                188
#define PER_IMG     SimBinImage//SimBinImage:用于透视变换的图像
#define ImageUsed   *PerImg_ip//*PerImg_ip定义使用的图像,ImageUsed为用于巡线和识别的图像
typedef unsigned char       uint8_t;                                              // 无符号  8 bits
uint8_t *PerImg_ip[RESULT_ROW][RESULT_COL];void ImagePerspective_Init(void) {static uint8_t BlackColor = 0;double change_un_Mat[3][3] = {          //114w*100h{ -0.01609759704190238, 0.01932561893613478, -2.040617594981866 }, {0.0004352209945470896, -0.000367865364438621,-0.7035606436969671 }, { 1.115951268069474e-005,0.0001970185393508392, -0.03104642853440032 }, };for (int i = 0; i < RESULT_COL ;i++) {for (int j = 0; j < RESULT_ROW ;j++) {int local_x = (int) ((change_un_Mat[0][0] * i+ change_un_Mat[0][1] * j + change_un_Mat[0][2])/ (change_un_Mat[2][0] * i + change_un_Mat[2][1] * j+ change_un_Mat[2][2]));int local_y = (int) ((change_un_Mat[1][0] * i+ change_un_Mat[1][1] * j + change_un_Mat[1][2])/ (change_un_Mat[2][0] * i + change_un_Mat[2][1] * j+ change_un_Mat[2][2]));if (local_x>= 0&& local_y >= 0 && local_y < USED_ROW && local_x < USED_COL){PerImg_ip[j][i] = &PER_IMG[local_y][local_x];}else {PerImg_ip[j][i] = &BlackColor;          //&PER_IMG[0][0];}}}}/*完成摄像头初始化后,调用一次ImagePerspective_Init,此后,直接调用ImageUsed   即为透视结果*/

屏幕显示透视变换后的灰度图DEMO:

int main(void)
{All_Init();//屏幕、摄像头、以及其他外设初始化ImagePerspective_Init();while(1){if (mt9v03x_finish_flag_dvp == 1) {uint8_t show[RESULT_ROW][RESULT_COL];for(int i=0;i<RESULT_ROW;i++){for(int j=0;j<RESULT_COL;j++){show[i][j]=ImageUsed[i][j];}}ips114_show_gray_image(0,0,show[0],RESULT_COL,RESULT_ROW,RESULT_COL,RESULT_ROW,0);mt9v03x_finish_flag_dvp = 0;}}
}

若想使用zf库函数显示需要针对指针略作更改,参考如下:

/**
*@Name          :ips114_show_gray_image_vec
*@Description   :ips114_show_gray_image_vec 显示透视变换指针所指的图像
*@Param         :
*@Return        :
*@Sample        :ips114_show_gray_image_vec(0,0,PerImg_ip,TRFED_COL,TRFED_ROW,TRFED_COL,TRFED_ROW,0);
**/
void ips114_show_gray_image_vec (uint16_t x, uint16_t y, uint8_t *p[][TRFED_COL], uint16_t width, uint16_t height, uint16_t dis_width, uint16_t dis_height, uint8_t threshold)
{zf_assert(x < ips114_x_max);zf_assert(y < ips114_y_max);uint32_t i = 0, j = 0;uint16_t color = 0,temp = 0;uint32_t width_index = 0, height_index = 0;ips114_set_region(x, y, x+dis_width-1, y+dis_height-1);                     // 设置显示区域for(j=0;j<dis_height;j++){height_index = j*height/dis_height;for(i=0;i<dis_width;i++){width_index = i*width/dis_width;temp = *p[height_index][width_index];                         // 读取像素点if(threshold == 0){color=(0x001f&((temp)>>3))<<11;color=color|(((0x003f)&((temp)>>2))<<5);color=color|(0x001f&((temp)>>3));ips114_write_16bit_data(color);}else if(temp < threshold)ips114_write_16bit_data(BLACK);elseips114_write_16bit_data(WHITE);}}
}

效果显示:

已知原图坐标情况下求透视后坐标

如果只想对边线或是某些点进行逆透视,在使用同样矩阵下,可以参考17届智能车-多车编队寻光测距_Wyean的博客-CSDN博客

6.资源文件

其中包含了测试图包

CSDN:https://download.csdn.net/download/wu58430/86399773

推荐github:https://github.com/wu58430/RUBO-IPM

如果只使用用途,下载github中Release即可。

现在已经完成了逆透视、去畸变、逆透视+去畸变的操作,除非程序有重大bug,后续不会考虑更新。此三种只是图片处理方法,如此软件只适用于简化和降低操作的门槛,以便大家共同进步,图像处理方法无好坏之分,但确实有精妙与粗糙之别。

版权声明:

此软件仅用于竞赛、学习交流,禁止任何商业用途,包括有营利性的、商业的教学指导活动。

7.更新日志

2022.8.23        修复了不同版本windows兼容问题

2022.8.27        修复中文路径、视图大小异常问题,缩小程序体积

2022.9.23        增加了彩色图像显示,输出格式改为数组

2022.10.7        代码迁移至QT6.3.1环境,加入去畸变,加入保存图片功能
        2022.10.29        融合两种方法,修复保存图像色彩错误问题

智能车图像处理逆透视教程相关推荐

  1. 智能车图像处理去畸变教程

    逆透视请参考:智能车逆透视教程(含上位机.源码)_Wyean的博客-CSDN博客  去畸变+逆透视请参考:智能车去畸变+逆透视教程_LoseHu的博客-CSDN博客 去畸变:如下 1.简介 对于镜头而 ...

  2. 【第十七届智能车】智能车图像处理(2)-赛道边界的简单提取和无元素循迹

    本博客使用的图像是188*120的大津法二值化图像.摄像头安装高度为25cm(离地),前瞻长度约1m. 智能车图像处理的过程就是读取输入的图像,经过处理后向控制部分输出一个偏差值,控制部分根据再这个偏 ...

  3. 智能车图像处理之透视变换

    透视变换介绍 透视变换被广泛应用于投影仪器.倒车影像等视觉设备当中.在智能车竞赛中,通过摄像头对赛道信息的采集,在单片机上提取赛道两边的边缘,经过处理后控制小车在赛道边缘内行驶.但由于摄像头与赛道之间 ...

  4. 智能车图像处理-阳光算法

    阳光算法见仁见智,多阈值OSTU和模糊OSTU是我参考论文进行改进的,整篇内容都放进了我的本科毕业论文中. 感谢大家的留言和指正,首先,这个算法经过实践,确实存在问题,因为当时毕业比较忙,我在智能车上 ...

  5. 智能车竞赛逆透视变换(含编程实现)

    在阅读本文之前,应该先阅读朱葛峻的<逆透视变换的一种方法>(下简称<方法>),本文的实现是基于这篇文章的推导的. 本文中提到的方法主要用于智能车竞赛.虽然在智能车有限的视野和像 ...

  6. 【第十七届智能车】智能车图像处理(1)-图像预处理

    本博客使用的硬件是逐飞总钻风130°无畸变摄像头,采用的图像分辨率为188*120,主控为CH32V307VCT6,使用DVI接口进行连接. 前言 我们在本次比赛中采用的是头尾车总钻风摄像头+中间车线 ...

  7. 智能车图像处理11-斜入十字补线

    前言 这篇文章主要讲述智能车竞赛中如何对于斜入十字进行补线操作. 一.代码 思路讲解: 补十字相较于 其他元素 是比较简单的 核心就是找十字路口: 四个拐点(也许看不到四个,比如斜入时可能只能看到一个 ...

  8. 智能车图像处理8-右环岛状态机与补线

    前言 这篇文章主要讲述智能车竞赛中如何判断右环岛并且进行状态补线. 一.函数主体 /* 注释1:环岛的八个状态 环岛分为八个状态.以右环岛为例,一二三状态都在未入环的直道上,这时候需要把右环岛的 中拐 ...

  9. 17届智能车图像处理部分讲解

    目录 须知 寻边线 寻拐点 补线 最后 须知 讲解代码使用的摄像头为总钻风摄像头,图像像素为188*120,图像进行了二值化,这里建议如果需要对光线有要求的同学使用灰度处理.没有使用过上位机,展示的图 ...

最新文章

  1. 2020-09-19
  2. redis源码笔记-endian
  3. C++day15 学习笔记
  4. mapreduce value 排序_MapReduce知识点一
  5. P5367 【模板】康托展开
  6. 在50亿信息泄露事件面前,Struts 2 漏洞和CIA泄密都是小事 | 宅客周刊
  7. Python 计算机视觉(十三)—— 图像的傅里叶变换
  8. Netty原理五:ChannelFuture、DefaultChannelPromise对象解析
  9. 基因在细胞系当中的表达数据库,CCLE使用简述
  10. C++ 文件头 static char THIS_FILE[] = __FILE__
  11. Win10 Edge浏览器续航碾压火狐/Chrome
  12. 一步一步写算法(开篇)
  13. centos activemq 集群配置 Networks of Brokers
  14. main()如果返回0,则代表程序正常退出,返回非零代表程序异常退出。
  15. 学python可以从事什么工作-学Python可以找什么工作或者做什么兼职?
  16. 怎么用计算机弹histheme,来至世界最好的器乐演奏大合集可做音乐素材-Various Artists 2015  (20CD)FLAC/MP...
  17. Python一个很好玩的特性decorator
  18. 以前计算机弹玻璃的游戏叫什么,小时候做过的游戏 你还记得多少 是否还有所保留呢...
  19. 虚拟机VMware的下载、安装与卸载
  20. 华为音频编辑服务实时变声,多种音色随意变换

热门文章

  1. 苹果传数据到苹果手机?iPhone怎么数据传输
  2. html鼠标手状态,css鼠标样式
  3. 中国“钱”途最光明10所大学
  4. 仓鼠找sugar II
  5. 十二 iOS之 折叠图片
  6. HTML 5 em strong dfn code samp kbd var cite 标签
  7. Torque引擎系列
  8. 【OpenJudge 1665】完美覆盖
  9. 操作系统中消费者与生产者的同步互斥问题
  10. 使用SendGrid宇宙函数发送电子邮件