VINS-Mono中的DBoW2关键代码注释
在阅读VINS-Mono源码时对DBoW2中代码顺手做的注释,怕以后会忘记,在这里记录一下,注释有不当之处,望各位大神看到后多多指点。理论参考高翔的《视觉SLAM十四讲》第12章的内容。这里找回环的方法是图像与数据库的比较,ORBSLAM中采用的方法是 图像与图像直接比较。
在pose_graph包里的pose_graph_node.cpp文件中,有这么一句代码,
posegraph.loadVocabulary(vocabulary_file);
这句代码包含的信息量巨大,其实现的功能就是将support_files文件夹下的brief_k10L6.bin文件构造为词袋模型的词典。这个词典的内容以树形结构存储,大意可以用下图表示,节点存储的权重和描述子是字典的核心内容。
转到pose_graph.cpp文件中,
void PoseGraph::loadVocabulary(std::string voc_path)
{
//构造词典,核心代码在这里
voc = new BriefVocabulary(voc_path);
//利用构造的词典,初始化图像数据库,它在计算图像相似度时发挥重要作用
db.setVocabulary(*voc, false, 0);
}
/// BRIEF Vocabulary
//BriefVocabulary类其实是这个类的另外一个名字
typedef DBoW2::TemplatedVocabulary<DBoW2::FBrief::TDescriptor, DBoW2::FBrief>
BriefVocabulary;
/// BRIEF Database
//BriefDatabase类其实是这个类的另外一个名字
typedef DBoW2::TemplatedDatabase<DBoW2::FBrief::TDescriptor, DBoW2::FBrief>
BriefDatabase;
上面的代码在DBoW文件夹下的DBoW2.h文件中,下面的代码在TemplatedVocabulary.h文件中,
template<class TDescriptor, class F>
TemplatedVocabulary<TDescriptor,F>::TemplatedVocabulary
(const std::string &filename): m_scoring_object(NULL)
{
//从brief_k10L6.bin文件中加载词典
loadBin(filename);
}
//节点m_nodes包括叶子m_words,即叶子一定是节点,节点不一定是叶子。叶子就是单词
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);//从文件流中得到voc,这里不懂具体怎么实现的
ifStream.close();
m_k = voc.k;//树形结构各节点的子节点数的最大值
m_L = voc.L;//树形结构的深度,即层数
m_scoring = (ScoringType)voc.scoringType;//评分的标准选哪一个
m_weighting = (WeightingType)voc.weightingType;//权重的标准选哪一个
createScoringObject(); //根据评分标准得到m_scoring_object
//节点数重置
m_nodes.resize(voc.nNodes + 1); // +1 to include root
m_nodes[0].id = 0;//根节点id
for(unsigned int i = 0; i < voc.nNodes; ++i)
{
NodeId nid = voc.nodes[i].nodeId;//节点id
NodeId pid = voc.nodes[i].parentId;//节点的父id
WordValue weight = voc.nodes[i].weight;//节点权重
//构造节点m_nodes
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