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的文件见git@192.168.1.244:......./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];
}
}