Tuesday 15 December 2015

SVO论文笔记

SVO提出了一种基于向下看的相机和IMU的定位算法。论文开始先总结了运动估计的方法,主要有两种。

第一种是基于特征点,现在图像中选取角点等特征,然后在相邻图像中匹配,用epipolar集合来回复相机运动和场景。最后最小化反投影残差来优化相机姿态和场景。这种方法的成功在于有很多特征点检测和匹配的算法,甚至可以用在两个图像之间运动很大的情况。缺点是需要设定检测和匹配的阈值来剔除错误的匹配,而且很多检测方法往往不精确,导致运动的漂移需要平均很多特征点才能减小。

第二种是直接的方法,基于图像中的像素值。这里使用局部的梯度,包括大小和方向。当图像中特征点很少的时候,或者图像有模糊的时候,这种方法都好于特征点法。计算photometric error需要比反投影残差更多的计算量,不过不需要特征点的检测和匹配。

之前多数单目视觉里程计都是基于PTAM的,它是基于特征点检测的SLAM算法,通过跟踪和匹配上百个特征点实现。它通过并行计算运动估计和建图,使用高效的关键帧的BA,来实现实时性能。不过PTAM主要用在室内桌面的AR,如果在室外使用需要限制关键帧的个数。

直接的方法有DTAM,用最小化一个能量方程来计算每个关键帧里面的深度值。相机的姿态通过匹配整个深度图来计算。这种方法需要很大计算量,所以只能用GPU。

对比之前的方法,SVO主要的贡献在
1. semi-direct方法,比之前的方法更准确,快速。
2. 基于概率的构图方法,可以处理outlier。

SVO使用了两个并行的thread,一个用来估计相机姿态,另一个构建地图。

估计相机姿态时,第一步是最小化相邻两个图像中相同3D点投影的photometric error。反投影的点对应的2D点通过匹配图像块进行优化。最后同时优化姿态和反投影残差。

在论文的motion estimation部分,作者假设像素的残差成正态分布,variance是1.与之前方法不同,并不是很多的点都有深度,而是只有稀疏的特征点有深度。在每个特征点周围选取4x4的图像块,我们要找到能使得这些图像块残差最小的相机姿态。

为了减小漂移,相机的姿态应该和地图对应,而不是前一帧。所有能在当前相机中看到的已知3D点会被反投影到图像中,对每个反投影点,都找到它在关键帧中对应的图像块,然后在跟当前图像中的图像块对比。

在姿态和结构优化部分,作者对运动和3D点分别使用BA来优化,然后在将两者放在一起优化。跟只是两帧之间对比的sparse image alignment比较,加入当前图像和关键帧以及地图的对比能得到更准确的结果。

在地图构建中,我们根据当前图像和相机的姿态来估计每个特征点的深度。构建地图的时候,一个基于概率的深度滤波器会对每个2D特征点初始化,来寻找对应3D点。开始的时候每个深度的不确定性都非常大,之后每个图像中都根据贝叶斯定理优化深度。当一个深度的不确定性足够小的时候,一个新的3D点就被加入地图,用来做运动估计。

这部分可以参考这篇论文,大概是讲如何从多个图像中估计深度。在图像I中,在光轴上一点x(Z),距离相机深度为Z,它在I中的图像块w对应另外一个图像I'中的图像块w',可以用NCC来计算w和w'的相似度。通过观察作者发现用寻找NCC最大值的方法计算Z,要么得到的深度很准,要么就随机分布在Zmin和Zmax的区间内,也就是可以用一个gaussian+uniform的概率分布来描述。给定一个初始的先验概率,接下来就可以用bayesian inference来计算最大化后验概率的深度。

在SVO的论文里,depth filter的大意貌似是这样的。计算了某个点u在图像Ir的深度rP之后,在图像Ik中可以找到u的对应点u',如果把u'移动一个像素,就能得到一个新的u对应的3D点rP+,对深度估计的误差就是rP和rP+之间的距离。为什么rP的variance是把u'移动一个像素之后得到的呢?具体要参考这里。更多关于为何使用depth filter参考这里

仔细看mapping部分,每个depth filter都对应一个关键帧。初始化的时候每个点的不确定性很大,初始值就是关键帧中深度的平均值。接下来的每个图像中,我们在epipolar line上面寻找对应的图像块,然后通过三角定位计算深度。跟这篇论文中不同的是,为了应对很大的深度变化,SVO使用了inverse depth。

算法实现
在最开始的两帧,SVO使用了平面假设来估计一个homography,然后用三角定位初始化两帧里面点的深度,这个过程和PTAM相似。为了应对大幅度的运动,在sparse image alignment用了coarse to fine方法。

如果当前帧距离所有关键帧的距离超过场景平均深度的12%,那么当前帧就被选为关键帧。为了加快效率,SVO中的关键帧数目是一定的,所以每加入一个关键帧,都会把最老的一个关键帧去掉。

在mapping thread中,图像被分成了30x30的小格子。每个Shi-Tomasi score最高的FAST角点会被加入depth filter,除非那个格子里面已经有了2D和3D对应的特征点存在。这样就可以得到平均分布的特征点。

推荐另外一篇非常好的SVO论文博客

运行SVO
从github上面下载并安装好svo之后,可以运行test pipeline来看结果。在catkin_ws里面catkin_make, 生成的.exe文件在catkin_ws/devel/lib/svo里面。作者给的airground dataset的pose可以用这里提到的方法存在txt文件里面。








No comments:

Post a Comment