VINS迴環檢測使用的是FAST(Features from Accelerated Segment Test)特徵點檢測,並利用BRIEF描述子存儲特徵。挑選了兩個實時性較好的檢測和描述。BRIEF提供了一種計算二值串的捷徑,而並不需要去計算一個類似於SIFT的特徵描述子。採用這樣的組合,是因爲基於處理器和內存的限制,爲保證實時性要求。
常見的字典庫主要有DBoW2 DBoW3 fBoW等。寫程序的過程中發現使用DBoW3庫時加載.bin文件不能初始化詞彙,如下編譯運行總是出現opencv錯誤。
DBoW3::Vocabulary voc("./brief_k10L6.bin");
這個詞彙文件應該來自dorian3d的DLoopDetector “./resources/brief_k10L6.voc.gz”.
生成詞彙.bin的文件見[email protected]:......./extracvoc.git
值得一提的是原本的DBoW2不支持讀取bin文件,而VINS-mono中的DBoW專爲Brief特徵寫了讀取.bin文件的加載函數。添加了頭文件
#include "../VocabularyBinary.hpp"
#include <boost/dynamic_bitset.hpp>
初始化函數改成了使用bin文件初始化
template<class TDescriptor, class F>
TemplatedVocabulary<TDescriptor,F>::TemplatedVocabulary
(const std::string &filename): m_scoring_object(NULL)
{
//m_scoring = KL;
// Changed by VINS [[[
//printf("loop start load bin\n");
loadBin(filename);
// Changed by VINS ]]]
}
loadBin定義如下
template<class TDescriptor, class F>
void TemplatedVocabulary<TDescriptor,F>::loadBin(const std::string &filename) {
m_words.clear();
m_nodes.clear();
//printf("loop load bin\n");
std::ifstream ifStream(filename);
VINSLoop::Vocabulary voc;
voc.deserialize(ifStream);
ifStream.close();
m_k = voc.k;
m_L = voc.L;
m_scoring = (ScoringType)voc.scoringType;
m_weighting = (WeightingType)voc.weightingType;
createScoringObject();
m_nodes.resize(voc.nNodes + 1); // +1 to include root
m_nodes[0].id = 0;
for(unsigned int i = 0; i < voc.nNodes; ++i)
{
NodeId nid = voc.nodes[i].nodeId;
NodeId pid = voc.nodes[i].parentId;
WordValue weight = voc.nodes[i].weight;
m_nodes[nid].id = nid;
m_nodes[nid].parent = pid;
m_nodes[nid].weight = weight;
m_nodes[pid].children.push_back(nid);
// Sorry to break template here
m_nodes[nid].descriptor = boost::dynamic_bitset<>(voc.nodes[i].descriptor, voc.nodes[i].descriptor + 4);
if (i < 5) {
std::string test;
boost::to_string(m_nodes[nid].descriptor, test);
//cout << "descriptor[" << i << "] = " << test << endl;
}
}
// words
m_words.resize(voc.nWords);
for(unsigned int i = 0; i < voc.nWords; ++i)
{
NodeId wid = (int)voc.words[i].wordId;
NodeId nid = (int)voc.words[i].nodeId;
m_nodes[nid].word_id = wid;
m_words[wid] = &m_nodes[nid];
}
}