学习DBow3源码(一)

学习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

未完待续。。。

参考资料:
https://mp.weixin.qq.com/s?__biz=MzI5MTM1MTQwMw==&mid=2247487947&idx=1&sn=a161d5ba005adabbfef23ee823c3f34b&chksm=ec10afcfdb6726d9460e3992357b93a50fb622a805c785a9322d7cafb6f8d7d0b02494206fbd&mpshare=1&scene=25&srcid=0120tujPrzQBRJvOMRlHZuAr&pass_ticket=DyCv5iDYNGzqu%2FG5eHjGG4I5gZSFV%2B4a6kb08nDUOcc%3D#wechat_redirect

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值