1.前言
现在,我们已经知道了SLAM中在前端进行姿态估计,在前端估计中,相邻的时间中,位姿的估计可以使用前端估计解决;在较长的时间中,位姿估计可以使用图优化解决;那么,对于更长的时间呢,如果依然使用图优化会导致漂移的持续累计,这时候,要怎么解决来遏制这种长时间导致的漂移呢?
这就要用到回环检测了。
> 回环检测,又称闭环检测,是指机器人识别曾到达某场景,使得地图闭环的能力。说的简单点,就是机器人在左转一下,右转一下建图的时候能意识到某个地方是“我”曾经来过的,然后把此刻生成的地图与刚刚生成的地图做匹配。
2.回环检测的方法
回环检测有2的重要的目的:
- 长时间的漂移校正;
- 地图重定位。
那么,如何判断是否出现回环检测呢?
从最简单的方法来看,就是比较2个图像的相似度,完全相似或者高度相似就是出现了回环。
这可以通过特征匹配来计算2个图像的相似度,但是这样做,一副要和产生的所有图像比较特征是否一致,这个计算量实在是太大了,那么有没有更好的办法呢?
可以通过基于外观匹配的方式计算,也就是说,当机器人运动过程中估计图像的相似度来比较是否存在回环。这就诞生了SLAM中前端、后端、回环检测的三大部分。
那么如何评价图像的相似度?
3.准确率和召回率
准确率:
召回率:
4.词袋
从最简单的方法来看,回环检测就是比较2个图像的相似度,比较他们的特征匹配,完全相似或者高度相似就是出现了回环。
但是这种检测匹配的方式计算量太过庞大,如何降低计算量呢?
可以使用词袋模型。
> 词袋模型(英语:Bag-of-words model)是个在自然语言处理和信息检索(IR)下被简化的表达模型。
struct Node
{
//标记如下建立词袋模型
//在所有节点中的标号
NodeId id;
//该节点的权重,该权重为训练的过程中设置的,在得到了树之后,
//将所有的描述子过一遍树,得到每个单词出现的次数,除以总的描述子数目
WordValue weight;
//描述符,为每一类的均值(对于brief描述子,则要对均值进行二值化)
TDescriptor descriptor;
//如果是叶节点,则有词汇的id
WordId word_id;
}
5.字典
对于词袋模型,可以建立较少的单词来表述一个图像,那么,如何使用通用的做法表述一个图像呢?
就可以建立字典模型,顾名思义,字典就是一个有很大量单词的词袋,可以描述更多的图像、更多的内容。
但是,问题接踵而至,如此大规模的字典,如何快速检索呢?
研究者提出了很多很多解决办法,这里我们使用简单的k叉树表述字典。
6.实践
现在,我们来创建一个字典模型:
int main( int argc, char** argv ) {
// read the image
cout<<"reading images... "<<endl; vector<mat=""> images;
for ( int i=0; i<10; i++ )
{
string path = "./data/"+to_string(i+1)+".png";
images.push_back( imread(path) );
}
// detect ORB features
cout<<"detecting ORB features ... "<<endl; ptr<="" feature2d=""> detector = ORB::create();
vector<mat> descriptors;
for ( Mat& image:images )
{
vector<keypoint> keypoints;
Mat descriptor;
detector->detectAndCompute( image, Mat(), keypoints, descriptor );
descriptors.push_back( descriptor );
}
我们了解了词袋、字典、回环检测的基本原理,从为什么到怎么做。回环检测是如今slam中不可缺少的一环,也有很多与深度学习融合的算法,以后我会继续讲解。=""> 参考资料:视觉SLAM十四讲</endl;></keypoint></mat></endl;></endl;>