什么是回环检测?
在讲解回环检测前,我们先来了解下回环的概念。在视觉 SLAM 问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿解算当前帧位姿,因此其中的误差便这样一帧一帧的传递下去,也就是我们所说的累计误差。
我们的位姿约束都是与上一帧建立的,第五帧的位姿误差中便已经积累了前面四个约束中的误差。但如果我们发现第五帧位姿不一定要由第四帧推出来,还可以由第二帧推算出来,显然这样计算误差会小很多,因为只存在两个约束的误差了。像这样与之前的某一帧建立位姿约束关系就叫做回环。回环通过减少约束数,起到了减小累计误差的作用。
那么我们怎么知道可以由第二帧推算第五帧位姿呢?也许第一帧、第三帧也可以呢。确实,我们之所以用前一帧递推下一帧位姿,因为这两帧足够近,肯定可以建立两帧的约束,但是距离较远的两帧就不一定可以建立这样的约束关系了。找出可以建立这种位姿约束的历史帧,就是回环检测。
回环检测的意义
有了前端的视觉里程计及后端优化的 SLAM 系统,似乎已经比较好用了。但其在提高实时性的同时精度却降低了,一旦精度降低,又会面临长时间累计误差的问题,特别是像 ORB-SLAM 那样只做局部地图优化的方案。我们该如何平衡这个矛盾呢?
我们不妨先思考下,在一个陌生的环境中,我们人类是如何进行环境地图的建立?在局部区域,人不断的移动从而在脑海中建造增量式地图,时间长了大部分人也分不清东南西北了,与起始点的关系又如何。假如人正巧回到了之前路过的位置,在对环境足够敏感的情况下,他就能发现这个事实,从而修正自己之前对方位的判断。我们说,此时检测到了一个回环,显然,人可以通过面前看到的景象与脑海中残缺的印象来对比从而检测到回环的,对于 SLAM 来说也可以通过对比当前帧与过去关键帧的相似度,如相似度超过某一阀值时就可以被认为是检测到回环。
现在,问题的关键就在于如何判断两帧图片的相似度。最直观的做法是特征匹配,比较匹配的数量是否足够多。但由于特征匹配非常耗时,回环检测需要与过去所有关键帧匹配,这个运算量是绝对无法承受的。因此,有人提出了词袋模型,用来加速特征匹配。
什么是词袋模型?词袋模型就是把特征看成是一个个单词,通过比较两张图片中单词的一致性,来判断两张图片是否属于同一场景。为了能够把特征归类为单词,我们需要训练一个字典。所谓的字典就是包含了所有可能的单词的集合,为了提高通用性,需要使用海量的数据训练。字典的训练其实是一个聚类的过程。假设所有图片中共提取了 10,000,000 个特征,可以使用 K -means 方法把它们聚成 100,000 个单词。但是,如果只是用这 100,000 个单词来匹配的话效率还是太低,因为每个特征需要比较 100,000 次才能找到自己对应的单词。为了提高效率,字典在训练的过程中构建了一个 k 个分支,深度为 d 的树,如下图所示。直观上看,上层结点提供了粗分类,下层结点提供了细分类,直到叶子结点。利用这个树,就可以将时间复杂度降低到对数级别,大大加速了特征匹配。
使用 DBoW3 库训练及使用词典
DBoW3 库为我们提供了非常方便的训练词典和使用词典的方法。
训练词典时,只需要把所有训练用的图片的描述符传给 DBoW3::Vocabulary 的 create 方法就可以了。训练好的词袋模型保存在 vocabulary.yml.gz 文件中。接下来,使用训练好的词袋模型对图片计算相似性评分。DBoW3 为我们提供了两种计算相似性的方式,第一种是直接对两张图片比较;第二种是把图片集构造成一个数据库,再与另一张图片比较。005QQQghzy7oCR8cSOZ31&690 可以看出,图片越相似,评分越接近 1。我们可以根据这个评分来判断两张图片是否是同一场景。但是直接给定一个绝对的阈值并不合适。通常,如果当前帧与之前某帧的相似度超过当前帧与上一个关键帧相似度的 3 倍,就认为可能存在回环。不过,这种做法要求关键帧之间的相似性不能太高,否则无法检测出回环。