前言
简单总结一下:将共视关键帧设置为局部关键帧将共视最高的关键帧设置为参考关键帧
当前帧F的局部关键帧包括:
1.能够观测到当前帧F中地图点的共视关键帧KF1、KF2, 称为一级共视关键帧。
2. 一级共视关键帧的共视关键帧(代码中取前10 个共视程度最高的关键帧)比如图中的KF1的共视关键帧为KF3 、KF4,KF2 的共视关键帧为KF5 、KF6, 称为二级共视关键帧。
3.一级共视关键帧的父关键帧和子关键帧。当前关键帧共视程度最高的关键帧称为父关键帧,反过来,当前关键帧称为对方的子关键帧。图中KF7是KF1的父关键帧;反过来, KF1是KF7 的子关键帧。一个关键帧只有一个父关键帧,但可以有多个子关键帧。
总结: 图中当前帧F的局部关键帧为一级共视关键帧KF1 、KF2, 二级共视关键帧KF3 、KF4 、KF5 、KF6, 一级共视关键帧的父子关键帧KF7 、KF8。
1.函数声明
void Tracking::UpdateLocalKeyFrames()
2.函数定义
具体流程如下:
1.找到和当前帧所有共视的关键帧。
// Each map point vote for the keyframes in which it has been observed
// Step 1:遍历当前帧的地图点,记录所有能观测到当前帧地图点的关键帧
map<KeyFrame*,int> keyframeCounter;//创建一个map容器
for(int i=0; i<mCurrentFrame.N; i++)//遍历当前帧的地图点。
{
if(mCurrentFrame.mvpMapPoints[i])//检查这个地图点是否存在。
{
MapPoint* pMP = mCurrentFrame.mvpMapPoints[i];//赋值给局部变量便于后续操作。
if(!pMP->isBad())//判断地图点的好坏。
{
// 得到观测到该地图点的关键帧和该地图点在该关键帧观察到的地图点中的索引
const map<KeyFrame*,size_t> observations = pMP->GetObservations();
// 由于一个地图点可以被多个关键帧观测到,因此对于每一次观测,都对观测到这个地图点的关键帧进行累计投票
for(map<KeyFrame*,size_t>::const_iterator it=observations.begin(), itend=observations.end(); it!=itend; it++)
// 这里的操作非常精彩!
// map[key] = value,当要插入的键存在时,会覆盖键对应的原来的值。如果键不存在,则添加一组键值对
// it->first 是地图点看到的关键帧,同一个关键帧看到的地图点会累加到该关键帧计数
// 所以最后keyframeCounter 第一个参数表示某个关键帧,第2个参数表示该关键帧看到了多少当前帧(mCurrentFrame)的地图点,也就是共视程度
keyframeCounter[it->first]++;
}
else
{
mCurrentFrame.mvpMapPoints[i]=NULL;
}
}
}
// 当前帧没有共视关键帧,返回
if(keyframeCounter.empty())
return;
2.开始更新局部关键帧,主要添加三种类型的关键帧
添加前的准备
// 存储具有最多观测次数(max)的关键帧
int max=0;
KeyFrame* pKFmax= static_cast<KeyFrame*>(NULL);
// Step 2:更新局部关键帧(mvpLocalKeyFrames),添加局部关键帧有3种类型
// 先清空局部关键帧
mvpLocalKeyFrames.clear();
// 先申请3倍内存,不够后面再加
mvpLocalKeyFrames