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

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

首先是原始图像:

下图为逆透视变换图像:

下面说具体的实现吧!!

一、参数设置:

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

逆透视变换详解 及 代码实现(二)相关推荐

  1. 逆透视变换详解 及 代码实现(一)

    逆透视变换详解 及 代码实现(一) 中主要是原理的说明: 一.世界坐标轴和摄像机坐标轴 从下图中可以看到,世界坐标为(X,Y,Z)  相机坐标为(Xc,Yc,Zc) 而世界坐标变换到相机坐标存在一个旋 ...

  2. 逆透视变换详解 及 代码实现

    逆透视变换详解 及 代码实现(一) 中主要是原理的说明: 一.世界坐标轴和摄像机坐标轴 从下图中可以看到,世界坐标为(X,Y,Z)  相机坐标为(Xc,Yc,Zc) 而世界坐标变换到相机坐标存在一个旋 ...

  3. 【运筹优化】凸多面体重叠判断算法:GJK 算法详解 C++代码实现二维情形的凸多边形重叠判断

    文章目录 一.GJK 算法简介 二.前置知识 2.1 二维向量的点乘和叉乘 2.2 三维向量叉乘 2.3 凸多边形 2.4 闵可夫斯基差 2.5 单纯形 2.6 Support 函数 三.GJK 算法 ...

  4. 水平集详解与代码分析二

    上一节我们分析了CV模型的原理并列出了演化公式,这一节我们将通过该公式编写CV模型的C++代码,代码调用了opencv库的一些函数,可以根据自己使用的版本更改.代码一一对应公式里的各项系数. 头文件. ...

  5. 数学建模——一维、二维插值模型详解Python代码

    数学建模--一维.二维插值模型详解Python代码 一.一维插值 # -*-coding:utf-8 -*- import numpy as np from scipy import interpol ...

  6. 一文速学数模-时序预测模型(四)二次指数平滑法和三次指数平滑法详解+Python代码实现

    目录 前言 二次指数平滑法(Holt's linear trend method) 1.定义 2.公式 二次指数平滑值: 二次指数平滑数学模型: 3.案例实现 三次指数平滑法(Holt-Winters ...

  7. 三维空间刚体运动1:旋转矩阵与变换矩阵(详解加代码示例)

    三维空间刚体运动1:旋转矩阵与变换矩阵(详解加代码示例) 1. 点.向量和坐标系 2.坐标系间的欧式变换 2.1 旋转 2.2 平移 3.齐次坐标和变换矩阵 4. 相似.仿射和射影变换 4.1 相似变 ...

  8. 支付接口教程,详解支付宝接口(二)

    支付宝的接口向来集成过程都让人觉得比较舒服,只有APP支付相对复杂,但也只是配置上复杂一些,只要清楚原理相信也不是什么难事.下面是以前介绍双钥加密原理的传送门: 支付接口教程特别篇,公钥与私钥,双钥加 ...

  9. TOPSIS(逼近理想解)算法原理详解与代码实现

    写在前面: 个人理解:针对存在多项指标,多个方案的方案评价分析方法,也就是根据已存在的一份数据,判断数据中各个方案的优劣.中心思想是首先确定各项指标的最优理想值(正理想值)和最劣理想值(负理想解),所 ...

最新文章

  1. CVE-2019-0708复现
  2. 分区安装linux,怎样安装Linux?
  3. shell 字符串删除特定字符
  4. fcc无线充电认证_FCC规定了无线路由器固件,轮椅和胰岛素的开放状态以及更多新闻
  5. [机器学习] 机器学习中所说的“线性模型”是个什么东西?
  6. Android 资源(resource)学习小结
  7. 商务部:保障春节期间“菜篮子”供应充足、价格稳定
  8. 用VB实现自己的邮件“自己发”
  9. 【微信小程序】小程序代码基本组成结构
  10. html让ie11不用兼容视图,如何设置ie11浏览器兼容性视图?
  11. 有趣的符号图画(颜文字)(I have a AC dream)(神兽护体)(保佑你次次Accepted)
  12. 【论文翻译 AAAI 2020 | 知识图谱综述】A Survey on Knowledge Graphs: Representation, Acquisition and Applications
  13. 网页打印问题-页面显示不全
  14. NOIP 2018模拟赛 by zwz T3 磨懒虫主义
  15. docker 安装mysql,不区分大小写配置
  16. 什么是AudioEffect
  17. 如何通过instant client 来连接数据库以及使用exp/imp?
  18. 宿州计算机学院录取分,宿州学院录取分数线2021是多少分(附历年录取分数线)
  19. 队列的应用——短信模拟
  20. layui 使用laydate动态创建多个时间选择框

热门文章

  1. spark源码分析之Executor启动与任务提交篇
  2. Ubuntu抛弃了Untiy转向Gnome,美化之路怎么办?不用怕咱一步一步大变身!
  3. LNMP/LEMP(PHP7.0.04+mysql5.7.12+nginx1.10.0)
  4. 2012年3月编程语言排行榜:JavaScript超越Perl和Python
  5. select函数_SQL高级功能:窗口函数
  6. Hive的数据模型-管理表
  7. mysql启多_MySQL启多个实例
  8. c++输入一个整数判断是否为完全平方数_matlab判断一个整数是完全平方数
  9. [转载] public static void main(String[] args) 隐含了什么?
  10. julia fit 函数_带有Julia中示例的flipsign()函数