上一篇提到,无论在单目、双目还是RGBD中,追踪得到的位姿都是有误差的。随着路径的不断延伸,前面帧的误差会一直传递到后面去,导致最后一帧的位姿在世界坐标系里的误差有可能非常大。除了利用优化方法在局部和全局调整位姿,也可以利用回环检测(loop closure)来优化位姿。

这件事情就好比一个人走在陌生的城市里,一开始还能分清东南西北,但随着在小街小巷转来转去,已经不知道自己在什么地方了。通过认真辨识周边环境,他可以建立起局部的地图信息(局部优化)。再回忆以前走过的路径,他可以纠正一些以前的地图信息(全局优化)。然而他还是不敢确定自己在城市的精确方位。直到他看到了一个之前路过的地方,就会恍然大悟,“噢!原来我回到了这个地方。”此时,将这个信息传递回整个地图,就可以得到相当准确的地图信息。这就是回环检测。

因此,回环检测在大尺度地图构建上是一个非常有用的方法。回环检测可以从二维图像出发,也可以从三维点云出发。目前大家更推荐基于二维图像的方法。

DBoW2

基于二维图像的方法本质上是一个场景识别的问题。我没有深入研究过,因此直接介绍一下ORB-SLAM中用到的DBoW2的方法。

BoW(bag of words,词袋模型),可以理解为一个以特征描述作为元素的词典。如果是ORB特征,那就是ORB词典;如果是SIFT特征,那就是SIFT词典。词典可以从图像数据集中训练出来。下面举一个简单的例子。假如我们有一个一万幅图像的数据集,并认为它基本上涵盖了我们所面临的场景。

  1. 从每幅图像中提取特征点和特征描述;特征描述一般是一个多维向量,因此可以计算两个特征描述之间的距离;

  2. 将这些特征描述进行聚类(比如k-means),类别的个数就是词典的单词数,比如1000;也可以用Beyes、SVM等;

  3. DBoW2将这个词典组织成树的形式,方便搜索。

在实际应用中,每一幅图像都在词典中搜索其最近邻的单词,并在该单词下留下标记。如果A、B两幅图像定位到同一个单词时,说明这两幅图像有可能有相似的特征点。当A、B有一定量的相似点时,可以认为这两幅图像之间存在着一定的相似性。

ORB-SLAM的作者修改了DBoW2,输出一系列候选图像(candidate)而不是一幅最相似的图像。

基于BoW的方法有一些非常好的优势:

  1. 词典可以离线训练。在实时应用中能离线的东西越多越好。作者提供了通过大量数据训练出来的BRIEF和SIFT的词典。

  2. 搜索速度飞快。小尺寸的图像可以在毫秒级别完成。作者提供了正向(direct index)和反向(inverse index)两种辅助指标。反向指标在节点(单词)上储存到达这个节点的图像特征的权重信息和图像编号,因此可用于快速寻找相似图像。正向指标则储存每幅图像上的特征以及其对应的节点在词典树上的某一层父节点的位置,因此可用于快速特征点匹配(只需要匹配该父节点下面的单词)。

  3. 很多slam应用本身就需要计算特征点和描述,因此可以用特征来搜索。

  4. ORB-SLAM的作者还用词典的特性做快速的特征筛选,减少特征匹配需要的时间(特别是在大尺度上搜索特征时)。​

当然它也有自己的劣势:

  1. 如果应用的场景比较特殊,请训练自己的词典。一般的词典会不太好用。

  2. BoW一般不太考虑特征之间的几何关系(有人在做,但不清楚效果和计算量如何)

还有几个comments:

  1. 如果应用本身不需要计算特征,那要考虑额外的计算时间。

  2. 推荐像ORB-SLAM一样,BoW只用来快速筛选图像,后续需要通过其它方法一一验证、严格验证。如果回环选错了,那,就跪了。

  3. 如果场景特征很少,或者重复的特征太多,比较难办。

  4. 在稠密点云重建中,如果场景本身有丰富的几何纹理,那么可以利用两帧之间(包括相邻位置)的三维点云匹配去验证回环。如果匹配的误差足够小,那么回环是比较准确的。

回环验证和Sim3优化

对每个候选的回环帧,作者先匹配其和当前帧上的特征点,然后用特征点对应的三维点去求解一个相似变换矩阵(RANSAC框架下)。如果某个回环帧对应的矩阵有足够多的内点,那去做Sim3优化。利用优化结果再去寻找更多的特征匹配,再做一遍优化。如果内点足够多,那么接受这个回环。

Sim3优化详见上一篇。

回环融合(fusion)

这里有一个隐含假设,即误差随着时间不断累积,相对而言,我们更信任之前的信息而不是当前的信息。这部分主要是把回环帧的信息融合到当前帧里面,包括匹配的特征点对应的三维信息(深度、尺度等),世界坐标系下的位姿(通过Sim3的结果转化过去)等等。融合也包括回环帧的邻域和当前帧的邻域。

全局优化

全局优化时,固定回环帧及其邻域,当前帧及其邻域,优化剩余帧在世界坐标系的位姿。详见上一篇。

预告

这个系列写到这里就暂时告一段落啦。回头来看,前面几篇写的并不满意,尤其追踪那部分,将来争取重写一下。

接下来,本来想写关于LSD的文章,估计会暂缓一下,先写一两篇关于网格生成的文章。

该系列的其它文章:

ORB-SLAM(一)简介

ORB-SLAM(二)性能

ORB-SLAM(三)初始化

ORB-SLAM(四)追踪

ORB-SLAM(五)优化

05-01 00:54