ORB-SLAM2 --- KeyFrame::SetBadFlag函数

article/2025/5/6 5:35:03

目录

1.函数作用

2.code 

3.函数解析 


1.函数作用

        真正地执行删除关键帧的操作。

        需要删除的是该关键帧和其他所有帧、地图点之间的连接关系。

2.code 

void KeyFrame::SetBadFlag()
{   // Step 1 首先处理一下删除不了的特殊情况{unique_lock<mutex> lock(mMutexConnections);// 第0关键帧不允许被删除if(mnId==0)return;else if(mbNotErase){// mbNotErase表示不应该删除,于是把mbToBeErased置为true,假装已经删除,其实没有删除mbToBeErased = true;return;}}// Step 2 遍历所有和当前关键帧相连的关键帧,删除他们与当前关键帧的联系for(map<KeyFrame*,int>::iterator mit = mConnectedKeyFrameWeights.begin(), mend=mConnectedKeyFrameWeights.end(); mit!=mend; mit++)mit->first->EraseConnection(this); // 让其它的关键帧删除与自己的联系// Step 3 遍历每一个当前关键帧的地图点,删除每一个地图点和当前关键帧的联系for(size_t i=0; i<mvpMapPoints.size(); i++)if(mvpMapPoints[i])mvpMapPoints[i]->EraseObservation(this); {unique_lock<mutex> lock(mMutexConnections);unique_lock<mutex> lock1(mMutexFeatures);// 清空自己与其它关键帧之间的联系mConnectedKeyFrameWeights.clear();mvpOrderedConnectedKeyFrames.clear();// Update Spanning Tree // Step 4 更新生成树,主要是处理好父子关键帧,不然会造成整个关键帧维护的图断裂,或者混乱// 候选父关键帧set<KeyFrame*> sParentCandidates;// 将当前帧的父关键帧放入候选父关键帧sParentCandidates.insert(mpParent);// Assign at each iteration one children with a parent (the pair with highest covisibility weight)// Include that children as new parent candidate for the rest// 每迭代一次就为其中一个子关键帧寻找父关键帧(最高共视程度),找到父的子关键帧可以作为其他子关键帧的候选父关键帧while(!mspChildrens.empty()){bool bContinue = false;int max = -1;KeyFrame* pC;KeyFrame* pP;// Step 4.1 遍历每一个子关键帧,让它们更新它们指向的父关键帧for(set<KeyFrame*>::iterator sit=mspChildrens.begin(), send=mspChildrens.end(); sit!=send; sit++){KeyFrame* pKF = *sit;// 跳过无效的子关键帧if(pKF->isBad())    continue;// Check if a parent candidate is connected to the keyframe// Step 4.2 子关键帧遍历每一个与它共视的关键帧    vector<KeyFrame*> vpConnected = pKF->GetVectorCovisibleKeyFrames();for(size_t i=0, iend=vpConnected.size(); i<iend; i++){// sParentCandidates 中刚开始存的是这里子关键帧的“爷爷”,也是当前关键帧的候选父关键帧for(set<KeyFrame*>::iterator spcit=sParentCandidates.begin(), spcend=sParentCandidates.end(); spcit!=spcend; spcit++){// Step 4.3 如果孩子和sParentCandidates中有共视,选择共视最强的那个作为新的父if(vpConnected[i]->mnId == (*spcit)->mnId){int w = pKF->GetWeight(vpConnected[i]);// 寻找并更新权值最大的那个共视关系if(w>max){pC = pKF;                   //子关键帧pP = vpConnected[i];        //目前和子关键帧具有最大权值的关键帧(将来的父关键帧) max = w;                    //这个最大的权值bContinue = true;           //说明子节点找到了可以作为其新父关键帧的帧}}}}}// Step 4.4 如果在上面的过程中找到了新的父节点// 下面代码应该放到遍历子关键帧循环中?// 回答:不需要!这里while循环还没退出,会使用更新的sParentCandidatesif(bContinue){// 因为父节点死了,并且子节点找到了新的父节点,就把它更新为自己的父节点pC->ChangeParent(pP);// 因为子节点找到了新的父节点并更新了父节点,那么该子节点升级,作为其它子节点的备选父节点sParentCandidates.insert(pC);// 该子节点处理完毕,删掉mspChildrens.erase(pC);}elsebreak;}// If a children has no covisibility links with any parent candidate, assign to the original parent of this KF// Step 4.5 如果还有子节点没有找到新的父节点if(!mspChildrens.empty())for(set<KeyFrame*>::iterator sit=mspChildrens.begin(); sit!=mspChildrens.end(); sit++){// 直接把父节点的父节点作为自己的父节点 即对于这些子节点来说,他们的新的父节点其实就是自己的爷爷节点(*sit)->ChangeParent(mpParent);}mpParent->EraseChild(this);// mTcp 表示原父关键帧到当前关键帧的位姿变换,在保存位姿的时候使用mTcp = Tcw*mpParent->GetPoseInverse();// 标记当前关键帧已经挂了mbBad = true;}  // 地图和关键帧数据库中删除该关键帧mpMap->EraseKeyFrame(this);mpKeyFrameDB->erase(this);
}

3.函数解析 

        先介绍mbNotErase作用:表示要删除该关键帧及其连接关系但是这个关键帧有可能正在回环检测或者计算sim3操作,这时候虽然这个关键帧冗余,但是却不能删除,仅设置mbNotErase为true,这时候调用setbadflag函数时,不会将这个关键帧删除,只会把mbTobeErase变成true,代表这个关键帧可以删除但不到时候,先记下来以后处理。在闭环线程里调用 SetErase函数会根据mbToBeErased来删除之前可以删除还没删除的帧。

        ①首先处理一下删除不了的特殊情况:

        即SLAM的第一帧不能被删除,因为其他帧的定位都靠第一帧,因此把mbToBeErased置为true,假装已经删除,其实没有删除。

        ②遍历所有和当前关键帧相连的关键帧,删除他们与当前关键帧的联系:

        mConnectedKeyFrameWeights存储当前关键帧的共视信息,记录当前关键帧共视关键帧的信息(哪一帧和当前关键帧有共视,共视程度是多少),是一个map<KeyFrame*,int>型变量,关于它的具体信息请参阅我的博客:

ORB-SLAM2 --- KeyFrame::UpdateConnections 函数解析icon-default.png?t=MBR7https://blog.csdn.net/qq_41694024/article/details/128516249        

    for(map<KeyFrame*,int>::iterator mit = mConnectedKeyFrameWeights.begin(), mend=mConnectedKeyFrameWeights.end(); mit!=mend; mit++)mit->first->EraseConnection(this); // 让其它的关键帧删除与自己的联系
void KeyFrame::EraseConnection(KeyFrame* pKF)
{// 其实这个应该表示是否真的是有共视关系bool bUpdate = false;{unique_lock<mutex> lock(mMutexConnections);if(mConnectedKeyFrameWeights.count(pKF)){mConnectedKeyFrameWeights.erase(pKF);bUpdate=true;}}// 如果是真的有共视关系,那么删除之后就要更新共视关系if(bUpdate)UpdateBestCovisibles();
}

        即对于每个与当前帧有共视的帧,如图中红色帧,将该红色帧中关于此帧的共视信息删掉(因为红色帧也有mConnectedKeyFrameWeights向量,保存着共视关系,其中有一条就是 <被删除帧>,共视地图点的索引,我们要删掉这条信息),同时删除之后要更新共视关系。

void KeyFrame::UpdateBestCovisibles()
{// 互斥锁,防止同时操作共享数据产生冲突unique_lock<mutex> lock(mMutexConnections);// http://stackoverflow.com/questions/3389648/difference-between-stdliststdpair-and-stdmap-in-c-stl (std::map 和 std::list<std::pair>的区别)vector<pair<int,KeyFrame*> > vPairs;vPairs.reserve(mConnectedKeyFrameWeights.size());// 取出所有连接的关键帧,mConnectedKeyFrameWeights的类型为std::map<KeyFrame*,int>,而vPairs变量将共视的地图点数放在前面,利于排序for(map<KeyFrame*,int>::iterator mit=mConnectedKeyFrameWeights.begin(), mend=mConnectedKeyFrameWeights.end(); mit!=mend; mit++)vPairs.push_back(make_pair(mit->second,mit->first));// 按照权重进行排序(默认是从小到大)sort(vPairs.begin(),vPairs.end());// 为什么要用链表保存?因为插入和删除操作方便,只需要修改上一节点位置,不需要移动其他元素list<KeyFrame*> lKFs;   // 所有连接关键帧list<int> lWs;          // 所有连接关键帧对应的权重(共视地图点数目)for(size_t i=0, iend=vPairs.size(); i<iend;i++){// push_front 后变成从大到小lKFs.push_front(vPairs[i].second);lWs.push_front(vPairs[i].first);}// 权重从大到小排列的连接关键帧mvpOrderedConnectedKeyFrames = vector<KeyFrame*>(lKFs.begin(),lKFs.end());// 从大到小排列的权重,和mvpOrderedConnectedKeyFrames一一对应mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());
}

        ③遍历每一个当前关键帧的地图点,删除每一个地图点和当前关键帧的联系:

void MapPoint::EraseObservation(KeyFrame* pKF)
{bool bBad=false;{unique_lock<mutex> lock(mMutexFeatures);// 查找这个要删除的观测,根据单目和双目类型的不同从其中删除当前地图点的被观测次数if(mObservations.count(pKF)){int idx = mObservations[pKF];if(pKF->mvuRight[idx]>=0)nObs-=2;elsenObs--;mObservations.erase(pKF);// 如果该keyFrame是参考帧,该Frame被删除后重新指定RefFrameif(mpRefKF==pKF)mpRefKF=mObservations.begin()->first;// If only 2 observations or less, discard point// 当观测到该点的相机数目少于2时,丢弃该点if(nObs<=2)bBad=true;}}if(bBad)// 告知可以观测到该MapPoint的Frame,该MapPoint已被删除SetBadFlag();
}

        ④更新生成树,主要是处理好父子关键帧,不然会造成整个关键帧维护的图断裂,或者混乱

        ⑤地图和关键帧数据库中删除该关键帧


http://chatgpt.dhexx.cn/article/8wgGM11G.shtml

相关文章

【视觉SLAM】Fast Relocalisation and Loop Closing in Keyframe-Based SLAM

See discussions, stats, and author profiles for this publication at: https://www.researchgate.net/publication/263621033 Article in Proceedings - IEEE International Conference on Robotics and Automation June 2014 DOI: 10.1109/ICRA.2014.6906953 先读Abstrac…

Android属性动画 Keyframe

转载请标明出处&#xff1a;http://blog.csdn.net/zhaoyanjun6/article/details/118963313 本文出自【赵彦军的博客】 文章目录 KeyFrame实战 KeyFrame KeyFrame 主要用于自定义控制动画速率&#xff0c;KeyFrame 直译过来就是关键帧。 而关键帧这个概念是从动画里学来的&…

ORB-SLAM2代码详解05: 关键帧KeyFrame

pdf版本笔记的下载地址: ORB-SLAM2代码详解05_关键帧KeyFrame,排版更美观一点,这个网站的默认排版太丑了&#xff08;访问密码&#xff1a;3834&#xff09; ORB-SLAM2代码详解05: 关键帧KeyFrame 各成员函数/变量共视图: mConnectedKeyFrameWeights基于对地图点的观测重新构造…

@keyframes详解

一、transform 和keyframes动画的区别&#xff1a; keyframes动画是循环的&#xff0c;而transform 只执行一遍. 二、keyframes CSS3中添加的新属性animation是用来为元素实现动画效果的&#xff0c;但是animation无法单独担当起实现动画的效果。承载动画的另一个属性——keyfr…

KeyFrame类

关键帧类主要是进行Covisbility Graph&#xff0c; Essential&#xff0c;Spanning Tree 三个图的维护&#xff0c;更新。 其中不涉及关键帧的筛选策略问题&#xff0c;只设置了剔除某关键帧和剔除关键帧后如何更新图的方法。总体来说&#xff0c;不难理解。 PS:本文设计多线程…

自定义控件三部曲之动画篇(八)——PropertyValuesHolder与Keyframe

前言&#xff1a;只有比牛人跑的更快&#xff0c;才有可能追上他的脚步。 相关文章&#xff1a; 《Android自定义控件三部曲文章索引》:http://blog.csdn.net/harvic880925/article/details/50995268 前几篇给大家讲了ValueAnimator、ObjectAnimator的知识&#xff0c;讲解了…

ORB-SLAM2从理论到代码实现(十四):KeyFrame类

1. 原理分析 KeyFrame为关键帧&#xff0c;关键帧之所以存在是因为优化需要&#xff0c;所以KeyFrame的几乎所有内容都是位优化服务的。该类中的函数较多&#xff0c;我们需要归类梳理一下&#xff0c;明白其功能原理&#xff0c;才能真正弄懂它的内容。 图优化需要构建节点和…

css基础(九)--keyframe

33.keyframe 关键帧&#xff0c;类似于flash中的关键帧&#xff0c;以keyframes开头紧跟着动画名称加上花括号&#xff5b;。。。&#xff5d;&#xff0c;括号中表示不同时间段样式规则 keyframes changecolor{ 0%{ background: red; } 100%{ background: green; } } 样式规…

windows10 企业版 ltsc系统的激活

具体步骤参考下面的网址内容&#xff1a; https://www.landiannews.com/archives/51131.html

win10哪个版本最好用,推荐win10企业版LTSC

win10企业版LTSC又被称为win10企业版2019长期服务版本&#xff0c;这个版本小编认为是目前最好用的win10版本,在win10企业版2016长期服务版本的基础上&#xff0c;微软做了大量优化和升级。win10企业版LTSC更加快捷和轻便。 现在很多网站上都是有人修改过的win10企业版LTSC安装…

一键解决Win10 LTSC 2021官方镜像存在的问题

一键解决Win10 LTSC 2021官方镜像存在的问题 由于适用了win10 ltsc 2021之后&#xff0c;发现官方镜像存在一些致命的bug。但是本人又喜欢这个官方精简的系统&#xff0c;所以进行了一些修复。并将搜集到的办法其汇总成一个一键修复脚本 Win10_LTSC_2021_FixPacks。来让其他用户…

Windows:MULTIPROCESSOR CONFIGURATION NOT SUPPORTED蓝屏(32位(win10/LTSC 2019/LTSC 2021))

网上的答案帮助不大&#xff0c;全靠摸索&#xff0c;记录一下 Content 1.环境2.案发现场(bushi3.解决方案 1.环境 所有32位win10操作系统应该都有这个问题&#xff08;旧版没装过&#xff09;&#xff0c;我的配置: CPU: i5 2400主板:戴尔DELL H61内存8G&#xff08;没必要关…

win10ltsc转版本,win10ltsc升级win11,无损

之前电脑有些卡&#xff0c;一时兴起&#xff0c;就装了比较精简的ltsc&#xff0c;一开始还挺好用。但后来用着用着发现确实少了很多东西&#xff0c;地图&#xff0c;相机&#xff0c;商店什么的都没了。后来又索性加装了一根内存条。 但是ltsc上的文件我又不想丢&#xff0…

[篇五章二]_使用 USB 系统安装盘在真机上安装激活 Windows 10 LTSC 2021 中文企业版系统

################################################## 目录 使用系统盘在真机上安装激活 Windows 10 操作系统 启动盘真机安装 Win 10 图文教程 烧录系统盘 插入开机 安装前设置 重要的分区 安装后设置 安装成功&#xff01; 关于 Windows 10 处于通知模式如何处理 …

Windows 10 Enterprise LTSC 2019 (x64) 版本 (安装+激活+添加系统邮箱)

1. 网站 https://msdn.itellyou.cn/ 下载。 2. 制作U盘启动&#xff0c;注意采用UEFIGPT模式&#xff0c;为什么呢&#xff0c;见链接https://blog.csdn.net/yang2716210363/article/details/78581388。 3. 装好后激活。 https://pan.baidu.com/s/1Zxy-kJHNOHbvLxc47wBs0Q c…

激活出现 错误0x800706F7 占位程序接收到错误数据

KMS 错误0x800706F7 占位程序接收到错误数据 &#xff08;SWbemObjectEx&#xff09; 解决办法&#xff1a; 退出360安全卫士。

windows10 提示系统激活失败,报错为:激活错误0xcc004f012

前因 买的笔记本有正版 win10 激活&#xff0c;但因为自己要往 c 盘复制东西改了 System32 文件的一些权限&#xff0c;后发现系统显示激活失败&#xff0c;错误代码为 0xcc004f012。 做法 WIN R 输入 services.msc 找到 Software Protection 服务 当时发现服务为停止状态&…

Microsoft Office 2021 LTSC 专业激活版 win/mac版

Office 2021它包含了Word、Excel、PowerPoint、Outlook、OneNote、Publisher以及Access等应用程序。这些应用程序都是专门为帮助用户轻松处理各种办公任务而设计的。 其中&#xff0c;Word是一款强大的文字处理软件&#xff0c;可以帮助用户创建和编辑文档&#xff1b;Excel是…

win10LTSC(企业版)命令激活

使用管理员权限依次复制粘贴 slmgr.vbs -skms zh.us.to slmgr -ipk M7XTQ-FN8P6-TTKYV-9D4CC-J462D slmgr -skms kms.03k.org slmgr -ato

聚类分析实验报告作业

课程《生物数据处理》 老师&#xff1a;邓阳君老师 要求&#xff1a;请采用 k 均值 、 k 中心点、层次聚类或者模糊聚类等对 iris 数据 进行聚类分析&#xff0c; 并评价其效果。实验报告应包括算法理论知识、算法代码、仿真实验结果及其分析等内 容&#xff0c;请于 5 …