三维重建是指获取真实物体的三维外观形貌,并建立可复用模型的一种技术。它是当下计算机视觉的一个研究热点,主要有三方面的用途: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. 理解Object.defineProperty()

    理解Object.defineProperty() Object.defineProperty() 方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象. 基本语法:Obj ...

  2. SpringMVC随笔记录

    在web.xml里可以配置webapp的默认首页,格式如下: <welcome-file-list> <welcome-file>index.html</welcome- ...

  3. 【Uva623】500!(高精)

    Description 求N! \(N \leq 1000\) Sample Input 10 30 50 100 Sample Output 10! 3628800 30! 265252859812 ...

  4. 使用 webpack 打包 font 字体的问题

    之前在使用 Vue 做项目的时候使用了 font 字体,然而在打包的时候 font 字体的引用路径不正确. 解决办法就是在 webpack 的配置文件中设置根路径 目录在 \config\index. ...

  5. 大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解

    引言 在之前的大数据学习系列中,搭建了Hadoop+Spark+HBase+Hive 环境以及一些测试.其实要说的话,我开始学习大数据的时候,搭建的就是集群,并不是单机模式和伪分布式.至于为什么先写单 ...

  6. C语言中一些不被熟知的特性

    designated initializers(c99) C99允许你对结构体中指定的变量初始化,如 struct Foo { int x; int y; int z; }; }; 指定初始化也可适用 ...

  7. 每周.NET前沿技术文章摘要(2017-05-10)

    汇总国内外.NET社区相关文章,覆盖.NET ,ASP.NET和Docker容器三个方面的内容: .NET Debugging .NET core with SOS everywhere 链接:htt ...

  8. mvn命令笔记

    #发布到本地仓库 mvn deploy -DaltDeploymentRepository=snapshots::default::http://mvnrepo.xxx.com/mvn/snapsho ...

  9. ArcGIS API for JavaScript 4.2学习笔记[31] (补充学习)Task类

    Task这个东西很有用,是AJS中用于解决各种乱七八糟任务的一个类.它有很多子类,有用于空间分析的,有用于空间查询的,等等. 这篇作为补充学习的第一篇,也是进阶学习的第一篇,我就改个写法. 我将使用思 ...

  10. 虚拟机创建流程中neutron代码分析(一)

    前言: 在openstack的学习当中有一说法就是网络占学习时间的百分之七十.这个说法或许有夸大的成分,但不可否认的是openstack中的 网络是及其重要的部分,并且难度也是相当大.试图通过nova ...