学习DBow3源码(一)
1 简介
本人小白,近期学习DBoW3源码做了一些可供参考的注释,如若有误,欢迎大家批评指正。
1.1 DBow3库的主要的类:
BowVector: 表示图像的单词向量(本质上就是map,代表一对一对的键值对)
Database: 图像数据库
DescManip: 操作特征描述子(计算均值、差分、IO例程)
Feature Vector: 局部特征的的向量
**QueryResults:**检索图像数据库
ScoringObject: 计算两个向量间的值
Vocabulary: 词典
quicklz: 快速数据压缩库
1.2 所有的数据结构:
Vocabulary
Database
BowVector
FeatureVector
QueryResults
2 源码解读
对BoWVextor.cpp源码进行详细注解
2.1 BoWVector.h
/**
* File: BowVector.h
* Date: March 2011
* Author: Dorian Galvez-Lopez
* Description: bag of words vector
* License: see the LICENSE.txt file
*
*/
#ifndef __D_T_BOW_VECTOR__
#define __D_T_BOW_VECTOR__
#include <map>
#include <vector>
#include "exports.h"
#if _WIN32
#include <cstdint>
#endif
namespace DBoW3 {
/// Id of words
typedef unsigned int WordId;
/// Value of a word
typedef double WordValue;
/// Id of nodes in the vocabulary tree
typedef unsigned int NodeId;
/// L-norms for normalization
enum LNorm
{
L1,
L2
};
/// Weighting type
enum WeightingType
{
TF_IDF,
TF,
IDF,
BINARY
};
/// Scoring type
enum ScoringType
{
L1_NORM,
L2_NORM,
CHI_SQUARE,
KL,
BHATTACHARYYA,
DOT_PRODUCT
};
/// Vector of words to represent images
class DBOW_API BowVector:
public std::map<WordId, WordValue>
{
public:
/**
* Constructor
*/
BowVector(void);
/**
* Destructor
*/
~BowVector(void);
/**
* Adds a value to a word value existing in the vector, or creates a new
* word with the given value
* @param id word id to look for
* @param v value to create the word with, or to add to existing word
*/
void addWeight(WordId id, WordValue v);
/**
* Adds a word with a value to the vector only if this does not exist yet
* @param id word id to look for
* @param v value to give to the word if this does not exist
*/
void addIfNotExist(WordId id, WordValue v);
/**
* L1-Normalizes the values in the vector
* @param norm_type norm used
*/
void normalize(LNorm norm_type);
/**
* Prints the content of the bow vector
* @param out stream
* @param v
*/
friend std::ostream& operator<<(std::ostream &out, const BowVector &v);
/**
* Saves the bow vector as a vector in a matlab file
* @param filename
* @param W number of words in the vocabulary
*/
void saveM(const std::string &filename, size_t W) const;
//returns a unique number from the configuration
uint64_t getSignature()const;
//serialization
void toStream(std::ostream &str)const;
void fromStream(std::istream &str);
};
} // namespace DBoW3
#endif
2.2 BoWVector.cpp
/**
* File: BowVector.cpp
* Date: March 2011
* Author: Dorian Galvez-Lopez
* Description: bag of words vector
* License: see the LICENSE.txt file
*
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#include "BowVector.h"
namespace DBoW3 {
// --------------------------------------------------------------------------
BowVector::BowVector(void)
{
}
// --------------------------------------------------------------------------
BowVector::~BowVector(void)
{
}
// --------------------------------------------------------------------------
void BowVector::addWeight(WordId id, WordValue v)//给已有word添加权重,或给空的值创建新word,word id对应的WordValue是idf
{
BowVector::iterator vit = this->lower_bound(id);//保证数据对象大于等于id的迭代器
if(vit != this->end() && !(this->key_comp()(id, vit->first)))//保证键id位于vit对应的键之前,并且迭代器不超尾
{
vit->second += v;//vit对应的值加上v
}
else
{
this->insert(vit, BowVector::value_type(id, v));//给空的值创建新的word
}
}
// --------------------------------------------------------------------------
void BowVector::addIfNotExist(WordId id, WordValue v)//添加一个新word到向量中
{
BowVector::iterator vit = this->lower_bound(id);
if(vit == this->end() || (this->key_comp()(id, vit->first)))
{
this->insert(vit, BowVector::value_type(id, v));//给空的值创建新的word
}
}
// --------------------------------------------------------------------------
void BowVector::normalize(LNorm norm_type)//归一化向量中的值
{
double norm = 0.0;
BowVector::iterator it;
if(norm_type == DBoW3::L1)//选择L1范数
{
for(it = begin(); it != end(); ++it)
norm += fabs(it->second);//取绝对值
}
else//L2范数
{
for(it = begin(); it != end(); ++it)
norm += it->second * it->second;
norm = sqrt(norm);//取平方根
}
if(norm > 0.0)
{
for(it = begin(); it != end(); ++it)
it->second /= norm;
}
}
// --------------------------------------------------------------------------
std::ostream& operator<< (std::ostream &out, const BowVector &v)//重载<<操作符
{
BowVector::const_iterator vit;
std::vector<unsigned int>::const_iterator iit;
unsigned int i = 0;
const size_t N = v.size();
for(vit = v.begin(); vit != v.end(); ++vit, ++i)//用来打印向量单词向量(键值对,即v的id和权重)
{
out << "<" << vit->first << ", " << vit->second << ">";
if(i < N-1) out << ", ";
}
return out;
}
// --------------------------------------------------------------------------
void BowVector::saveM(const std::string &filename, size_t W) const
{//保存词袋向量到matlab文件中
std::fstream f(filename.c_str(), std::ios::out);//让程序写入文件,c_str把string类型变量转换成char*变量
WordId last = 0;
BowVector::const_iterator bit;
for(bit = this->begin(); bit != this->end(); ++bit)
{
for(; last < bit->first; ++last)//把未被创建的id的权重置0
{
f << "0 ";
}
f << bit->second << " ";//打印已有id的权重
last = bit->first + 1;
}
for(; last < (WordId)W; ++last)//把未被创建的id的权重置0
f << "0 ";
f.close();
}
// --------------------------------------------------------------------------
void BowVector::toStream(std::ostream &str)const{//写入至屏幕操作
uint32_t s=size();
str.write((char*)&s,sizeof(s));
for(auto d:*this){
str.write((char*)&d.first,sizeof(d.first));
str.write((char*)&d.second,sizeof(d.second));
}
}
// --------------------------------------------------------------------------
void BowVector::fromStream(std::istream &str){//从屏幕读取操作
clear();
uint32_t s;
str.read((char*)&s,sizeof(s));
for(int i=0;i<s;i++){
WordId wid;
WordValue wv;
str.read((char*)&wid,sizeof(wid));
str.read((char*)&wv,sizeof(wv));
insert(std::make_pair(wid,wv));
}
}
uint64_t BowVector::getSignature()const{//返回配置的唯一数字
uint64_t sig=0;
for(auto ww:*this) sig+=ww.first+1e6*ww.second;
return sig;
}
// --------------------------------------------------------------------------
} // namespace DBoW3
未完待续。。。