ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析

/函数的三要素是:函数返回值类型,函数名称,函数参数
函数的返回值是装有关键帧指针的vector
该函数是类KeyFrameDatabase的成员函数,函数名是DetectLoopCandidate
该函数的参数分别是KeyFrame类型的指针变量 pKF和最小得分vector<KeyFrame*> KeyFrameDatabase::DetectLoopCandidates(KeyFrame* pKF, float minScore)
{spConnectedKeyFrames是一个set定义的变量,set中装的是在covisibility graph中与关键帧pKF相关联的关键帧。GetConnectedKeyFrame()是类KeyFrame的成员函数,通过遍历变量map变量                 mConnectedKeyFrameWeights来得到关联帧。map<KeyFrame*, int> mConnectedKeyFrameWeights;set 有自动排序功能,不能直接存取元素list不可以随机存取元素set<KeyFrame*> spConnectedKeyFrames = pKF->GetConnectedKeyFrames();list<KeyFrame*> lKFsSharingWords;// Search all keyframes that share a word with current keyframes// Discard keyframes connected to the query keyframe{unique_lock<mutex> lock(mMutex);//遍历pKF中所有生成的Bow向量for(DBoW2::BowVector::const_iterator vit=pKF->mBowVec.begin(), vend=pKF->mBowVec.end(); vit != vend; vit++){//在inverse indexes中查找该word都在哪些图像中出现过list<KeyFrame*> &lKFs =   mvInvertedFile[vit->first];//遍历这些查找出来的与pKF有共视的word的关键帧for(list<KeyFrame*>::iterator lit=lKFs.begin(), lend= lKFs.end(); lit!=lend; lit++){//紧接着这一小段程序可以统计pKF与pKFi共视words的个数。//到了这里就是说pKF与pKFi有共视关系,但是并不是pKFi都可以被认为是闭环候选帧//只有当pKFi不是在covisibility graph中与pKF直接相连的关键帧才有机会入围。KeyFrame* pKFi=*lit;//如果pKFi是第一次被pKF查询,那么先初始化成员变量mnLoopwords为0//经判断pKFi确实不与pKF直接相连则将成员变量mnLoopQuery设置为pKF的Id号码//表示pKFi已经被pKF查询过,下次再次查询pKFi的时候//pKFi->mnLoopQuery = pKF->mnId 则直接让 pKFi->mnLoopWords++;//并且将pKFi插入到lKFsSharingwords中去。if(pKFi->mnLoopQuery!=pKF->mnId){pKFi->mnLoopWords=0;if(!spConnectedKeyFrames.count(pKFi)){pKFi->mnLoopQuery=pKF->mnId;lKFsSharingWords.push_back(pKFi);}}pKFi->mnLoopWords++;}}}if(lKFsSharingWords.empty())return vector<KeyFrame*>();//IScoreAndMatch变量中与pKF有共视关系的关键帧以及两者之间的得分//pair<float, KeyFrame>pair的使用是将两者捆绑到一起存储list<pair<float,KeyFrame*> > lScoreAndMatch;int maxCommonWords=0;//遍历那些所有与pKF有共视关系又满足条件的存储在lKFsSharingWords中的关键帧for(list<KeyFrame*>::iterator lit=lKFsSharingWords.begin(), lend= lKFsSharingWords.end(); lit!=lend; lit++){//从上面的程序我们知道mnLoopWords变量中存储了该关键帧与pKF的共视word数目//找到这些所有与pKF有共视关系的关键帧中与pKF共视word最大值 maxCommonWordsif((*lit)->mnLoopWords>maxCommonWords)maxCommonWords=(*lit)->mnLoopWords;}//但是我们如果要求这么严格,那满足我们条件的关键帧真的是寥寥无几啦,所以为了得到多一些的//闭环候选帧我们不得不降低要求,让前20%的关键帧都能进入下一轮的比赛。//如果这个要求您都不能满足的话,那对不起,您只能等下一次了。int minCommonWords = maxCommonWords*0.8f;int nscores=0;//再次遍历lKFsSharingWords中存储的所有与pKF有共视关系的关键帧for(list<KeyFrame*>::iterator lit=lKFsSharingWords.begin(), lend= lKFsSharingWords.end(); lit!=lend; lit++){//将每一个关键帧单独拿出来,看一看他的mnLoopWords与minCommonWords的大小KeyFrame* pKFi = *lit;if(pKFi->mnLoopWords>minCommonWords){nscores++;//对于那些共视单词数满足条件的pKFi计算与pKF之间的BoW得分float si = mpVoc->score(pKF->mBowVec,pKFi->mBowVec);//mLoopScore目前的值是pKFi与pKF之间的Bow得分。pKFi->mLoopScore = si;//只有那些得分大于minScore的pKFi才可以留下第三关:Bow得分限制if(si>=minScore)lScoreAndMatch.push_back(make_pair(si,pKFi));}}if(lScoreAndMatch.empty())return vector<KeyFrame*>();list<pair<float,KeyFrame*> > lAccScoreAndMatch;float bestAccScore = minScore;// Lets now accumulate score by covisibility//遍历所有上一贯留下的关键帧pKFifor(list<pair<float,KeyFrame*> >::iterator it=lScoreAndMatch.begin(), itend=lScoreAndMatch.end(); it!=itend; it++){//单独拿出每一帧KeyFrame* pKFi = it->second;//查找在covisibility graph上与pKFi连接最密切的10个关键帧vector<KeyFrame*> vpNeighs = pKFi->GetBestCovisibilityKeyFrames(10);//bestScore初始化为pKFi与pKF之间的得分float bestScore = it->first;//这个累计得分accScore也被初始化为pKFi与pKF之间的得分float accScore = it->first;//而最佳帧选也初始化为pKFiKeyFrame* pBestKF = pKFi;//遍历每一个pKFi的10个联系最为密切的关键帧for(vector<KeyFrame*>::iterator vit=vpNeighs.begin(), vend=vpNeighs.end(); vit!=vend; vit++){KeyFrame* pKF2 = *vit;//如果在这10个关键帧中有之前被pKF查询过(即有共视单词),并且共视的单词数还满足//大于minCommonwords的要求if(pKF2->mnLoopQuery==pKF->mnId && pKF2->mnLoopWords>minCommonWords){//那么就要在原来pKFi与pKF得分的基础上再加上pKFi的“好友”pKF2与pKF之间的得分accScore+=pKF2->mLoopScore;//残忍的时刻到了,倘若pKF2与pKF之间的得分要比pKFi大,//pKF2就会超过pKFi pBestKF就成了pKF2了if(pKF2->mLoopScore>bestScore){pBestKF=pKF2;bestScore = pKF2->mLoopScore;}}}//现在存储是从多个成员是11的小组内选择出的与pKF得分最高的pBestKF以及累计得分accScorelAccScoreAndMatch.push_back(make_pair(accScore,pBestKF));//并且在所有的accScore中找到那个最大的得分bestAccScore.if(accScore>bestAccScore)bestAccScore=accScore;}//但是为了能够得到多一些的闭环候选帧,需要降低要求,将那些上一关留下来分数靠前25%的关键帧//留下来float minScoreToRetain = 0.75f*bestAccScore;set<KeyFrame*> spAlreadyAddedKF;vector<KeyFrame*> vpLoopCandidates;vpLoopCandidates.reserve(lAccScoreAndMatch.size());//遍历所有上一关留下的关键帧for(list<pair<float,KeyFrame*> >::iterator it=lAccScoreAndMatch.begin(), itend=lAccScoreAndMatch.end(); it!=itend; it++){//将那些上一关留下来分数靠前25%的关键帧留下来if(it->first>minScoreToRetain){KeyFrame* pKFi = it->second;//如果检测到set中已经有pKFi了就不要重复插入了,其实这个判断是多余的//set本来就具有值唯一性,不可以存入重复的值。if(!spAlreadyAddedKF.count(pKFi)){vpLoopCandidates.push_back(pKFi);spAlreadyAddedKF.insert(pKFi);}}}//最后终于得到了想要的关键帧,就想皇帝选妃子,需要层层选拔//可以走到这里的关键帧真的是过五关斩六将了//第一关:与pKF有共视单词的pKF1,且不能是与pKF在covisibility graph中与pKF直接相连的//关键帧//第二关:共视单词数必须大于minCommonWords的才可以留下 pKF2//第三关:pKF2中与pKF的BOw得分必须大于minScore的才可以留下 pKF3//第四关:pKF3要与自己最亲密的“朋友”PK与pKF之间的共视单词数,留下的记为pKF4//第五关:pKF4中那些与pKF得分大于minScoreToRetain的才可以最终留下来 记为pKF5;return vpLoopCandidates;
}

 

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

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

相关文章

NYOJ2—括号配对问题

括号配对问题 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB 难度&#xff1a;3描述现在&#xff0c;有一行括号序列&#xff0c;请你检查这行括号是否配对。输入第一行输入一个数N&#xff08;0<N<100&#xff09;,表示有N组测试数据。后面的N行输入多…

李彦宏千字愿景内部信:10次提到“用户”

中新网1月17日电 1月17日&#xff0c;百度公司创始人、董事长兼CEO李彦宏发出一封内部信&#xff0c;信中&#xff0c;李彦宏向员工阐述了百度愿景&#xff1a;成为最懂用户&#xff0c;并能帮助人们成长的全球顶级高科技公司。他提出&#xff0c;百度要持续创新&#xff0c;“…

spring-boot 速成(8) 集成druid+mybatis

spring-boot与druid、mybatis集成&#xff08;包括pageHelper分页插件&#xff09;, 要添加以下几个依赖项: compile(mysql:mysql-connector-java:6.0.5)compile(tk.mybatis:mapper-spring-boot-starter:1.1.1)compile(org.mybatis.spring.boot:mybatis-spring-boot-starter:1.…

ORB-SLAM2中生成金字塔提取FAST角点和计算BRIEF描述子

//这个是类ORBextractor的带参构造函数&#xff0c;并且使用初始化列表对该类中的这5个变量赋值 ORBextractor::ORBextractor(int _nfeatures, float _scaleFactor, int _nlevels,int _iniThFAST, int _minThFAST):nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(…

我们怎样确保从大数据计算中获得价值

我们怎样确保从大数据计算中获得价值 支持大数据方案并不是在硬件以及软件层次终止&#xff0c;企业要想真正地从大数据中受益&#xff0c;领导者必须改变思考与对待信息的方式。 我们怎样确保从大数据计算中获得价值&#xff1f; 当所有可用数据都可用时&#xff0c;大数据…

jsoncpp-src-0.5.0.tar.gz 源码错误!!!!

近期在做毕设&#xff0c;使用到了JsonCpp0.5.0版本号的源码&#xff01;依照网上的安装配置教程&#xff0c;搭建好环境后就能够使用了&#xff01; 在这里就不浪费空间去将怎样搭建开发环境了&#xff01;请大家去google一下就好了&#xff01;在解析一个Json文件时。程序总是…

青海省多地日降水量突破历史极值

受高原槽和西北冷空气的共同影响&#xff0c;青海省海西州茫崖等多地日降水量突破历史极值。 李万花 摄 受高原槽和西北冷空气的共同影响&#xff0c;青海省海西州茫崖等多地日降水量突破历史极值。 李万花 摄 中新网西宁1月18日电 (孙睿 赵海梅)记者18日从青海省气象局获悉&am…

ORB-SLAM2中四叉树管理特征点

当从图像金字塔中的每一层图像上提取特征点之后&#xff0c;都要先用四叉树技术对这些特征点进行管理 //该类中定义了四叉树创建的函数以及树中结点的属性 //bool bNoMore&#xff1a; 根据该结点中被分配的特征点的数目来决定是否继续对其进行分割 //DivisionNode()&#xff…

Python多线程3:queue

queue模块实现了多生产者。多消费者队列。在多线程环境下&#xff0c;该队列能实现多个线程间安全的信息交换。 queue模块介绍 模块实现了3种类型的队列&#xff0c;差别在于队列中条目检索的顺序不同。在FIFO队列中。依照先进先出的顺序检索条目。在LIFO队列中&#xff0c;最后…

微信小程序教程02:App(Object)和Page(Object) 构造器介绍

在/app.js中&#xff0c;有方法App&#xff0c;它的作用是注册整个小程序的应用&#xff0c;其中可以传入一些配置&#xff0c;或者存储全局状态。 App(Object) 构造器生命周期 属性类型描述onLaunchFunction在小程序初始化时触发&#xff0c;全局仅触发一次onShowFunction小程…

阿里云.log

申请证书审核失败的原因及处理方法;( 新添加站点 免费版 SSL 网页内不能有 HTTPS的连接&#xff1b;更多点击连接) 转载于:https://www.cnblogs.com/q1104460935/p/8287377.html

SharePoint Search之(七)Search result- 结果源

在使用搜索引擎的时候。非常多情况下&#xff0c;用户希望限定一下搜索范围&#xff0c;以便更加easy找到想要的结果。在SharePoint 2013的search里&#xff0c;也支持类似的功能&#xff0c;SharePoint 默认提供了几种范围&#xff1a; 在SharePoint&#xff0c;这个叫Search …

旷视砸20亿进军AIoT,发布国内首个机器人协作大脑河图

1 月 16 日&#xff0c;人工智能独角兽旷视科技发布了机器人战略&#xff0c;以及自 2018 年 4 月收购艾瑞思机器人&#xff0c;进军机器人领域的最新进展——智能协同大脑河图。在会上&#xff0c;旷视还大笔一挥&#xff0c;决定投入 20 亿元&#xff0c;用于打造物流仓储上下…

ORB-SLAM2-金字塔求解-特征点的提取-描述子的计算

//这个成员函数重载了函数括号运算符&#xff0c;让他具有函数的特点 //但是还不知道在其他程序块是如何应用这块代码的。 //InputArray和OutputArray是opencv中的两个函数接口 void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>&a…

am335x uboot, kernel 编译

一、设置环境变量// 写在家目录下面的 .bashrc 里面export KERNEL_PATH~/aplex/kernel3.2.0 // kernel 路径export UBOOT_PATH~/aplex/uboot2011.09 // u-boot 路劲export ROOTFS_PATH~/aplex/filesystemexport TOOLFS_PATH~/aplex/toolsexport ARCHarm …

php+ajax简单实现跨域(http+https)请求调用

当一个网站 a站 需要调用另一个网站 b站 列表文章时 比如&#xff1a;www.a123.com 调用 www.b456.com 文章 在 a站 建立php文件获取 b站 资源文章到本地后&#xff0c;再传递a站前端 在网站 b456 下的文件为 <ul class"ls_wz"> <li><a href"#&q…

ORB-SLAM2中MapPoints的描述子的计算

//我们在从金字塔的图像中获取特征点时为每一个特征点计算了描述子 //现在看看如何计算一个空间的地图点的描述子 void MapPoint::ComputeDistinctiveDescriptors() {// Retrieve all observed descriptorsvector<cv::Mat> vDescriptors;//获取到某一个地图点可以被哪些关…

HDU:4185-Oil Skimming

Oil Skimming Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Thanks to a certain “green” resources company, there is a new profitable industry of oil skimming. There are large slicks of crude oil floa…

域控制器情况分析

域控制器情况分析 1、Windows Server 的 Foundation、Standard、Enterprise 以及 Datacenter 版本号既可作为源server&#xff0c;也可作为目标server。仅支持将 Foundation Server 版本号作为受限方案中的目标server。在使用 Foundation Server 作为目标server之前&#xff0c…