ORB-SLAM2 --- KeyFrameDatabase::DetectLoopCandidates函数

news2024/11/25 4:21:27

目录

1.函数作用

2.函数流程 

3.函数解析 

3.1 传入参数解析

3.2 找出和当前帧具有公共单词的所有关键帧,不包括与当前帧连接的关键帧 

3.3 统计上述所有闭环候选帧lKFsSharingWords中与当前帧具有共同单词最多的单词数,用来决定相对阈值  

3.4 遍历上述所有闭环候选帧,挑选出共有单词数大于minCommonWords且单词匹配度大于minScore存入lScoreAndMatch 

3.5 单单计算当前帧和某一关键帧的相似性是不够的,这里将与关键帧相连(权值最高,共视程度最高)的前十个关键帧归为一组,计算累计得分 

3.6 只取组得分大于阈值的组,得到组中分数最高的关键帧们作为闭环候选关键帧 


1.函数作用

        在闭环检测中找到与该关键帧可能闭环的关键帧(注意不和当前帧连接)。

2.函数流程 

 * Step 1:找出和当前帧具有公共单词的所有关键帧,不包括与当前帧连接的关键帧。
 * Step 2:只和具有共同单词较多的(最大数目的80%以上)关键帧进行相似度计算 。
 * Step 3:计算上述候选帧对应的共视关键帧组的总得分,只取最高组得分75%以上的组。
 * Step 4:得到上述组中分数最高的关键帧作为闭环候选关键帧。

3.函数解析 

3.1 传入参数解析

        函数的传入参数:

        @pKF : 关键帧pKF,本函数的目的是找到关键帧pKF的闭环候选帧

        @minScore : 帧pKF和其所有共视关键帧的相似度得分的最低值,且得分越低相似度越低,ORB-SLAM2算法认为回环候选帧与帧pKF的相似度得分不得低于这个分数

        函数由LoopClosing::DetectLoop调用,目的是在关键帧数据库mpKeyFrameDB中找到帧pKF的闭环候选关键帧。

        我们首先获取与该关键帧连接(>15个共视地图点)的关键帧(没有排序的)。存储在变量spConnectedKeyFrames中。

// 得到与该关键帧连接(>15个共视地图点)的关键帧(没有排序的)
set<KeyFrame*> KeyFrame::GetConnectedKeyFrames()
{
    unique_lock<mutex> lock(mMutexConnections);

    set<KeyFrame*> s;
    for(map<KeyFrame*,int>::iterator mit=mConnectedKeyFrameWeights.begin();mit!=mConnectedKeyFrameWeights.end();mit++)
        s.insert(mit->first);
    return s;
}

        建立变量lKFsSharingWords保存可能与当前关键帧形成闭环的候选帧。

3.2 找出和当前帧具有公共单词的所有关键帧,不包括与当前帧连接的关键帧 

        先说一个知识点:倒排索引

  // 倒排索引,mvInvertedFile[i]表示包含了第i个word id的所有关键帧
  std::vector<list<KeyFrame*> > mvInvertedFile; 

         我们遍历pKF帧的BowVector向量:

        如果有不了解BoWVec的,推荐看完我的博客之后再继续往下看:

 详解什么是BowVec和FeatVecicon-default.png?t=MBR7https://blog.csdn.net/qq_41694024/article/details/128007040

        通过倒排索引取出所有word的KeyFrame(即所有与pKF帧有相同描述子的帧)存放在变量lKFs中。然后对这些关键帧lKFs展开遍历:

        如果这帧没有标记为当前帧pKF的候选关键帧(即这些帧的mnLoopQuery标记不是pKF的帧ID,这么做的目的是为了防止重复添加),我们将此帧的mnLoopWords置为0,即初始化该帧和pKF的能看见相同地图点的数量为0。

                若该帧和当前关键帧共视的话不作为闭环候选帧,因为闭环候选帧是能和当前帧有相同的观测但不相连

                若该帧和当前关键帧没有共视的话作为闭环候选帧,将该帧的mnLoopQuery标记为pKF的帧ID,并将该帧放入lKFsSharingWords中作为闭环候选关键帧。

        如果这帧标记为当前帧pKF的候选关键帧,则将mnLoopWords++

        完成3.2节这些之后,我们得到了一个闭环候选关键帧的集合lKFsSharingWords,并且这里面的关键帧的mnLoopWords属性记录着该帧和pKF帧的共视程度。

3.3 统计上述所有闭环候选帧lKFsSharingWords中与当前帧具有共同单词最多的单词数,用来决定相对阈值  

        我们遍历lKFsSharingWords中的关键帧,统计上述所有闭环候选帧中与当前帧具有共同单词最多的单词数存放在maxCommonWords变量中,并取maxCommonWords的0.8倍为最小公共单词数用于进一步筛选闭环候选关键帧,存储在minCommonWords中。

3.4 遍历上述所有闭环候选帧,挑选出共有单词数大于minCommonWords且单词匹配度大于minScore存入lScoreAndMatch 

        我们新建变量lScoreAndMatch用于存储这一步从lKFsSharingWords筛选后的关键帧,其定义格式为list<pair<float,KeyFrame*> >。

        遍历每一个在lKFsSharingWords中的关键帧,pKF只和具有共同单词较多(大于minCommonWords)的关键帧进行比较,若公共单词数少则直接淘汰掉该帧。计算此帧和pKF的相似度得分,记录在该帧的mLoopScore中,如果这个score大于我们传入的参数,则将该帧的分数和帧存入lScoreAndMatch变量中等待下一轮的筛选。

3.5 单单计算当前帧和某一关键帧的相似性是不够的,这里将与关键帧相连(权值最高,共视程度最高)的前十个关键帧归为一组,计算累计得分 

                我们遍历lScoreAndMatch中的每一帧,对其中的每一帧,我们建立一个关键帧组,取出和它连接的共视程度最好的十个关键帧。

        即在上图中表现出来即是,lScoreAndMatch是对应的红色的帧,对于每一个红色帧,建立一个关键帧组(对应绿色部分)。

        在每一组中,记录组中的最高得分bestScore、累计得分accScore、该组最高分数对应的关键帧pBestKF

        遍历每一组内的关键帧更新这三个变量,且只有这些帧也在闭环候选帧中,且公共单词数超过最小要求,才能贡献分数。

        并记录所有组中组得分最高的组的得分bestAccScore,用于确定相对阈值。

        走完3.5节后我们完成了如下流程:

        对于每个关键帧组:我们得到了该组内分数最高的关键帧pBestKF以及得分bestScore和该组的累计得分accScore

        对于所有关键帧组:我们得到了所有组中组得分最高的组bestAccScore

        对于整个函数:我们创立list<pair<float,KeyFrame*> >型变量lAccScoreAndMatch,存储闭环候选关键帧和它的组分数。

3.6 只取组得分大于阈值的组,得到组中分数最高的关键帧们作为闭环候选关键帧 

        此步我们进行最终筛选,我们设置筛选阈值minScoreToRetain为所有组中最高得分的0.75倍。

        遍历lAccScoreAndMatch,只取组得分大于阈值的组,得到组中分数最高的关键帧们作为闭环候选关键帧。将最终的候选的关键帧放入vpLoopCandidates容器中,返回给上层函数。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java基于ssm的图书管理系统图书借阅管理网站图书管理网站源码

简介 本项目是图书借阅管理系统&#xff0c;主要实现了对图书的管理和借阅。 演示视频 https://www.bilibili.com/video/BV14p4y1H7GQ/?share_sourcecopy_web&vd_sourceed0f04fbb713154db5cc611225d92156 技术 ssmjqueryajaxmysql 角色 管理员学生 功能 管理员&am…

带着刚刷题的你一步步学会刷题:989. 数组形式的整数加法

这是一道很经典的题目啊&#xff0c;考的就是数字数组转换&#xff0c;思路不难&#xff0c;但是在写的时候一步一步改代码&#xff0c;去优化复杂度&#xff0c;也是有助于学习的&#xff0c;今天刷了一下&#xff0c;也分享出来&#xff0c;建议刚开始刷题的友友们可以做一做…

【 java 集合】Map 接口常用实现类对比

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

P9 PyTorch 导数,偏微分,梯度

参考&#xff1a; 多元函数的偏导数、方向导数、梯度以及微分之间的关系思考 - 知乎 关于梯度下降与Momentum通俗易懂的解释_ssswill的博客-CSDN博客_有momentum之后还要梯度剪裁吗 前言&#xff1a; 这里简单了解一下 导数 梯度 微分的概念。 在前面矩阵求导术里面介绍过 梯…

表格控件DHTMLX Spreadsheet 5.0版本重大更新,新增搜索和过滤数据、合并单元格、自动宽度功能

DHTMLX Spreadsheet是用纯JavaScript编写的开源电子表格小部件&#xff0c;可让您快速在网页上添加类似于Excel的可编辑数据表。高度可定制的JavaScript电子表格组件&#xff0c;具有优雅的Material样式&#xff0c;可安全、方便地编辑和格式化数据。本文给大家讲解DHTMLX Gant…

4种大文件传输工具和软件,用于共享大文件

无论是个人还是与团队一起工作&#xff0c;大文件传输软件和网站都能协助提高工作效率、有效地管理工作内容。疫情原因有时我们不得不居家办公&#xff0c;在这种情况下可以分享文件的工具就显得尤为重要。 每个公司都需要一个文件传输软件&#xff0c;让员工可以上传和分享他…

【华为机试真题详解】不含 101 的数(二)【2022 Q4 | 100分】

文章目录 前言题目解析参考代码前言 《华为机试真题详解 Python实现》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过…

Docker 从入门到精通

目录 一、安装Docker 1. 安装必要的包 2. 设置镜像的仓库 3. 更新软件包的索引 4. 安装docker 5. 启动docker 6. 测试 hello-world 7. 查看的hello-world镜像 8. 卸载docker 9. 配置阿里云镜像加速 二、Docker 常用命令 镜像命令 &#xff08;1&#xff09;docker …

4.2 集成运放中的电流源电路

集成运放电路中的晶体管和场效应管&#xff0c;除了作为放大管外&#xff0c;还构成电流源电路&#xff0c;为各级提供合适的静态电流&#xff1b;或作为有源负载取代高阻值的电阻&#xff0c;从而提高放大电路的放大能力。 一、基本电流源电路 1、镜像电流源 图4.2.1所示为…

SAP FICO 内部订单解析

内部订单提供成本控制和短期的工作与任务的监测。内部订单通常被用于内部工作和任务的计划、信息收集和成本清算等等&#xff0c;如市场营销活动和工作修复等。成本中心用于长期成本管理&#xff0c;而内部订单则用于中短期的成本征收。整个订单生命周期过程&#xff08;从订单…

mysqldump命令备份数据库数据

#MySQLdump常用 mysqldump -u root -p --databases 数据库1 数据库2 > xxx.sql备份全部数据库的数据和结构mysqldump -u root -hlocalhost -p123456 -A > /data/mysqlDump/mydb.sql备份全部数据库的结构(加-d参数)mysqldump -u root -hlocalhost -p123456 -A -d > /da…

【测试】Bug篇

努力经营当下&#xff0c;直至未来明朗&#xff01; 文章目录一. 如何创建Bug二&#xff0e;Bug的级别三&#xff0e;Bug的生命周期四&#xff0e;跟开发起争执怎么办【高频面试题】:sparkles:小结普通小孩也要热爱生活&#xff01; 一. 如何创建Bug 创建Bug的要素&#xff1…

逻辑卷管理器:PV、PE、VG、LV

LVM&#xff1a;Logical Volume Manager&#xff0c;逻辑卷管理器。重点&#xff1a;可以弹性的调整文件系统的容量&#xff0c;而不在于性能和数据安全上面&#xff0c;因此如果强调性能和备份&#xff0c;那么直接使用raid即可&#xff0c;不需要用到LVM。 LVM可以整合多个物…

利用VNC远程连接Ubuntu server(图形界面)

有时会需要远程连上ubuntu server图形界面控制调试&#xff0c;这时VNC就是一个挺好的工具&#xff0c; windows 上安装 vnc viewer &#xff0c; ubuntu server 上安装vnc server 进行连接即可 一、ubuntu 安装vnc server 1.sudo apt-get install vnc4server 2.修改vnc pwd …

Django-ORM框架操作数据库不生效问题的定位示例

本文详细描述使用Django 的ORM框架操作PostgreSQL数据库删除不生效问题的定位过程及解决方案&#xff0c;并总结使用ORM框架操作数据库不生效的问题的通用定位方法 问题描述 最近使用Django 的ORM框架操作PostgreSQL数据库总是出现删除不生效&#xff08;尤其是在并发的时候&…

C#/.Net开发chatGPT、openAI

C#/.Net开发chatGPT、openAI 最近ChatGPT火爆了&#xff0c;自己使用了一下&#xff0c;确实厉害。但是使用官方网站不支持国内访问&#xff0c;好在国内可以使用API调用&#xff0c;所以自己折腾一番&#xff0c;使用C#来调用API。 获取Token 注册账号获取api-keys等操作可…

HR软件如何人性化管理提高留存率

一直以来&#xff0c;我们都在强调“人是企业最大的资产”&#xff0c;这应该是新时代下&#xff0c;企业对于人才管理的共识。在这样的环境中&#xff0c;人力资源部门承担着重要的责任&#xff0c;HR需要迎合当前的人才需求和管理趋势&#xff0c;在“技术运用”和“人性管理…

激活函数、Sigmoid激活函数、tanh激活函数、ReLU激活函数、Leaky ReLU激活函数、Parametric ReLU激活函数详细介绍及其原理详解

相关文章 梯度下降算法、随机梯度下降算法、动量随机梯度下降算法、AdaGrad算法、RMSProp算法、Adam算法详细介绍及其原理详解反向传播算法和计算图详细介绍及其原理详解激活函数、Sigmoid激活函数、tanh激活函数、ReLU激活函数、Leaky ReLU激活函数、Parametric ReLU激活函数…

从技术、产品、运营3个维度详尽阐述从0到1搭建用户画像系统

通过阅读以下原文获取下载链接。 ​​​​​从技术、产品、运营3个维度详尽阐述从0到1搭建用户画像系统 1 简介 本书借助数据仓库实现一套用户画像系统的方案。从实际工程案例出发&#xff0c;结合多业务场景&#xff0c;内容涵盖开发离线批处理计算的标签及流式计算标签&am…

【C语言进阶】 带你玩转指针

指针进阶一、字符指针二、指针数组三、数组指针3.1&#xff1a;数组指针的使用四、数组参数、指针参数4.1&#xff1a;一维数组传参4.2&#xff1a;二维数组传参4.3&#xff1a;一级指针传参&#xff1a;4.4&#xff1a;二级指针传参&#xff1a;五&#xff1a;函数指针一、字符…