最近在学习DIBR并尝试实现。感觉网上相关资料比较少,大多还是爬虫,决定自己写一个。

DIBR就是depth image based rendering问题。输入一个视角下的图像和深度图,要求你输出另外一个虚拟视角下的图像(当然两个视角的内外参矩阵都有办法通过已知信息求得)。

总共分三步:内参提取 和 外参提取 ,以及DIBR的主过程。这里按照网上其他博客的顺序,先介绍内参提取。看的过程中注意坐标系的定义。由于是第一次接触,这里我采用的坐标系可能和常规的坐标系不太一样。

开始之前先介绍一些定义(基于我自己实现算法的时候所使用的数据集):

\((u,v,1)^T\)为一个点的像素坐标。

\((x,y,1)^T\)为一个点在图像平面上以物理距离衡量的坐标。

\((X,Y,Z)\)为一个点在相机坐标系下的坐标。

\((X_w,Y_w,Z_w)\)为一个点在世界坐标系下的坐标。

\(f_x、f_y\)分别表示X轴的焦距和Y轴的焦距(非理想情况下横向和纵向的焦距是不一样的)。

\(d_x、d_y\)分别表示X轴(对应于图像的U轴)和Y轴(对应于图像的V轴)每个像素的物理尺寸(一个像素实际有多长)。

\(p_u、p_v\)表示相机的主点(principal point,就是相机主轴与成像平面的交点)在图像中的位置(以像素为单位)。

像素纵横比:\(pixel\ aspect\ ratio\)。表示像素的实际尺寸的高与宽之比。

主点:\(principal\ point\)。是一个二维向量,表示相机主光轴与成像平面的交点。这里以像素为单位在图像上进行刻画。

相机位置\((position_x,position_y,position_z)\)

焦距\(focal\ length\)

相机姿态(朝向)\(camera\ orientation\)。为一个三维向量,通常可用欧拉角、轴角、四元数等方式表示。这里采用的是轴角表示法。

后面的公式可以对照着这个表来看。

内参提取

内参提取就是求从相机坐标系到最终像素图像的变换。

在看具体的矩阵之前,先看一下怎么推的。

根据透视模型(这里就不赘述了)有:

那么就用\(\frac{y}{f}=\frac{Y}{Z}\)即\(y=\frac{fY}{Z}\)。对于x同理。

那么图像平面上的坐标(以物理长度衡量)就是\((x,y,1)=(\frac{fX}{Z},\frac{fY}{Z},1)\)。这里采用齐次坐标。表示为\((fX,fY,Z)\)。

再映射到以像素为单位的坐标系下:



就是\(u=\frac{x}{d_x}+p_u\),v同理。那么就有\((u,v)^T=(\frac{x}{d_x}+p_u,\frac{y}{d_y}+p_v,1)\)。同样使用齐次坐标有:\((Zu,Zv,Z)=(\frac{fX}{d_x},\frac{fY}{d_y},Z)\)。后面的推理都是在齐次坐标下进行的。

接下来写出矩阵乘法的形式:

定义\(K'=\left[ \begin{matrix} f_x & 0 & 0 \\ 0 & f_y & 0 \\ 0 & 0 & 1 \end{matrix} \right]\)用于从相机坐标系转移到图像平面上的坐标系(以图片的物理尺度进行衡量,还不是像素尺度,不妨设为V坐标系)

定义\(C=\left[ \begin{matrix} \frac{1}{d_x} & 0 & p_u \\ 0 & \frac{1}{d_y} & p_v \\ 0 & 0 & 1 \end{matrix} \right]\)为从V坐标系映射到图像坐标系(以像素为尺度)

定义\(K=C*K'=\left[ \begin{matrix} \frac{f_x}{d_x} & 0 & p_u \\ 0 & \frac{f_y}{d_y} & p_v \\ 0 & 0 & 1 \end{matrix} \right]\)。 这就是我们的内参矩阵。即

其中,\(\frac{f_x}{d_x}、\frac{f_y}{d_y}\)可由定义的\(par=pixel\ aspect\ ratio\)(像素纵横比)得到。我手上的数据集给出的焦距(focal length)是以像素为单位的,应该默认是给出\(focal\ length=\frac{f_x}{d_x}\)。那么\(\frac{f_y}{d_y}=\frac{f_x}{d_x}\x par\)。也就不需要我们去计算\(d_x、d_y\)了,毕竟jpg格式的解压不是人人都会的,opencv貌似也无法直接读出图像的分辨率信息(至少我没有查到)。

外参提取

外参提取就是求从世界坐标系到相机坐标系的变换。

这里把变换拆分为旋转变换和平移向量。

先来看看平移变换,这个很好写:

相机位置是\((p_x,p_y,p_z)\)(变量名有点重复,见谅见谅),那么就有平移向量:

\(C=(-p_x,-p_y,-p_z)^T\)。\((X_w,Y_w,Z_w)^T+C\)就能够实现平移了。

接下来看旋转变换

这里的原理还没怎么搞懂,后面再来补上,先把做法说了。

输入给的是轴角表示(axis-angle),文章给出的实现是,先转化为四元数,再用四元数进行旋转。(我的评价是,不如直接用欧拉角,这好复杂...)

首先将axis和angle转化为四元数。设axis=\((a,b,c)^T\)。得到的四元数是\(q=(a,b,c,w)^T\)。不妨设axis是单位向量。

那么有\(q=(sin(\frac{angle}{2})axis,cos(\frac{angle}{2}))^T\)。

下面用四元数得到旋转矩阵。不妨设q已经经过了单位化。

那么有:

最后就有\((X,Y,Z)^T=R((X_w,Y_w,Z_w)^T+C)\)

DIBR的核心步骤

有了两个视角下分别的内参和外参之后怎么做呢?这其实是最简单的一步。

\(Z(u,v,1)^T=KR((X_w,Y_w,Z_w)^T+C)\)

这对于两个视角下都是成立的:

\(Z_1p_1=K_1R_1(P+C_1)\)

\(Z_2p_2=K_2R_2(P+C_2)\)

用第一个式子把P求出来:

\(P=(K_1R_1)^{-1}Z_1p_1-C_1\)

再带到第二个式子里,最后把\(Z_2p_2\)弄成p2=(u,v,1)的形式就可以了。最后一步就是把p1对应的像素直接赋给p2即可。

注意:这里的Z_1,Z_2指的就是深度,所以才需要深度作为输入。这样看来,也能通过DIBR得到输出图像的深度信息。

这里写的时间不长,写的比较粗糙,如果有问题敬请指出。有时间我会回来把四元数的推导补上的。

参考:https://blog.csdn.net/u010922186/article/details/40683129

【OpenCV】【计算机图形学】DIBR: Depth Image Based Rendering/ 3D image warping 中的实现细节的更多相关文章

  1. [图形学] 计算机图形学 with OpenGL开篇

    <计算机图形学>(第四版)正在学习中,学习目的是为了在Unity中使用shader实现不同的渲染效果. 希望在这里能把学习过程中学到的知识和遇到的问题记录下来. 工作环境是:Xcode 8 ...

  2. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  3. Mathematics for Computer Graphics数学在计算机图形学中的应用 [转]

    最近严重感觉到数学知识的不足! http://bbs.gameres.com/showthread.asp?threadid=10509 [译]Mathematics for Computer Gra ...

  4. 计算机图形学学习方法和相关书籍,做游戏,GIS,虚拟现实,三维引擎的都能够看看.

    本书參照<<图形学扫盲>> 整理的,原文内容引子: http://www.cppblog.com/lai3d/archive/2008/12/30/70796.html 前言: ...

  5. 64 计算机图形学入门(1)——OpenGL环境配置与图形流水线(图像管线)

    0 引言 最近想学一下计算机图形学方面的知识,原因如下.目前本人接触了数字图像处理(opencv)以及点云处理(PCL)方面的知识,对从图像和点云中提取特征信息,并将特征转化为底层/中层语义信息有了一 ...

  6. 关于opengl中的矩阵平移,矩阵旋转,推导过程理解 OpenGL计算机图形学的一些必要矩阵运算知识

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12166896.html 为什么引入齐次坐标的变换矩阵可以表示平移呢? - Yu Mao的回答 ...

  7. 计算机图形学 - 图形变换(opengl版)

    作业题目: 图形变换:实现一个图形绕任意直线旋转的程序. 要求:把一个三维图形绕任意一条直线旋转,需要有初始图形,和旋转后的图形,最好也可以实时控制旋转. 最少要做出绕z轴旋转. 原理:http:// ...

  8. 【3D计算机图形学】变换矩阵、欧拉角、四元数

    [3D计算机图形学]变换矩阵.欧拉角.四元数 旋转矩阵.欧拉角.四元数主要用于:向量的旋转.坐标系之间的转换.角位移计算.方位的平滑插值计算.   一.变换矩阵: 首先要区分旋转矩阵和变换矩阵: 旋转 ...

  9. 计算机图形学(第2版 于万波 于硕 编著)第45页的Bresenham算法有错误

    计算机图形学(第2版 于万波 于硕 编著)第45页的Bresenham算法有错误: 书上本来要写的是以x为阶越步长的方法,但是他写的是用一部分y为阶越步长的方法(其实也写的不对),最后以x为阶越步长的 ...

随机推荐

  1. SP5971 LCMSUM - LCM Sum

    一个基于观察不依赖于反演的做法. 首先 \(\rm lcm\) 是不好算的,转化为计算 \(\rm gcd\) 的问题,求: \[\sum\limits_{i = 1} ^ n \frac{in}{\ ...

  2. HTML 5的革新——语义化标签

    感谢原文作者:html5jscss 原文链接:http://www.html5jscss.com/html5-semantics-section.html 大佬的下一篇博文:http://www.ht ...

  3. 为什么内部类调用的外部变量必须是final修饰的?

    感谢原文:https://blog.csdn.net/u010393325/article/details/80643636 因为生命周期的原因.方法中的局部变量,方法结束后这个变量就要释放掉,fin ...

  4. JavaWeb编码浅解

    感谢原文作者:少年无形 原文链接:https://blog.csdn.net/dl18215164175/article/details/72512131?depth_1-utm_source=dis ...

  5. ansible学习(一)

    基础概念 ansible是什么? 它是一个"配置管理工具",它是一个"自动化运维工具",如果你没有使用过任何配置管理工具,不要害怕,看完这篇文章,你自然会对an ...

  6. curl: (6) Could not resolve host: mirrors.163.com; Unknown error 服务器上解析不了域名,换成ip可以

    原因是DNS域名解析问题: 添加nameserver即可解决 echo nameserver 8.8.8.8 > /etc/resolv.conf 解释一下DNS服务 DNS(Domain Na ...

  7. php include,require,include_once,require_once 的区别

    include(),require(),include_once(),require_once()作用都是包含并运行指定文件,但是使用场景又有很大区别. 1.include()和require()的区 ...

  8. endl与\n的用法区别

    学习C++的时候,老师说换行有两种写法. 1 //方法一 2 3 std::cout<<"你好!\n李华"; 4 5 //方法二 6 7 std::cout<&l ...

  9. Shell脚本之编程规范和变量

    Shell脚本编程规划和变量 1.Shell脚本概述 2.Shell编程规划 3.重定向与管道 4.Shell脚本变量 1.Shell脚本概述 Shell的作用:充当"翻译官"的角 ...

  10. FastJSON解析Json字符串(反序列化为List、Map)

    在日常开发与数据库打交道的时候,常有以Json格式的字符串存储到数据库的情况,当在Java程序中获取到对应的Json格式的String字符串后,如何才能转换为我们想要的数据格式(比如转换成Java中的 ...