最近在学习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. ApacheCN JavaScript 译文集(二) 20211123 更新

    使用 Meteor 构建单页 Web 应用 零.前言 一.制作 Meteor 应用 二.构建 HTML 模板 三.存储数据和处理集合 四.控制数据流 五.使我们的应用与路由通用 六.保持会话状态 七. ...

  2. Redis 中如何保证数据的不丢失,Redis 中的持久化是如何进行

    Redis 中数据的持久化 前言 AOF 持久化 什么是 AOF 持久化 为什么要后记录日志呢 AOF 的潜在风险 AOF 文件的写入和同步 AOF 文件重写机制 AOF 的数据还原 RDB 持久化 ...

  3. express源码分析之Router

    express作为nodejs平台下非常流行的web框架,相信大家都对其已经很熟悉了,对于express的使用这里不再多说,如有需要可以移步到www.expressjs.com自行查看express的 ...

  4. Java开发调试技巧及Eclipse快捷键使用方法

    1. 快捷键 syso 通过打印输出来调试,println可接受object型的参数,能输出任何类型 Syso输出的是黑色字体,代表的是Debug的信息 Syse,输出的是红色字体,代表错误的输出信息 ...

  5. 如何快速为团队打造自己的组件库(下)—— 基于 element-ui 为团队打造自己的组件库

    文章已收录到 github,欢迎 Watch 和 Star. 简介 在了解 Element 源码架构 的基础上,接下来我们基于 element-ui 为团队打造自己的组件库. 主题配置 基础组件库在 ...

  6. 拔掉网线后, 原本的 TCP 连接还存在吗?

    大家好,我是小林. 今天,聊一个有趣的问题:拔掉网线几秒,再插回去,原本的 TCP 连接还存在吗? 可能有的同学会说,网线都被拔掉了,那说明物理层被断开了,那在上层的传输层理应也会断开,所以原本的 T ...

  7. Postman_JavaScript

    使用语法:JavaScript 结构: 测试工具主要包括三部分 在发起请求之前运行的Pre-request,预处理数据,作用:在发送请求前编辑请求数据,比如用户名或时间戳 对响应后的数据运行的Test ...

  8. Feign实现动态URL

    需求描述 动态URL的需求场景: 有一个异步服务S,它为其他业务(业务A,业务B...)提供异步服务接口,在这些异步接口中执行完指定逻辑之后需要回调相应业务方的接口. 这在诸如风控审核,支付回调等场景 ...

  9. 如何对Spring MVC中的Controller进行单元测试

    对Controller进行单元测试是Spring框架原生就支持的能力,它可以模拟HTTP客户端发起对服务地址的请求,可以不用借助于诸如Postman这样的外部工具就能完成对接口的测试. 具体来讲,是由 ...

  10. Solution -「CF 1622F」Quadratic Set

    \(\mathscr{Description}\)   Link.   求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...