KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量)。对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理就很有必要了。

KeyFrame中比较难理解的是SetBagFlag()函数,真实删除当前关键帧之前,需要处理好父亲和儿子关键帧关系,不然会造成整个关键帧维护的图断裂,或者混乱,不能够为后端提供较好的初值。

理解起来就是父亲挂了,儿子需要找新的父亲,在候选父亲里找,当前帧的父亲(mpParent)肯定在候选父亲中的;

1. 首先将当前帧的父亲,放入候选父亲中

sParentCandidates.insert(mpParent);

2. 遍历当前帧的所有儿子,然后遍历儿子A的每个共视帧,如果其中有候选父亲,则将A的父亲更新为该候选父亲,并且将A放入候选父亲中(因为这时候A已经将整个图联系起来了);如果没有,break。如果遍历一圈下来,发现有的儿子还没有找到新父亲,例如儿子B的共视帧不是候选父亲里的任何一个。这种情况出现在,B和当前帧的父亲不存在共视关系(速度太快,旋转太急,匹配跟丢)。并且B与当前帧的儿子之间也没有共视关系:当前帧不是一个好的关键帧,本来就没有多少儿子;或者B本身是个例外,恩,反正B是个孤家寡人。。。那么直接将B的父亲设置为当前帧的父亲,交给爷爷去管。

while(!mspChildrens.empty())
{
bool bContinue = false; int max = -;
KeyFrame* pC;
KeyFrame* pP; 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
vector<KeyFrame*> vpConnected = pKF->GetVectorCovisibleKeyFrames();
for(size_t i=, iend=vpConnected.size(); i<iend; i++)
{
for(set<KeyFrame*>::iterator spcit=sParentCandidates.begin(), spcend=sParentCandidates.end(); spcit!=spcend; spcit++)
{
  if(vpConnected[i]->mnId == (*spcit)->mnId)
  {
  int w = pKF->GetWeight(vpConnected[i]);
  if(w>max)
  {
  pC = pKF;
  pP = vpConnected[i];
  max = w;
  bContinue = true;
  }
  }
}
}
}
} if(bContinue)
{
pC->ChangeParent(pP);
sParentCandidates.insert(pC);
mspChildrens.erase(pC);
}
else
break;
} if(!mspChildrens.empty())
for(set<KeyFrame*>::iterator sit=mspChildrens.begin(); sit!=mspChildrens.end(); sit++)
{
(*sit)->ChangeParent(mpParent);
}

3. 具体删除一个关键帧的步骤是这样的:

  1) 初始mbNotErase状态是true,那么调用SetBadFlag后,将mbToBeErased状态置为true,然后return,并没有执行SetBadFlag()中后面的代码。

  2) 然后调用SetErase(),这时首先要检查mspLoopEdges是否是空的!因为如果当前帧维护了一个回环,删了该关键帧回环就没了。。。通常情况下是空的,那么把mbNotErase置为false,此时再在SetErase()中调用SetBagFlag时,就会真正去执行删除该帧的代码了。

总结一下就是,首先设置为坏帧,如果该帧不是回环帧,则可以真的删掉;如果该帧是回环帧,怎么都删不掉的。。。

ORB-SLAM(五)KeyFrame类-最小生成树的更多相关文章

  1. ORB-SLAM(五)KeyFrame类

    KeyFrame类利用Frame类来构造.对于什么样的Frame可以认为是关键帧以及何时需要加入关键帧,是实现在tracking模块中的. 由于KeyFrame中一部分数据会被多个线程访问修改,因此需 ...

  2. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  3. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  4. c++ 吕凤翥 第五章 类对象一

    一   类的声明和实现 1. class tdate   //声明部分 { public: void setdate(int y,int m,int d); int isleapyear(); voi ...

  5. Java基础复习笔记系列 五 常用类

    Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String ...

  6. Java编程思想学习(五) 复用类

    1.继承与组合 复用类的方法有两种:继承与组合.继承就不多说了,组合就是直接在类中new一个对象. 数组也是对象,使用数组也是组合的一种. 2.初始化基类 当创建一个导出类的对象时,该对象包含一个基类 ...

  7. C#基础(五)——类中私有构造函数作用

    如果类成员有private修饰符,就不允许在类范围以外访问这个类成员.对类构造函数应用private修饰符时,则禁止外部类创建该类的实例.尽管看上去有些不好理解(既然不能实例化,那么这个类还有什么用处 ...

  8. Java解惑五:类之谜

    本文是依据JAVA解惑这本书,做的笔记.电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题46 函数重载的问题. JAVA重载解析过程 ...

  9. PHP学习笔记二十五【类的继承】

    <?php //定义父类 class Stu{ public $name; protected $age; protected $grade; private $address;//私有变量不会 ...

随机推荐

  1. Django 模型中FileField字段

    FileField¶ class FileField([upload_to=None, max_length=100, **options])¶ 一个上传文件的字段. 注意 FileField字段不支 ...

  2. CRT公钥登录

    1.实现原理: 通过CRT生成的密钥对,把公钥上传到Linux服务器指定用户下的.ssh目录中,在客户端上只需输入秘钥的密码即可登陆,而且验证一次以后可以免密码登陆 2.具体过程: 转自:http:/ ...

  3. 【原创】多字节版本下MFC控件处理字符集的BUG

    工程项目属性: 字符集:多字节 stdafx.h文件中添加: #pragma comment(linker,"/manifestdependency:\"type='win32' ...

  4. HDU 3292 【佩尔方程求解 && 矩阵快速幂】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=3292 No more tricks, Mr Nanguo Time Limit: 3000/1000 M ...

  5. Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】

    传送门:http://codeforces.com/contest/1092/problem/D1 D1. Great Vova Wall (Version 1) time limit per tes ...

  6. javascript中数组的22种方法 (转载)

    前面的话 数组总共有22种方法,本文将其分为对象继承方法.数组转换方法.栈和队列方法.数组排序方法.数组拼接方法.创建子数组方法.数组删改方法.数组位置方法.数组归并方法和数组迭代方法共10类来进行详 ...

  7. angular.js和ionic框架搭建一个webApp

    原文地址:http://www.jianshu.com/p/ea0dcf1d31c9

  8. windows自带的netsh 端口转发

    netsh interface portproxy show v4tov4 (3)添加“端口映射” netsh interface portproxy add v4tov4 listenaddress ...

  9. js的匿名函数与自定义函数

    //匿名方法,会执行,自己调用自己 (function () { console.log(window.innerHeight); })(); (function () { console.log(w ...

  10. 冒泡排序_c++

    冒泡排序_c++ GitHub 文解 冒泡排序是采用类似气泡上升的方式对数据进行排序. 例如: 我们这里有10个元素,具体数值随意,对每个数值标记上 1~10 的标记. 首先将标记为 1 的数值与标记 ...