2021SC@SDUSC
KeyFrame中有一个很重要的概念共视图
1.首先解释一下什么是共视图(mConnectedKeyFrameWeights
):能看到同一地图点的两关键帧之间存在共视关系,共视地图点的数量被称为权重.
2.共视图结构由3个成员变量维护:
mConnectedKeyFrameWeights是一个std::map,无序地保存当前关键帧的共视关键帧及权重.
mvpOrderedConnectedKeyFrames和mvOrderedWeights按权重降序分别保存当前关键帧的共视关键帧列表和权重列表.
3.下面解释几个有关关键帧的成员函数
void KeyFrame::AddConnection(KeyFrame *pKF, const int &weight) {
// step1. 修改变量mConnectedKeyFrameWeights
{
unique_lock<mutex> lock(mMutexConnections);
if (!mConnectedKeyFrameWeights.count(pKF) || mConnectedKeyFrameWeights[pKF] != weight)
mConnectedKeyFrameWeights[pKF] = weight;
else
return;
}
// step2. 调用函数UpdateBestCovisibles()修改变量mvpOrderedConnectedKeyFrames和mvOrderedWeights
UpdateBestCovisibles();
}
在map<KeyFrame*,int> mConnectedKeyFrameWeights容器中加入此关键帧;
对mConnectedKeyFrameWeights中存储的关键帧集按照连接权重进行降序排序,排序之后的关键帧存储到mvpOrderedConnectedKeyFrames中,排序后的关键帧存储到mvOrderedWeights中
2)将关联的关键帧进行排序
void KeyFrame::UpdateBestCovisibles() {
unique_lock<mutex> lock(mMutexConnections);
// 取出所有关键帧进行排序,排序结果存入变量mvpOrderedConnectedKeyFrames和mvOrderedWeights中
vector<pair<int, KeyFrame *> > vPairs;
vPairs.reserve(mConnectedKeyFrameWeights.size());
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++) {
lKFs.push_front(vPairs[i].second);
lWs.push_front(vPairs[i].first);
}
mvpOrderedConnectedKeyFrames = vector<KeyFrame *>(lKFs.begin(), lKFs.end());
mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());
}
对mConnectedKeyFrameWeights中存储的关键帧集按照连接权重进行降序排序,排序之后的关键帧存储到mvpOrderedConnectedKeyFrames中,排序后的关键帧存储到mvOrderedWeights中
3)返回关联关键帧(关联关键帧是指权重大于15的共视关键帧)
set<KeyFrame*> KeyFrame::GetConnectedKeyFrames()
抽取mConnectedKeyFrameWeights容器中存储的关键帧集返回
4)更新连接,创建共视图
void KeyFrame::UpdateConnections() {
// 第一步. 通过遍历当前帧地图点获取其与其它关键帧的共视程度,存入变量KFcounter中
vector<MapPoint *> vpMP;
{
unique_lock<mutex> lockMPs(mMutexFeatures);
vpMP = mvpMapPoints;
}
map<KeyFrame *, int> KFcounter;
for (MapPoint *pMP : vpMP) {
map<KeyFrame *, size_t> observations = pMP->GetObservations();
for (map<KeyFrame *, size_t>::iterator mit = observations.begin(); mit != observations.end(); mit++) {
if (mit->first->mnId == mnId) // 与当前关键帧本身不算共视
continue;
KFcounter[mit->first]++;
}
}
// 第二步. 找到与当前关键帧共视程度超过15的关键帧,存入变量vPairs中
vector<pair<int, KeyFrame *> > vPairs;
int th = 15;
int nmax = 0;
KeyFrame *pKFmax = NULL;
for (map<KeyFrame *, int>::iterator mit = KFcounter.begin(), mend = KFcounter.end(); mit != mend; mit++) {
if (mit->second > nmax) {
nmax = mit->second;
pKFmax = mit->first;
}
if (mit->second >= th) {
vPairs.push_back(make_pair(mit->second, mit->first));
(mit->first)->AddConnection(this, mit->second); // 对超过阈值的共视边建立连接
}
}
// 第三步. 对关键帧按照共视权重降序排序,存入变量mvpOrderedConnectedKeyFrames和mvOrderedWeights中
sort(vPairs.begin(), vPairs.end());
list<KeyFrame *> lKFs;
list<int> lWs;
for (size_t i = 0; i < vPairs.size(); i++) {
lKFs.push_front(vPairs[i].second);
lWs.push_front(vPairs[i].first);
}
{
unique_lock<mutex> lockCon(mMutexConnections);
mConnectedKeyFrameWeights = KFcounter;
mvpOrderedConnectedKeyFrames = vector<KeyFrame *>(lKFs.begin(), lKFs.end());
mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());
// 第四步. 对于第一次加入生成树的关键帧,取共视程度最高的关键帧为父关键帧
if (mbFirstConnection && mnId != 0) {
mpParent = mvpOrderedConnectedKeyFrames.front();
mpParent->AddChild(this);
mbFirstConnection = false;
}
}
}