KeyFrame中維護了一個map,保存了與當前幀共視的KeyFrame*與權重(共視MapPonits數量)。對關鍵幀之間關係是用加權有向圖來完成的,那麼理解其spanning tree生成樹的原理就頗有必要了。後端
KeyFrame中比較難理解的是SetBagFlag()函數,真實刪除當前關鍵幀以前,須要處理好父親和兒子關鍵幀關係,否則會形成整個關鍵幀維護的圖斷裂,或者混亂,不可以爲後端提供較好的初值。函數
理解起來就是父親掛了,兒子須要找新的父親,在候選父親裏找,當前幀的父親(mpParent)確定在候選父親中的;oop
1. 首先將當前幀的父親,放入候選父親中spa
sParentCandidates.insert(mpParent);
2. 遍歷當前幀的全部兒子,而後遍歷兒子A的每一個共視幀,若是其中有候選父親,則將A的父親更新爲該候選父親,而且將A放入候選父親中(由於這時候A已經將整個圖聯繫起來了);若是沒有,break。若是遍歷一圈下來,發現有的兒子尚未找到新父親,例如兒子B的共視幀不是候選父親裏的任何一個。這種狀況出如今,B和當前幀的父親不存在共視關係(速度太快,旋轉太急,匹配跟丟)。而且B與當前幀的兒子之間也沒有共視關係:當前幀不是一個好的關鍵幀,原本就沒有多少兒子;或者B自己是個例外,恩,反正B是個孤家寡人。。。那麼直接將B的父親設置爲當前幀的父親,交給爺爺去管。code
while(!mspChildrens.empty()) { bool bContinue = false; int max = -1; 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=0, 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. 具體刪除一個關鍵幀的步驟是這樣的:blog
1) 初始mbNotErase狀態是true,那麼調用SetBadFlag後,將mbToBeErased狀態置爲true,而後return,並無執行SetBadFlag()中後面的代碼。ci
2) 而後調用SetErase(),這時首先要檢查mspLoopEdges是不是空的!由於若是當前幀維護了一個迴環,刪了該關鍵幀迴環就沒了。。。一般狀況下是空的,那麼把mbNotErase置爲false,此時再在SetErase()中調用SetBagFlag時,就會真正去執行刪除該幀的代碼了。it
總結一下就是,首先設置爲壞幀,若是該幀不是迴環幀,則能夠真的刪掉;若是該幀是迴環幀,怎麼都刪不掉的。。。class