逆透视变换详解 及 代码实现(二)

根据 逆透视变换详解 及 代码实现(一)的原理

下面我用车上拍摄的车道图像,采用逆透视变换得到的图像,给出代码前我们先看下处理结果。

 

首先是原始图像:

下图为逆透视变换图像:

 

下面说具体的实现吧!!

一、参数设置:

1、需要知道相机的内部参数(这个具体步骤可以找相关文档,这里就不具体展开说)。

我们这里假设已经获取内部参数:

相机焦距,相机光学中心, 相机高度, 相机的俯仰角, 相机的偏航角, 相机拍摄出的图像尺寸。

参数说明:  其中偏航角 俯仰角 就是在(一)中所说的世界坐标经过旋转矩阵得到相应的相机坐标。  而偏航角和俯仰角将决定这个旋转矩阵。  而相机焦距  和相机光学中心 是可以从相机标定后得出 ,相机高度需要自己测量。

图像尺寸,是拍出图像的尺寸。

2、 设定逆透视变换的参数:

逆透视图像的尺寸,需要进行逆透视变换的区域,逆透视变换的差值算法。

逆透视变换的区域:原始图像中需要变换的区域(当然这个区域不能超过消失点区域,后面会说到)

逆透视图像的尺寸: 就是需要将逆透视变换区域映射到这个逆透视图像上。

差值算法:因为需要映射,所以某些数值需要估计出,这里用双线性差值。

 

二、

根据相机的内部参数计算消失点:

因为图像是二维的,所以消失点是是一个二维坐标。

code:

 

function [ vp ] = GetVanishingPoint( cameraInfo )
%GetVanishingPoint Summary of this function goes here
%   Detailed explanation goes herevpp = [ sin(cameraInfo.yaw*pi/180)/cos(cameraInfo.pitch*pi/180);cos(cameraInfo.yaw*pi/180)/cos(cameraInfo.pitch*pi/180);0];tyawp = [cos(cameraInfo.yaw*pi/180), -sin(cameraInfo.yaw*pi/180), 0;         sin(cameraInfo.yaw*pi/180), cos(cameraInfo.yaw*pi/180), 0;0, 0, 1];tpitchp = [1, 0, 0;0, -sin(cameraInfo.pitch*pi/180), -cos(cameraInfo.pitch*pi/180);0, cos(cameraInfo.pitch*pi/180), -sin(cameraInfo.pitch*pi/180)];transform = tyawp*tpitchp;t1p = [cameraInfo.focalLengthX, 0, cameraInfo.opticalCenterX;0, cameraInfo.focalLengthY, cameraInfo.opticalCenterY;0, 0, 1];
transform = t1p*transform;vp = transform*vpp;end


三、利用消失点可以得到uv平面中的图像范围和对应的xy平面的范围

 

code:

 

uvLimitsp = [ vp.x,         ipmInfo.ipmRight, ipmInfo.ipmLeft,  vp.x;ipmInfo.ipmTop, ipmInfo.ipmTop, ipmInfo.ipmTop,   ipmInfo.ipmBottom];xyLimits = TransformImage2Ground(uvLimitsp,cameraInfo);

 

function [ xyLimits ] = TransformImage2Ground( uvLimits,cameraInfo )
%TransformImage2Ground Summary of this function goes here
%   Detailed explanation goes here
[row , col ] = size(uvLimits);
inPoints4 = zeros(row+2,col);
inPoints4(1:2,:) = uvLimits;
inPoints4(3,:) = 1;
inPoints3 = inPoints4(1:3,:);c1 = cos(cameraInfo.pitch*pi/180);
s1 = sin(cameraInfo.pitch*pi/180);
c2 = cos(cameraInfo.yaw*pi/180);
s2 = sin(cameraInfo.yaw*pi/180);matp= [-cameraInfo.cameraHeight*c2/cameraInfo.focalLengthX,cameraInfo.cameraHeight*s1*s2/cameraInfo.focalLengthY,(cameraInfo.cameraHeight*c2*cameraInfo.opticalCenterX/cameraInfo.focalLengthX)- (cameraInfo.cameraHeight *s1*s2* cameraInfo.opticalCenterY/ cameraInfo.focalLengthY) - cameraInfo.cameraHeight *c1*s2;cameraInfo.cameraHeight *s2/cameraInfo.focalLengthX, ...cameraInfo.cameraHeight *s1*c2/cameraInfo.focalLengthY, ...(-cameraInfo.cameraHeight *s2* cameraInfo.opticalCenterX ..../cameraInfo.focalLengthX)-(cameraInfo.cameraHeight *s1*c2* ....cameraInfo.opticalCenterY /cameraInfo.focalLengthY) -  ...cameraInfo.cameraHeight *c1*c2;0, cameraInfo.cameraHeight *c1/cameraInfo.focalLengthY, (-cameraInfo.cameraHeight *c1* cameraInfo.opticalCenterY/cameraInfo.focalLengthY)+cameraInfo.cameraHeight*s1;0, -c1 /cameraInfo.focalLengthY,(c1* cameraInfo.opticalCenterY /cameraInfo.focalLengthY) - s1];inPoints4 = matp*inPoints3;
inPointsr4 = inPoints4(4,:);
div = inPointsr4;
inPoints4(1,:) = inPoints4(1,:)./div;
inPoints4(2,:) = inPoints4(2,:)./div;
inPoints2 = inPoints4(1:2,:);
xyLimits = inPoints2;end


四、根据得到的范围计算xy平面的一一对应的映射

 

 

row1 = xyLimits(1,:);
row2 = xyLimits(2,:);
xfMin = min(row1); xfMax = max(row1);
yfMin = min(row2); yfMax = max(row2);[outRow outCol] = size(outImage);
stepRow = (yfMax - yfMin)/outRow;
stepCol = (xfMax - xfMin)/outCol;
xyGrid = zeros(2,outRow*outCol);
y = yfMax-0.5*stepRow;for i = 1:outRowx = xfMin+0.5*stepCol;for j = 1:outColxyGrid(1,(i-1)*outCol+j) = x;xyGrid(2,(i-1)*outCol+j) = y;x = x + stepCol;endy = y - stepRow;
end


五、将xy平面的映射转换到uv平面,并画出这个映射

 

 

%TransformGround2Image
uvGrid = TransformGround2Image(xyGrid,cameraInfo);
% Image mean 
means = mean(R(:))/255;
RR = double(R)/255;
for i=1:outRowfor j = 1:outCol;ui = uvGrid(1,(i-1)*outCol+j);vi = uvGrid(2,(i-1)*outCol+j);if (ui<ipmInfo.ipmLeft || ui>ipmInfo.ipmRight || vi<ipmInfo.ipmTop || vi>ipmInfo.ipmBottom) outImage(i,j) = means;elsex1 = int32(ui); x2 = int32(ui+1);y1 = int32(vi); y2 = int32(vi+1);x = ui-double(x1) ;  y = vi-double(y1);val = double(RR(y1,x1))*(1-x)*(1-y)+double(RR(y1,x2))*x*(1-y)+double(RR(y2,x1))*(1-x)*y+double(RR(y2,x2))*x*y;outImage(i,j) = val;endend
end


最终可以显示这个图像:如上面的逆透视变化图像!

 

具体的code,可以在这里下载。如果问题可以留言交流!!

 

##修改时间2019-01-23##begin##

鉴于目前csdn下载积分需求比较高,我把代码挂在github上

 https://github.com/yeyang1021/matlab_IPM 

##修改时间2019-01-23##end##

 

另外,如果需要标定相机的可以参考这篇博文:

http://blog.csdn.net/yeyang911/article/details/52382722

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/549351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[赵星理]《简单男人》--歌曲温暖你的心,激励你前进

简单的男人&#xff0c;简单的歌曲&#xff0c;赵星理《简单男人》送给所有身负家庭责任的人&#xff0c;要让家越来越美&#xff0c;再苦再累也不能后退。加油&#xff01;简单男人词曲&#xff1a;赵星理演唱&#xff1a;赵星理累不累也不许落泪醉不醉苦辣都值得回味要让家越…

ArrayList list = new ArrayList(20);中的list扩充几次

16. ArrayList list new ArrayList(20);中的list扩充几次&#xff08;&#xff09; A 0 B 1 C 2 D 3 答案&#xff1a;A ArrayList动态扩容机制 初始化&#xff1a;有三种方式 默认的构造器&#xff0c;将会以默认的大小来初始化内部的数组&#xff1a;public …

利用ATL创建com组件和如何在程序中使用组件的接口函数和设置接口的属性

这是一个ATL开发实例的流程&#xff1a; 1. 在atl中插入一个atl实例&#xff0c;然后添加一个类&#xff0c;派生自ccmdtarget。 2. 添加相应的属性或者方法&#xff0c;在这里需要明白一点的是&#xff0c;这个属性和方法其实是一个概念&#xff0c;只是添加一个属…

java 课外练习题

1.下列哪些是Thread类中的方法&#xff08;&#xff09; A start() B run() C exit() D getPriority() 解析&#xff1a;线程的就绪状态&#xff1a;新建线程后start()方法的调用&#xff0c;来启动线程&#xff0c;但此时线程并没有进入运行状态&#xff0c;只是…

关于ubuntu 是否需要使用std::到问题。

首先是在ubuntu下编译c要使用g&#xff0c;比如 g -Wall 01knap2.cpp -o 01knap2 而如果是编译c语言文件的话则需要用 gcc -Wall 01knap2.c -o 01knap2 即可&#xff0c;g编译得到的是.cpp文件&#xff0c;而gcc编译得到的是.c文件。 第二个是关于是否能够直接使用cout&#…

对一道基础string题及其变式题的思考与解析

1、下面程序的运行结果是&#xff08;&#xff09;&#xff08;选择一项&#xff09; String str1“hello”; String str2new String(“hello”); System.out.println(str1str2); A.true B.false C.hello D.he 答案&#xff1a;B 分析&#xff1a;str1没有使用new关键字&am…

Redo Log 和Checkpoint not complete

首先我们来看下 alertSID.log 日志&#xff1a; Mon Nov 30 17:31:54 2009 Thread 1 advanced to log sequence 14214 (LGWR switch) Current log# 3 seq# 14214 mem# 0: /u03/oradata/newccs/redo03.log Mon Nov 30 17:34:29 2009 Thread 1 advanced to log sequence 14215 (L…

组合数学中的项链计数

给c种不同颜色宝石能穿成多少种长度为s的宝石项链&#xff08;本质不同&#xff09; Burnside定理的应用&#xff1a; 当n为奇数时&#xff0c;有n种翻转&#xff0c;每种翻转都是以一个顶点和该顶点对边的中点对称。有k^(n/21)*n种。 当n为偶数时&#xff0c;有n种翻转&#x…

蓝桥杯 算法训练(四)结点选择(树形动态规划)

结点选择&#xff08;树形动态规划&#xff09;C语言 问题描述 有一棵 n 个节点的树&#xff0c;树上每个节点都有一个正整数权值。如果一个点被选择了&#xff0c;那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少&#xff1f; 输入格式 第一行包含一个整数…

SCVMM

通过SCVMM实现并管理虚拟机高可用性 1、 添加群集主机2、 创建虚拟网络3、 创建虚拟机并实现高可用性接着上一篇文章&#xff0c;这次我们来看一下&#xff0c;如果通过SCVMM R2来实现虚拟机的高可用性。首先将群集主机添加到SCVMM 1、 登陆到计算机Win2008R2&#xff0c;打开S…

机器学习统计学相关书籍

1. 《统计学完全教程》 All of statistics 卡耐基梅隆 沃塞曼 2. 第四版《概率论与数理统计》 莫里斯。德格鲁特&#xff08;Morris H.DeGroot&#xff09;和马克。舍维什&#xff08;Mark J.Shervish&#xff09; 3. 《线性代数导论》 吉尔伯特。斯特朗--网上视频教程堪称经…

序列化包含多种不明类型的集合

序列化包含多种不明类型的集合 代码&#xff1a;/Files/zhuqil/Kirin.rar 导言: 你是否曾经想过序列化构造对象&#xff0c;它里面有一个集合&#xff0c;这个集合包含接口或者抽象类&#xff1f;你是否不知道所有的你要序列化的类型&#xff1f;好吧&#xff0c;如果这样&…

机器学习入门方法推荐(少走弯路)入门视频推荐

入门可以看看下列的几个课程。第一第二个公认的经典了。1、首先当然是吴恩达的经典机器学习了&#xff0c; 可以在万能的b站搜&#xff0c;也可以在网易公开课搜 吴恩达机器学习http://study.163.com/course/courseMain.htm?courseId10045700292、台大林轩田教授的机器学习基石…

NLP大神推荐的机器学习入门书单(附大量百度网盘电子书)

转载自&#xff1a;http://blog.csdn.net/surgent777/article/details/53895048 继NLP之后&#xff0c;我又开了ML这个大坑。这是因为NLP涉及到太多的ML模型&#xff0c;仅仅拿过来用的话&#xff0c;我实现的HanLP已经快到个人极限了。而模型背后的原理、如何优化、如何并行化…

$HOME/$user/.权限导致用户无法登陆图形界面

在redhat linux下&#xff0c;用户登陆图形界面时将在$HOME/$user/.目中添加隐藏文件&#xff08;以.开头的文件&#xff09;&#xff0c;如果在无意中将$HOME/$user/.的写权限去除&#xff0c;将会导致用户无法成功登陆gnome&#xff0c;在正确输入用户名和密码的情况下&#…

想要入坑机器学习?这是MIT在读博士的AI心得

从科研社区中汲取营养找论文AI 领域的论文可以在 arXiv 上找到和发布。现在的论文数量非常令人振奋。社区中的许多人降低了从噪声中分辨出信号的难度。Andrej Karpathy 开发了 arXiv sanity preserver&#xff0c;帮助分类、搜索和过滤特征。Miles Brundage 每晚都在推特上发布…

修改EIGRP 路径cost 值,以及分析和实现等价与非等价负载均衡

一、拓扑图&#xff1a;二、配置各路由器的IP和EIGRP 协议&#xff0c;并保证邻接关系的形成。1、我要达到的目的是要让R2到192.168.14.0/24这个网段能在R2和R1断开之后&#xff0c;形成网网络的快速收敛。因为根据EIGRP 的次优路径进拓扑关系的形成条件是要满足FC&#xff08;…

C++函数的用法:erase函数

前面的文章中提到过如何向容器中添加元素&#xff0c;这里介绍一个如何删除容器中元素的函数&#xff0c;包括顺序容器和关联容器。 就是这个erase函数&#xff0c;基本用法如下&#xff1a; c.erase(p)------------------------------从c中删除迭代器p指定的元素&#xff0c;…

关注BLUEBEE的浏览器发展

其实我并不认识蓝峰这个人。只是偶尔发现这个人在我的博客中转了一下。怀着好奇的心情回访了一下。发现此人正在开发浏览器。目前IE内核的浏览器实在太多了。除了IE本身如遨游&#xff0c;世界之窗&#xff0c;包括360&#xff0c;还有腾讯的TT。。。。。但我为什么要关注蓝峰的…