ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析
生活随笔
收集整理的這篇文章主要介紹了
ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
/函數(shù)的三要素是:函數(shù)返回值類型,函數(shù)名稱,函數(shù)參數(shù)
函數(shù)的返回值是裝有關(guān)鍵幀指針的vector
該函數(shù)是類KeyFrameDatabase的成員函數(shù),函數(shù)名是DetectLoopCandidate
該函數(shù)的參數(shù)分別是KeyFrame類型的指針變量 pKF和最小得分vector<KeyFrame*> KeyFrameDatabase::DetectLoopCandidates(KeyFrame* pKF, float minScore)
{spConnectedKeyFrames是一個(gè)set定義的變量,set中裝的是在covisibility graph中與關(guān)鍵幀pKF相關(guān)聯(lián)的關(guān)鍵幀。GetConnectedKeyFrame()是類KeyFrame的成員函數(shù),通過(guò)遍歷變量map變量 mConnectedKeyFrameWeights來(lái)得到關(guān)聯(lián)幀。map<KeyFrame*, int> mConnectedKeyFrameWeights;set 有自動(dòng)排序功能,不能直接存取元素list不可以隨機(jī)存取元素set<KeyFrame*> spConnectedKeyFrames = pKF->GetConnectedKeyFrames();list<KeyFrame*> lKFsSharingWords;// Search all keyframes that share a word with current keyframes// Discard keyframes connected to the query keyframe{unique_lock<mutex> lock(mMutex);//遍歷pKF中所有生成的Bow向量for(DBoW2::BowVector::const_iterator vit=pKF->mBowVec.begin(), vend=pKF->mBowVec.end(); vit != vend; vit++){//在inverse indexes中查找該word都在哪些圖像中出現(xiàn)過(guò)list<KeyFrame*> &lKFs = mvInvertedFile[vit->first];//遍歷這些查找出來(lái)的與pKF有共視的word的關(guān)鍵幀for(list<KeyFrame*>::iterator lit=lKFs.begin(), lend= lKFs.end(); lit!=lend; lit++){//緊接著這一小段程序可以統(tǒng)計(jì)pKF與pKFi共視words的個(gè)數(shù)。//到了這里就是說(shuō)pKF與pKFi有共視關(guān)系,但是并不是pKFi都可以被認(rèn)為是閉環(huán)候選幀//只有當(dāng)pKFi不是在covisibility graph中與pKF直接相連的關(guān)鍵幀才有機(jī)會(huì)入圍。KeyFrame* pKFi=*lit;//如果pKFi是第一次被pKF查詢,那么先初始化成員變量mnLoopwords為0//經(jīng)判斷pKFi確實(shí)不與pKF直接相連則將成員變量mnLoopQuery設(shè)置為pKF的Id號(hào)碼//表示pKFi已經(jīng)被pKF查詢過(guò),下次再次查詢pKFi的時(shí)候//pKFi->mnLoopQuery = pKF->mnId 則直接讓 pKFi->mnLoopWords++;//并且將pKFi插入到lKFsSharingwords中去。if(pKFi->mnLoopQuery!=pKF->mnId){pKFi->mnLoopWords=0;if(!spConnectedKeyFrames.count(pKFi)){pKFi->mnLoopQuery=pKF->mnId;lKFsSharingWords.push_back(pKFi);}}pKFi->mnLoopWords++;}}}if(lKFsSharingWords.empty())return vector<KeyFrame*>();//IScoreAndMatch變量中與pKF有共視關(guān)系的關(guān)鍵幀以及兩者之間的得分//pair<float, KeyFrame>pair的使用是將兩者捆綁到一起存儲(chǔ)list<pair<float,KeyFrame*> > lScoreAndMatch;int maxCommonWords=0;//遍歷那些所有與pKF有共視關(guān)系又滿足條件的存儲(chǔ)在lKFsSharingWords中的關(guān)鍵幀for(list<KeyFrame*>::iterator lit=lKFsSharingWords.begin(), lend= lKFsSharingWords.end(); lit!=lend; lit++){//從上面的程序我們知道m(xù)nLoopWords變量中存儲(chǔ)了該關(guān)鍵幀與pKF的共視word數(shù)目//找到這些所有與pKF有共視關(guān)系的關(guān)鍵幀中與pKF共視word最大值 maxCommonWordsif((*lit)->mnLoopWords>maxCommonWords)maxCommonWords=(*lit)->mnLoopWords;}//但是我們?nèi)绻筮@么嚴(yán)格,那滿足我們條件的關(guān)鍵幀真的是寥寥無(wú)幾啦,所以為了得到多一些的//閉環(huán)候選幀我們不得不降低要求,讓前20%的關(guān)鍵幀都能進(jìn)入下一輪的比賽。//如果這個(gè)要求您都不能滿足的話,那對(duì)不起,您只能等下一次了。int minCommonWords = maxCommonWords*0.8f;int nscores=0;//再次遍歷lKFsSharingWords中存儲(chǔ)的所有與pKF有共視關(guān)系的關(guān)鍵幀for(list<KeyFrame*>::iterator lit=lKFsSharingWords.begin(), lend= lKFsSharingWords.end(); lit!=lend; lit++){//將每一個(gè)關(guān)鍵幀單獨(dú)拿出來(lái),看一看他的mnLoopWords與minCommonWords的大小KeyFrame* pKFi = *lit;if(pKFi->mnLoopWords>minCommonWords){nscores++;//對(duì)于那些共視單詞數(shù)滿足條件的pKFi計(jì)算與pKF之間的BoW得分float si = mpVoc->score(pKF->mBowVec,pKFi->mBowVec);//mLoopScore目前的值是pKFi與pKF之間的Bow得分。pKFi->mLoopScore = si;//只有那些得分大于minScore的pKFi才可以留下第三關(guān):Bow得分限制if(si>=minScore)lScoreAndMatch.push_back(make_pair(si,pKFi));}}if(lScoreAndMatch.empty())return vector<KeyFrame*>();list<pair<float,KeyFrame*> > lAccScoreAndMatch;float bestAccScore = minScore;// Lets now accumulate score by covisibility//遍歷所有上一貫留下的關(guān)鍵幀pKFifor(list<pair<float,KeyFrame*> >::iterator it=lScoreAndMatch.begin(), itend=lScoreAndMatch.end(); it!=itend; it++){//單獨(dú)拿出每一幀KeyFrame* pKFi = it->second;//查找在covisibility graph上與pKFi連接最密切的10個(gè)關(guān)鍵幀vector<KeyFrame*> vpNeighs = pKFi->GetBestCovisibilityKeyFrames(10);//bestScore初始化為pKFi與pKF之間的得分float bestScore = it->first;//這個(gè)累計(jì)得分accScore也被初始化為pKFi與pKF之間的得分float accScore = it->first;//而最佳幀選也初始化為pKFiKeyFrame* pBestKF = pKFi;//遍歷每一個(gè)pKFi的10個(gè)聯(lián)系最為密切的關(guān)鍵幀for(vector<KeyFrame*>::iterator vit=vpNeighs.begin(), vend=vpNeighs.end(); vit!=vend; vit++){KeyFrame* pKF2 = *vit;//如果在這10個(gè)關(guān)鍵幀中有之前被pKF查詢過(guò)(即有共視單詞),并且共視的單詞數(shù)還滿足//大于minCommonwords的要求if(pKF2->mnLoopQuery==pKF->mnId && pKF2->mnLoopWords>minCommonWords){//那么就要在原來(lái)pKFi與pKF得分的基礎(chǔ)上再加上pKFi的“好友”pKF2與pKF之間的得分accScore+=pKF2->mLoopScore;//殘忍的時(shí)刻到了,倘若pKF2與pKF之間的得分要比pKFi大,//pKF2就會(huì)超過(guò)pKFi pBestKF就成了pKF2了if(pKF2->mLoopScore>bestScore){pBestKF=pKF2;bestScore = pKF2->mLoopScore;}}}//現(xiàn)在存儲(chǔ)是從多個(gè)成員是11的小組內(nèi)選擇出的與pKF得分最高的pBestKF以及累計(jì)得分accScorelAccScoreAndMatch.push_back(make_pair(accScore,pBestKF));//并且在所有的accScore中找到那個(gè)最大的得分bestAccScore.if(accScore>bestAccScore)bestAccScore=accScore;}//但是為了能夠得到多一些的閉環(huán)候選幀,需要降低要求,將那些上一關(guān)留下來(lái)分?jǐn)?shù)靠前25%的關(guān)鍵幀//留下來(lái)float minScoreToRetain = 0.75f*bestAccScore;set<KeyFrame*> spAlreadyAddedKF;vector<KeyFrame*> vpLoopCandidates;vpLoopCandidates.reserve(lAccScoreAndMatch.size());//遍歷所有上一關(guān)留下的關(guān)鍵幀for(list<pair<float,KeyFrame*> >::iterator it=lAccScoreAndMatch.begin(), itend=lAccScoreAndMatch.end(); it!=itend; it++){//將那些上一關(guān)留下來(lái)分?jǐn)?shù)靠前25%的關(guān)鍵幀留下來(lái)if(it->first>minScoreToRetain){KeyFrame* pKFi = it->second;//如果檢測(cè)到set中已經(jīng)有pKFi了就不要重復(fù)插入了,其實(shí)這個(gè)判斷是多余的//set本來(lái)就具有值唯一性,不可以存入重復(fù)的值。if(!spAlreadyAddedKF.count(pKFi)){vpLoopCandidates.push_back(pKFi);spAlreadyAddedKF.insert(pKFi);}}}//最后終于得到了想要的關(guān)鍵幀,就想皇帝選妃子,需要層層選拔//可以走到這里的關(guān)鍵幀真的是過(guò)五關(guān)斬六將了//第一關(guān):與pKF有共視單詞的pKF1,且不能是與pKF在covisibility graph中與pKF直接相連的//關(guān)鍵幀//第二關(guān):共視單詞數(shù)必須大于minCommonWords的才可以留下 pKF2//第三關(guān):pKF2中與pKF的BOw得分必須大于minScore的才可以留下 pKF3//第四關(guān):pKF3要與自己最親密的“朋友”PK與pKF之間的共視單詞數(shù),留下的記為pKF4//第五關(guān):pKF4中那些與pKF得分大于minScoreToRetain的才可以最終留下來(lái) 記為pKF5;return vpLoopCandidates;
}
?
總結(jié)
以上是生活随笔為你收集整理的ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: win7便签点击删除按钮的时候不弹出提示
- 下一篇: 领域模型(domain model)贫血