论文信息:Newcombe R A, Izadi S, Hilliges O, et al. KinectFusion: Real-time dense surface mapping and tracking[C]//2011 10th IEEE International Symposium on Mixed and Augmented Reality. IEEE, 2011: 127-136.
由于这篇论文首次提出TSDF这种三维模型表示形式,其中难免有许多公式化的表达,作为一个初学者,我首先只能通读大概了解方法的思路,然后结合网上一些优质的解读文章才大致理解其公式化的表达。
本篇文章就先作为一个“文字纯享版”,做一个论文内容的梳理,也供希望了解KinectFusion以及TSDF大致思想的人进行参考。至于详细的理论部分,我会再开一篇“公式推导版”进行重点解释(又挖一个坑)。
摘要
本文提出的实时建图系统,使用移动的深度相机和GPU,可以在可变照明条件下准确绘制室内任意场景的地图,重建结果是稠密表面,便于展示以及AR应用。当前的相机位姿也在同步更新,位姿估计考虑了已采集的所有深度信息,而不仅仅是上一帧。
主要亮点有:
- ·提出TSDF这种模型表示形式,使得模型易于更新,且易于以表面形式展示
- ·当前帧的相机位姿估计考虑了所有的历史信息,而不仅仅是相对上一帧进行相对位姿估计,在位姿估计精度上有所提升
- ·第一个允许手持KinectFusion进行实时稠密的容积重建
背景介绍
SFM(Structure from Motion)和MVS(Multi-view stereo)可以提供准确的相机跟踪、稀疏重建结果以及增量式的稠密表面重建结果,但是这些方法都不是面向实时应用场景的。
SLAM(Simultaneous Localization and Mapping)技术基于一个单目相机对动态场景进行实时的相机跟踪以及地图构建,这类方法主要是为了高效的相机跟踪而优化,其重建的地图是稀疏点云只能算是初步的场景重建结果。
基于单目相机的实时稠密三维重建的挑战在于相机运动的估计以及对场景照明的要求。新的深度相机如ToF(Time-of-Flight)和结构光传感器适用于这项任务,但是现有的算法并没有充分利用这类设施提供的数据和数据采集速度。
这篇文章提出了第一个允许手持KinectFusion进行实时稠密的容积重建的方法,仅仅使用深度信息,可以连续跟踪相机的6自由度位姿,并将深度信息更新至容积模型,追踪的速率高达30FPS。
本文所有设计的核心考虑都是希望使用GPU进行并行化计算,使得相机跟踪和建图都能实时进行。
以下是一些具体方面的背景情况:
·Kinect Sensor: 640*480分辨率11位深度图,采集频率30Hz。这个设备本身会给重建任务带来一些挑战,比如深度图会含有孔洞,这可能是由于场景中某些材料不反射它发出的光,或者一些非常薄的结构使得光线切线入射,该设备也存在运动模糊问题。本文对含有噪声的深度图进行了考虑。
·无漂移的SLAM:早期的SFM算法能够处理大量图像,但是难免会有相机跟踪累计误差导致的漂移问题,或者就需要额外的离线优化过程。PTAM系统放弃了完整概率状态传播的方法,提出将跟踪和建图过程交替或并行运行,其中跟踪是假设当前场景模型完全正确的情况下进行传感器姿态估计,然后建图是指通过全局优化的方式进行地图的扩展和改善。
·基于深度相机的稠密跟踪建图:ICP可用于进行点云对齐,将数据对齐视为非线性优化问题,使用前一次迭代在两组点间找到最接近的点来近似两组点的对应关系,距离的度量有常见的point-to-plane。ICP用于估计机器人移动的连续位姿,加上回环检测和校正可以生成大规模度量一致性地图。
·稠密场景表示:SDF(Signed Distance Function)符号距离函数用于深度图的融合,它用0表示表面,正值表示模型外部点,负值表示模型内部点,数值正比于点到最近表面的距离。表面容易提取为函数的零交叉点。给定一个SDF函数,有两种方法用于渲染出表面:
·marching cubes算法提取联结表面
·表面直接进行射线投射(raycast)方法,避免访问所需视锥范围之外的区域,复杂度与场景无关(本文采取的是这个方法)
·基于深度相机的稠密SLAM:现有对小物体进行高质量扫描的重建方法,但是本文是针对更高速移动相机重建较大规模场景。
重建方法
说到具体的重建流程,就一定要放上这张图:
按照图中的顺序:
1. Measurement: 预处理阶段,将采集到的深度图转化为稠密顶点图和法向量图
- ·双边滤波:对采集的深度图进行去噪
- ·深度图中的像素坐标,通过相机内参和深度值,可以对应到相机坐标系下的三维点,再通过后续估计的相机位姿,即可对应到模型中的三维点坐标
- ·相邻像素在相机系下的三维点坐标经过相减、叉乘即可计算出当前帧的法向量图
- ·对双边滤波的结果进行两次下采样再计算顶点图和法向量图,最后共有三种尺度的结果以供后续位姿估计
2. Pose Estimation: 使用多尺度ICP对齐当前帧和已重建的模型,估计当前帧的位姿,本文基于GPU的实现考虑了所有历史信息
- ·使用所有的历史信息进行稠密的迭代最近点位姿估计是基于两个考虑:
- ·通过保持高帧率的跟踪,可以假设相邻帧的移动是很微小的,因此可以使用快速投影关联法获得点对之间的关系
- ·GPU支持并行处理,因此点对关联和平面优化可以使用所有历史信息,猜测大致意思是所有历史信息重建的结果会被存储下来
- ·相比于以往的方法都是使用ICP估计当前帧和上一帧的位姿,本文估计当前帧和历史信息重建出的模型的位姿
- ·优化目标是当前帧和模型匹配点对在模型点的法向量方向上的投影距离尽可能小(ICP目标)
- ·使用了相邻帧移动很小的假设,建立增量变换模型,采用迭代优化的方法进行最小化目标函数
3. Update Reconstruction: 全局场景融合,给定当前帧的位姿,将当前帧的表面信息融合进重建的模型,模型表示为TSDF(Truncated Signed Distance Function),截断符号距离函数
- ·有了当前深度帧,以及当前帧的位姿,可以将当前深度信息融合进当前重建的TSDF模型
- ·TSDF模型每个体素点存储了两个值,一个表示到最近的表面的截断距离,另一个表示该点的权重,截断距离的意思是:
·对于距离最近表面的距离大于μ,且靠近相机一侧的体素点,TSDF截断距离值记为μ
·对于距离最近表面的距离大于μ,且远离相机一侧的体素点,不记录截断距离值,认为其为不可见区域
·TSDF更新的思路:
- ·对于每一个体素点,根据当前帧的位姿以及相机内参,计算其在图像上对应的像素坐标
- ·根据像素坐标对应到深度图中,得到的是该体素点和相机光心连线上经过的表面的深度
- ·计算体素点到相机的距离深度,和上一步得到的表面深度,二者之差,化为截断距离,即得到了当前体素点的截断距离值
- ·当前体素点的权重,与像素射线方向和表面的夹角有关,夹角越小,说明这个平面越垂直,权重越大;权重和深度有关,深度越小,说明离得越近,权重越大
- ·上述更新思路仅考虑当前帧信息,实际上还需要和上一帧的结果进行融合,融合方式是和上一帧进行加权平均,权重就是每一帧计算出的体素权重;权重的融合方式就是相加
- ·这种更新方式虽然访问了大量无需访问的体素,但是简单并且可并行,因此总时间是较短的
4. Surface Prediction: 对TSDF模型进行射线投射,估计出当前模型的稠密表面表示以供展示
- ·这一步骤的目的是计算出当前重建的TSDF模型对应的表面顶点以及法向量
- ·每个像素点根据外参内参计算出射线方向,从最小深度开始遍历,直到经过0点,或者从负值变为正值,将该点记为表面的顶点
- ·对于非常接近表面的点,假设这一处的TSDF梯度是和表面正交的,因此表面法向量可以通过对TSDF求梯度获得
实验效果
实验设置:为了控制每次实验条件一致,将Kinect放置在固定位置,观察安装在转盘上的桌面物体,采集了560帧图像,约19秒,TSDF体素分辨率是256^3。
五种对比实验设置:
- ·帧数为N,估计位姿时仅使用当前帧和上一帧的信息进行估计
- ·帧数小于N,估计位姿时使用当前帧和整个模型的信息进行估计
- ·帧数为N,估计位姿时使用当前帧和整个模型的信息进行估计(本文方法)
- ·N帧数据重复用了四遍,由于第一帧和第N帧几乎相同,所以假装为转盘多转了几圈,其余设置与3相同
- ·用户手持Kinect对桌面场景进行扫描,没有明显的运动规律,其余设置与3相同
以下是1-4的实验效果:
(a)可以看到仅使用相邻帧的信息进行位姿估计,由于累计误差很容易跟丢
(b)只使用部分帧重建,有些角度没有被覆盖
(c)重建较为完整,位姿图也几乎形成闭环
(d)效果比(c)更好,具体体现在书本的底部侧面以及位姿图的对齐情况
手持的重建效果如下:论文中说效果更好,因为提供了更广阔的视角
耗时情况:耗时主要受体素分辨率影响:
失败案例:主要的失败情况是面对一个很大的平面,因为当拍摄到的是平面时,无法准确估计位姿信息,这也是依赖于深度的一个弊端吧,如果结合色彩信息可能就可以进行比较准确的对齐
限制以及改进方向:
- 目前系统只在体积小于7平方米的容积内重建效果较好,这种稠密的容积表达方式需要太多内存,八叉树可能是一种解决方案
- 如果很大的扫描序列将会导致偏移,需要有效地引入自动重定位技术
- 对于这种容积表达方式怎么进行自动化的语义分割
写在最后
陆陆续续也没想到写了这么长,感觉有点啰嗦之余,只能说大致概括了论文内容,个人感觉这个算法的伟大之处在于能够高度并行化的计算,这一点仅看论文可能是无法真正理解的,得结合源码进行赏析才可能真的掌握吧
源码:https://github.com/chrdiller/KinectFusionLib
无奈这个仓库依赖于CUDA版本的OpenCV,之前尝试手动编译过没成功,之后有机会再来一波尝试,成功了就再来记录一下配环境血泪史......