三维重建是指获取真实物体的三维外观形貌,并建立可复用模型的一种技术。它是当下计算机视觉的一个研究热点,主要有三方面的用途:1)相比于二维图像,可以获取更全面的几何信息;2)在VR/AR中,建立真实和虚拟之间的纽带;3)辅助机器人更好的感知世界。传统的三维重建方法主要是SfM(Structure from Motion),通过一系列不同位置采集的图像,离线计算出三维模型。帝国理工和微软研究院在2011年提出的KinectFusion开启了用RGBD相机实时三维重建的序幕。本文主要参考KinectFusion的论文[1-2],解析它的算法流程。

  KinectFusion由四部分组成(图1):首先,处理采集到的原始深度图,获取点云voxel的坐标以及法向量坐标;接着,根据当前帧的点云和上一帧预测出的点云计算当前相机的位置姿态;然后,根据相机位置姿态更新TSDF值,融合点云;最后根据TSDF值估计出表面。

  KinectFusion用一群voxel来描述三维空间。它把固定大小的一个空间(比如\[3m\times3m\times3m\])均匀分割成一个个小方块(比如\[512\times512\times512\]),每个小方块就是一个voxel,存储TSDF值以及权重。具体算法如下文所示。

1. 原始数据的处理

  流程和公式如图2所示。先对原始深度图\[R_k\]进行滤波降噪,这里选择双边滤波,目的是保持清晰的边界。一般的滤波是在空间域做加权平均,像素越靠近中心点,权重越高。双边滤波是在空间域加权平均的基础上再对值域加权平均,即像素灰度值越靠近中心像素的灰度值,权重越高。在边界附近,灰度值差异很大,所以虽然边界两边的像素在空间域靠在一起,但是由于灰度值差别非常大,对于互相的权重很低,所以可以保持清晰的边界,如图3所示。

  拿到降噪后的深度图\[D_k\]之后,再根据相机内参\[K\],可以反投影出每个像素点的三维坐标,这就是Vertex map \[V_k\]。公式中\[u\]是像素坐标,\[\dot{u}\]是对应的齐次坐标。每个vertex的法向量可以很方便的通过相邻vertex用叉乘得到。然后对深度图降采样,行数、列数各减一半。降采样使用的是均值降采样,即深度图上四个相邻像素的深度值被平均成一个值。构建三层金字塔的目的是为了从粗到细地计算相机位置姿态,有加速计算的效果。

2. 相机位置姿态的估计

  相机的位置姿态是用ICP (Iterative Closest Point) 求解的。ICP是处理点云的常规手段,通过最小化两块点云的差别,迭代求解出拍摄两块点云的相机之间的相对位置。有不同的方式来描述点云的差别,最常用的是point-to-point和point-to-plane两种。KinectFusion选择的是point-to-plane的方式,要把点到点的距离向法向量投影,如图4所示。2001年的一篇论文[3]详细比较了point-to-point和point-to-plane的效果,结论是point-to-plane要比point-to-point收敛速度快很多,而且更鲁棒。图5列出了[3]中的Figure15和16,比较了在两种点云形貌的情况下不同ICP的收敛速度和残差。

  损失函数的公式中,\[T_{g,k}\]是第\[k\]帧图片时相机在世界坐标系下的位置姿态,这是优化求解的对象。\[\dot{V}_k(u)\]是第\[k\]帧深度图上像素\[u\]反投影出的vertex坐标,\[\hat{u}\]是这个vertex在第\[k-1\]帧图片的投影。为什么这里\[\hat{V}_{k-1}^{g}\](不知道为什么下标\[k-1\]上标\[g\]打不出来)有hat上标呢?因为这里的vertex并不是直接在第\[k-1\]帧深度图上,而是第\[k-1\]帧融合TSDF后的预测值。如果直接用第\[k-1\]帧的数据,那这就是frame-to-frame的方式,会带来累计误差。而实际采用的是frame-to-model的方式,误差小很多。为了加速计算,这里利用了三层金字塔,从粗到细计算,最大迭代次数分别是\[[4,5,10]\]。

3. TSDF的更新

  先介绍一个概念SDF(Signed Distance Function),SDF描述的是点到面的距离,在面上为0,在面的一边为正,另一边为负。TSDF(Truncated SDF)是只考虑面的邻域内的SDF值,邻域的最大值是max truncation的话,则实际距离会除以max truncation这个值,达到归一化的目的,所以TSDF的值在-1到+1之间,如图6所示。

  TSDF的具体算法也在图6中,利用GPU并行处理各个voxel。首先把每个voxel根据计算出的相机位置姿态投影到相机上,如果在相机的视椎内,则会有一个像素点和它对应,\[D_i(p)\]是这个像素点距离表面的实际测量值,\[t_i-v^g\]则是voxel到相机的距离,两者的差就是SDF值。然后用max truncation归一化得到当前TSDF值。接着,用加权平均的方式更新TSDF值。voxel越正对着相机(如图7所示),越靠近相机,权重越大,用公式表示就是:\[W(p)\propto cos(\theta)/R_k(u)\],\[u\]是\[p\]的像。但论文[1]中也提到把权重全部设为1,对TSDF做简单的平均,也可以取得很好的效果;而如图6算法第12行,设置max weight后,可以去除场景中动态物体的影响(这一点没有特别想明白)。

4. 表面的估计

  更新完TSDF值之后,就可以用TSDF来估计表面。这样估计出来的表面比直接用RGBD相机得到的深度图有更少的噪音,更少的孔洞(RGBD相机会有一些无效的数据,点云上表现出来的就是黑色的孔洞)。具体的表面估计方法叫Raycasting。这种方法模拟观测位置有一个相机,从每个像素按内参\[K\]投射出一条射线,射线穿过一个个voxel,在射线击中表面时,必然穿过TSDF值为一正一负的两个紧邻的voxel(因为射线和表面的交点的TSDF值为0),表面就夹在这两个voxel里面。然后可以利用线性插值,根据两个voxel的位置和TSDF值求出精确的交点位置。这些交点的集合就呈现出三维模型的表面。

参考文献:

[1] Newcombe R A, Izadi S, Hilliges O, et al. KinectFusion: Real-time dense surface mapping and tracking[C]//Mixed and augmented reality (ISMAR), 2011 10th IEEE international symposium on. IEEE, 2011: 127-136.

[2] Izadi S, Kim D, Hilliges O, et al. KinectFusion: real-time 3D reconstruction and interaction using a moving depth camera[C]//Proceedings of the 24th annual ACM symposium on User interface software and technology. ACM, 2011: 559-568.

[3] Rusinkiewicz S, Levoy M. Efficient variants of the ICP algorithm[C]//3-D Digital Imaging and Modeling, 2001. Proceedings. Third International Conference on. IEEE, 2001: 145-152.

KinectFusion解析的更多相关文章

  1. Kintinuous解析

    版权声明:本文为博主原创文章,未经博主允许不得转载. Kintinuous是Thomas Whelan在National University of Ireland Maynooth读博期间的工作,有 ...

  2. 转:SLAM算法解析:抓住视觉SLAM难点,了解技术发展大趋势

    SLAM(Simultaneous Localization and Mapping)是业界公认视觉领域空间定位技术的前沿方向,中文译名为“同步定位与地图构建”,它主要用于解决机器人在未知环境运动时的 ...

  3. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  4. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  5. Html Agility Pack 解析Html

    Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面  用Fir ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  8. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  9. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

随机推荐

  1. OC学习9——反射机制

    1.OC提供了3种编程方式与运行环境进行交互: 直接通过OC的源代码:这是最常见的方式,开发人员只是编写OC源代码,而运行环境负责在后台工作. 通过NSObject类中定义的方法进行动态编程:因为绝大 ...

  2. APP的线程安全

    一般来说iOS中两个就够了,但是安卓中的第三个,iOS也是要注意的: 第一:网络方面,别人以为做数据请求用post会比get请求安全,但是这是错的,post请求虽然看起来你的请求是在请求体上,不像ge ...

  3. [置顶] xamarin android 布局尺寸了解

    为了使UI界面在不同大小的移动端显示器上能够正常显示,大家可能都知道使用sp作为字体大小的单位,dp作为其他元素长度的单位. 前几天看了一篇文章关于 App设计规范的,文章用心写的非常好,这里是链接  ...

  4. bzoj 4446: [Scoi2015]小凸玩密室

    Description 小凸和小方相约玩密室逃脱,这个密室是一棵有n个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯 泡即可逃出密室.每个灯泡有个权值Ai,每条边也有个权值bi.点亮第1个灯泡不需要 ...

  5. Docker(八):Docker端口映射

    1.随机映射 docker run -P -d --name mynginx1 nginx [root@node1 ~]# docker ps -l CONTAINER ID IMAGE COMMAN ...

  6. pstree 命令详解

    作用: 以命令树状图的方式展现进程之间的派生关系, 显示效果比较直观. 选项: -a 显示每个程序的完整指令, 包含路径, 参数或者是常驻服务的标志 -c 不使用精简标示法 -h 列出树状图,特别标明 ...

  7. 在Ubuntu 12.04系统中安装配置OpenCV 2.4.3的方法

    在Ubuntu 12.04系统中安装配置OpenCV 2.4.3的方法   对于,在Linux系统下做图像识别,不像在windows下面我们可以利用Matlab中的图像工具箱来实现,我们必须借助Ope ...

  8. SQL基础学习_06_集合运算和联结

    集合运算 1. 并集:UNION     例:     SELECT shohin_id, shohin_mei    FROM Shohin    UNION    SELECT shohin_id ...

  9. 使用plenv安装perl,并使其支持多线程

    plenv与pyenv.rbenv等都是同类型软件中非常好用的,这三个软件不仅命名类似,操作方式也相差无几,节约了很多学习的成本,所以非常推荐: 安装使用plenv: git clone git:// ...

  10. Node.js 蚕食计划(五)—— Koa 基础项目搭建

    Koa 是由 Express 原班人马打造的超轻量服务端框架 与 Express 相比,除了自由度更高,可以自行引入中间件之外,更重要的是使用了 ES6 + async,从而避免了回调地狱 不过也是因 ...