(八)ORBSLAM回环检测之位置识别



ORBSLAM2回环检测简介

  由于回环检测模块包含两个部分的内容:其一是位置识别,即外观验证,通过图像间的相似度信息进行判断;其二是几何验证,通过回环候选帧与当前关键帧的几何关系来做进一步验证。

  由于两部分内容都较为繁琐,因此笔者将回环检测模块拆分成两讲,今天这一讲主要介绍外观验证,下一讲则继续几何验证。

  外观验证,或者叫位置识别,实际上是一个图像检索的问题,即输入图像与地图存储的所有关键帧进行相似度比较,找出相似度分数最高的即是最优匹配。由于还有几何验证,因此在外观验证阶段,通常会留下几个相似度分数比较高的回环候选帧,以便几何验证选择最合适的回环帧。

  这一讲,我们主要分下面几个部分来介绍外观验证:

  1. 词袋模型;

  2. 图像检索;



 词袋模型

  在讲图像匹配的时候,我们曾提及词袋模型,因为ORBSLAM2中的图像匹配用到的词袋模型,如果不稍微介绍一下,担心大家不太理解它们是怎么匹配的。值得注意的是,如何能保证高效且准确地找到正确匹配是一个检索问题的主要难题,而词袋模型基本上能满足这个要求。因此,本节将主要讲讲词袋模型,之后再利用词袋模型来介绍图像检索。

  词袋的目的是用图像的某些特征来描述一幅图像。从我们人的直观感觉来看图像,我们会说这张照片里有一个人,一张桌子这些特征;而另一张照片里有一只狗,一张凳子和一张桌子等特征来描述。根据这些特征描述,我们就可以判断这两张图像的相似性了。如果我们将上述这些描述内容整合成字典,让他们形成一一映射的关系,比如:

  $v_{1}$ 表示人,$v_{2}$ 表示桌子,$v_{3}$ 表示凳子,$v_{4}$ 表示狗。那么这字典的形式可以表示成 $D = [ v_{1}, v_{2}, v_{3}, v_{4} ]$。

  而对于第一张照片,我们会表示成 $I_{1} = 1\cdot v_{1} + 1\cdot v_{2} + 0\cdot v_{3} + 0\cdot v_{4}$,于是我们就可以用一个向量来描述这个照片 $I_{1} = [ 1, 1, 0, 0 ]^{T}$;

  同理,第二张照片表示成 $I_{2} = 0\cdot v_{1} + 1\cdot v_{2} + 1\cdot v_{3} + 1\cdot v_{4}$,描述成向量形式 $I_{2} = [ 0, 1, 1, 1 ]^{T}$。

  对待这两个向量,我们可以设定度量方式,就能得到两张照片的相似度了。

  在这里,我们提到了字典的概念,也用到了字典的方法,但是它是怎么定义的,怎么生成的?我们需要再稍微介绍一下。

  ----------字典------------

  按照前面的介绍,字典是由很多单词组成,每一个单词代表一个概念。一个单词代表的不单单是一个特征点,他是一类具有相似性的特征的组合,或者更明确的说是它们的聚类中心。因此,字典的生成问题就类似于一个聚类问题。

  聚类问题在无监督机器学习中非常常见,词袋模型主要使用经典的K-means算法来进行特征的聚类,假设有 $N$ 个特征点,我们需要将他分成 $k$ 类,下面的样本就表示特征点,具体流程如下:

  1. 随机选取 $k$ 个中心点:$c_{1}, \cdots, c_{k}$;

  2. 对每个样本,计算它和每个中心点之间的距离,取最小的作为它的归类;

  3. 重新计算每个类的中心点;

  4. 如果每个中心点都变化很小,则算法收敛,退出;否则返回第2步。

  但是在SLAM问题中,需要面对的场景非常多,特征的种类也非常多,如果只是非常笼统地将其分成几大类,这种做法显然是不够准确地。因此有学者提出了 $k$ 叉树的概念,类似于层次聚类,是K-means的直接拓展。同样,假设我们有 $N$ 个特征点,希望构建一个深度为 $d$,每次分叉为 $k$ 的树,那么做法如下:

  1. 在根节点,即 $N$ 个特征点的集合,用K-means把所有样本聚成 $k$ 类,这样就得到了第一层;

  2. 对第一层的每个节点,把属于把节点的样本再聚成 $k$ 类,得到下一层;

  3. 以此类推,最后得到叶子层,叶子层即为所谓的词汇。

  这些词汇就跟我们前面所讲的那个例子差不多,比如桌子只是其中一个词汇。当然,这里只是举例说明而已,这里的每一个词汇都是多个相似特征聚类而成的聚类中心,直接表征多个相似特征。更直观一些可以看下面这个图,尽管我们在图像匹配的时候看过,但是加上这里的描述,相信你可以更好地理解 $k$ 叉树是个什么东西。

  

   我们在叶子层构建了单词,树结构中的中间节点仅供快速查找时使用。实际上,我们构造了一个深度为2,3个分支的树,可以容纳 $3^{2}$ 个单词。我们可以通过增加树的深度和分支来增加字典的规模,达到更好的分类效果,这可以达到我们需要的准确率。此外,在检索时,一个特征会与逐层的中间节点的聚类中心比较,最终找到最优的匹配词汇,这个检索过程能达到对数级别的查找效率。



图像检索

  在介绍了词袋模型这个工具以后,我们的图像检索问题就简单很多了。

  检索问题的描述其实很简单:

  输入一帧图像,和已有的数据库图像逐一对比,找到一个最合适的或者说匹配分数最高的图像。

  笔者这里直接介绍ORBSLAM2的外观识别流程,因为它的意义是如此直观,只是在实现的时候加了一些小技巧,笔者将其罗列出来,以便大家参考:

  1. 利用一范数来度量当前帧与共视图关键帧之间的相似度分数,假设共视图中一个关键帧的BOW向量为 $w$,当前帧的BOW向量为 $v$,则相似度分数的度量方式为:

    $s(w-v) = 2\sum\limits_{i=1}^{N}\left|w_{i}\right| + \left|v_{i}\right| - \left|w_{i}-v_{i}\right|$

  将所有相似分数进行排序,取最小的匹配分数 $S_{min}$ 作为参考值,用于查找回环候选帧。

  2. 确定最小匹配分数后,排除当前帧共视图的所有关键帧,我们回环的意义是确定当前相机看到的场景,在很久之前是不是见过。而近期看到的,比如当前帧的共视图关键帧,我们通常是不考虑的,因为这对校正整个场景的误差,实际上作用不大。

  3. 对当前帧的BOW向量中的词汇逐个逆向索引在地图中找到相关联的关键帧,参考下图。并统计各个关键帧中与当前帧相似的词汇数量。排序确定最大的相似词汇数量 $M$,并筛选相似词汇数量大于$0.8\times M$的关键帧作为候选帧 $KF_{can}^{1}$;

  

  4. 将当前帧与步骤3的候选帧进行BOW向量计算匹配分数,取匹配分数高于步骤1计算的最小匹配分数 $S_{min}$的候选帧作为新的候选帧 $KF_{can}^{2}$;

  5. 统计候选帧集中 $KF_{can}^{2}$ 每个候选帧的共视图关键帧与当前帧的BOW匹配分数总和 $S_{total}$,并取分数总和大于 $0.75\times S_{total}$的候选帧组成新的候选帧 $KF_{can}^{3}$。笔者理解这也是为了确保在一个范围里都能检测到回环,增强回环的可靠性。

  6. 在上述候选帧 $KF_{can}^{3}$ 的基础上,我们检测连续三帧都识别到同一个回环,那么就可以进一步缩小候选帧集,形成最终的候选帧集 $KF_{can}^{final}$ ,这在ORBSLAM2中叫一致性验证。

  至此,我们的外观验证已经完成了。从步骤1开始到步骤6,ORBSLAM2都是在不断提高筛选条件进而缩小候选帧集。可以想见,这是在利用词袋模型检索和匹配效率极高的优势,快速完成粗检索,精细化的部分再交由几何验证去进一步确定最终的候选帧。



总结:

  在这一讲中,我们概述了ORBSLAM2中采用的回环检测方法,并着重讲解了其中的外观验证方法,包括:

  详细介绍了词袋模型的结构,以及生成方法;

  详细罗列了ORBSLAM2中的视觉验证中所采用的检索方法;

  下一讲,我们将继续回环检测方法中的另一部分——几何验证。

碎碎念:  

  笔者这种记录纲领的方法,在很多读者看来可能是一个记流水账的过程,十分枯燥。但是笔者还是同其他博主一样,优先写出对应模块的关键技术,再进一步分析ORBSLAM2中用这种关键技术,怎么样做优化,怎么样完成它想要完成的功能。

  笔者认为这种列提纲的方式,可以帮助大家对这些细小的方法有一个清晰的认识。笔者之前就困惑于如何提高位置识别的准确性,而ORBSLAM2中这多种筛选方法可以给笔者提供多种参考方案。因此,笔者想传递给大家的也是这样一个信息,罗列提纲的方式可以为大家提供的是ORBSLAM2中某个模块采用的各种方法,读者可以根据实际需要选择提纲中的任意一个或多个组合的方法完成自己想要的功能。若是本文能对读者产生一两点帮助,那笔者将是十分欣慰的。

PS:

  如果您觉得我的博客对您有所帮助,欢迎关注我的博客。此外,欢迎转载我的文章,但请注明出处链接。

  对本文有任何问题可以在留言区进行评论,也可以在泡泡机器人论坛:http://paopaorobot.org/bbs/index.php?c=cate&fid=1中的SLAM技术交流模块发帖提问。

  我的github链接是:https://github.com/yepeichu123/orbslam2_learn

  

    

原文地址:https://www.cnblogs.com/yepeichu/p/10793013.html

时间: 2024-07-31 20:37:36

(八)ORBSLAM回环检测之位置识别的相关文章

(九)ORBSLAM回环检测之几何验证

ORBSLAM2回环检测之几何验证简介 回环检测的目的是找到当前场景在历史中是否出现过,如果出现过,那会给我们提供一个非常强的约束条件,把我们偏离很多的轨迹一下子修正到正确的位置上.当然,这么好的东西,有利自然就有弊.万一我们检测出来的回环不是真正的回环,也就是说我们认错了地方,这种时候提供的回环约束会导致轨迹被错误地“修正”了,结果就是估计的轨迹跟真实的轨迹相差十万八千里,这显然是不可接受的. 因此,回环检测的正确性就显得非常重要.我们会宁愿不要回环约束,也不要一个错误的回环约束.所以ORBS

ORB-SLAM(六)回环检测

上一篇提到,无论在单目.双目还是RGBD中,追踪得到的位姿都是有误差的.随着路径的不断延伸,前面帧的误差会一直传递到后面去,导致最后一帧的位姿在世界坐标系里的误差有可能非常大.除了利用优化方法在局部和全局调整位姿,也可以利用回环检测(loop closure)来优化位姿. 这件事情就好比一个人走在陌生的城市里,一开始还能分清东南西北,但随着在小街小巷转来转去,已经不知道自己在什么地方了.通过认真辨识周边环境,他可以建立起局部的地图信息(局部优化).再回忆以前走过的路径,他可以纠正一些以前的地图信

ATS回环检测

ATS的回环检测是通过判断本机ip是否出现在请求头中的Via头来实现. Machine::Machine(char const* the_hostname, sockaddr const* addr):函数初始化了本机的入口ip. 如果没有配置proxy.local.incoming_ip_to_bind,这个函数第二个参数是地址存的值是一个空的sockaddr结构体.函数调用了getifaddrs,这个api可以获取系统所有的网络接口信息,存到一个ifaddrs结构体中,这个机构体是一个链表结

加速度传感器的原理和应用-手机翻转、失重检测、运动检测、位置识别

本文介绍可穿戴设备加速度传感器-Lis3dh的特性原理和应用场景.意法半导体研发的Lis3dh广泛应用在智能手环.智能计步鞋等智能穿戴产品中. Lis3dh有两种工作方式,一种是其内置了多种算法来处理常见的应用场景(如静止检测.运动检测.屏幕翻转.失重.位置识别.单击和双击等等),用户只需简单配置算法对应的寄存器即可开始检测,一旦检测到目标事件,Lis3dh的外围引脚INT1会产生中断.另一种是支持用户通过SPI/I2C来读取底层加速度数据,并自行通过软件算法来做进一步复杂的处理,如计步等等.

基于OpenCV读取摄像头进行人脸检测和人脸识别

前段时间使用OpenCV的库函数实现了人脸检测和人脸识别,笔者的实验环境为VS2010+OpenCV2.4.4,opencv的环境配置网上有很多,不再赘述.检测的代码网上很多,记不清楚从哪儿copy的了,识别的代码是从OpenCV官网上找到的:http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_api.html 需要注意的是,opencv的FaceRecogizer目前有三个类实现了它,特征脸和fisherface方法

一维回环数组求解最大子数组问题

一.题目与要求 题目:返回一个整数数组中最大子数组的和. 要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值.要求时间复杂度为O(n) 二.设计思想 通过上次求解简单一维数组的最大子数组问题的解决,我们找到了一种实现时间复杂为O(n)的方法,采用的是二分法和递归

linux命令练习:mount fdisk swap dd创建本地回环设备

练习一   1.创建一个1G的分区,文件系统为ext4,卷标为MYDATA,块大小为1024,预留管理空间为磁盘 分区的3%,要求开机后制动挂载至/data目录,并且自动挂载的设备要使用卷标进行引用.   fdisk /dev/sda  [[email protected] ~]# fdisk /dev/sda WARNING: DOS-compatible mode is deprecated. It's strongly recommended to switch off the mode

打印数字回环

题目要求: Input a value n, then print out a n×n matrix. Example 1: Input 2, output 1 2 4 3 Example2: Input 5, output 1    2    3    4    5 16   17   18   19    6 15   24   25   20    7 14   23   22   21    8 13   12   11   10    9 思路: 把该输出划分为多个环,每个环上有4根线

[算法]回文检测

链表的回文检测 有关链表的回文检测,用到的就是链表操作中常常用到的双指针的方法,找到链表的中点位置,然后依次对比两边的结点.但是在找链表的中点的时候要注意链表的总个数是偶数或者奇数的两种情况. 1.找链表的中点位置,并把中点以前的各个结点的值存入到栈中. 2.针对偶数或者奇数个链表结点,对中点结点做一个小的调整. 3.依次对比栈中结点的值后链表后半部分结点的值是否相等,决定是否是回文结构. 代码实现: bool isPalindrome(ListNode* head) { bool isPali