【DBoW3】【DBoW3实践】【DBoW3的使用学习记录】

0 前言

  • DoW库的使用主要是用来训练字典

1 下载DBoW3

2 DBoW3使用

2.1 头文件的使用

#include "DBoW3/DBoW3.h"//词袋支持头文件

2.2 CmakeLists.txt的使用

# dbow3
# dbow3 is a simple lib so I assume you installed it in default directory
set( DBoW3_INCLUDE_DIRS "/usr/local/include" )
set( DBoW3_LIBS "/usr/local/lib/libDBoW3.a" )

add_executable( xxx src/xxx.cpp )
target_link_libraries( xxx  ${
    
    DBoW3_LIBS} )

2.3 代码的使用

2.3.1 使用描述子提取并创建字典

  1. 参数descriptors:格式vector,是从图片中提取出的描述子
  2. 描述子的使用参考,【Opencv】【OpenCV实践】【OpenCV的使用学习记录】
  3. 该代码片段参考:【slam十四讲第二版】【课本例题代码向】【第十一讲~回环检测】【DBoW3的安装】【创建字典】【相似度检测】【增加字典规模】的2 创建字典
    // create vocabulary (创建字典)
    DBoW3::Vocabulary vocab;//默认构造函数 k=10,d=5
    
    vocab.create( descriptors );
    
    cout<<"vocabulary info: "<<vocab<<endl;//字典信息
    
    vocab.save( "vocabulary.yml.gz" );//保存字典压缩包

2.3.1.1 定义字典构造工具

    DBoW3::Vocabulary vocab;//默认构造函数 k=10,d=5
  • 这里使用了默认构造函数,也就是k=10,d=5。这是一个小规模字典,最大可以容纳100000个单词

2.3.1.2 确定字典构造的输入

  • 注意参数descriptors:格式vector,是从图片中提取出的描述子
    vocab.create( descriptors );

2.3.1.3 输出字典的信息

    cout<<"vocabulary info: "<<vocab<<endl;//字典信息
  • 输出格式类似于:
vocabulary info: Vocabulary: k = 10, L = 5, Weighting = tf-idf, Scoring = L1-norm, Number of words = 4970
  • 意思是:分支数量k为10,深度L为5,单词数量为4970,没有达到最大容量,Weighting是权重,Scoring是评分。

2.3.1.4 保存字典压缩包

  • 当然,使用也是以压缩包的形式
    vocab.save( "vocabulary.yml.gz" );//保存字典压缩包

2.3.2 使用字典进行回环检测

#include "DBoW3/DBoW3.h"//词袋支持头文件
#include <opencv2/core/core.hpp>//opencv核心模块
#include <opencv2/highgui/highgui.hpp>//gui模块
#include <opencv2/features2d/features2d.hpp>//特征点头文件
#include <iostream>
#include <vector>
#include <string>

using namespace cv;
using namespace std;

/***************************************************
 * 本节演示了如何根据前面训练的字典计算相似性评分
 * ************************************************/
int main(int argc, char **argv) {
    
    
    if (argc != 2) {
    
    
        cout << "Usage: 需要字典" << endl;
        return 1;
    }
    string zidian_file = argv[1];
    DBoW3::Vocabulary vocab(zidian_file);

    // read the images and database(读取图像和数据库)
    cout << "reading database" << endl;//输出reading database(读取数据)
    //DBoW3::Vocabulary vocab("../src/vocabulary.yml.gz");//vocabulary.yml.gz路径
    //DBoW3::Vocabulary vocab("../src/vocab_larger.yml.gz");  // use large vocab if you want:
    if (vocab.empty()) {
    
    
        cerr << "Vocabulary does not exist." << endl;//输出Vocabulary does not exist
        return 1;
    }
    cout << "reading images... " << endl;//输出reading images...
    vector<Mat> images;
    for (int i = 0; i < 10; i++) {
    
    
        string path = "../data/" + to_string(i + 1) + ".png";//图像读取路径
        images.push_back(imread(path));
    }

    // NOTE: in this case we are comparing images with a vocabulary generated by themselves, this may lead to overfit.
    // 这里我们用它们生成的字典比较它们本身的相似性,这可能会产生过拟合
    // detect ORB features
    cout << "detecting ORB features ... " << endl;//输出detecting ORB features ...(正在检测ORB特征)
    Ptr<Feature2D> detector = ORB::create();//默认图像500个特征点
    vector<Mat> descriptors;//描述子  将10张图像提取ORB特征并存放在vector容器里
    for (Mat &image:images) {
    
    
        vector<KeyPoint> keypoints;//关键点
        Mat descriptor;//描述子
        detector->detectAndCompute(image, Mat(), keypoints, descriptor);//检测和计算
        descriptors.push_back(descriptor);
    }

    // we can compare the images directly or we can compare one image to a database
    // images :
    cout << "comparing images with images " << endl;//输出comparing images with images
    for (int i = 0; i < images.size(); i++)
    {
    
    
        DBoW3::BowVector v1;
        //descriptors[i]表示图像i中所有的ORB描述子集合,函数transform()计算出用先前字典来描述的单词向量,每个向量中元素的值要么是0,表示图像i中没有这个单词;要么是该单词的权重
        //BoW描述向量中含有每个单词的ID和权重,两者构成了整个稀疏的向量
        //当比较两个向量时,DBoW3会为我们计算一个分数
        vocab.transform(descriptors[i], v1);
        for (int j = i; j < images.size(); j++)
        {
    
    
            DBoW3::BowVector v2;
            vocab.transform(descriptors[j], v2);
            double score = vocab.score(v1, v2);//p296式(11.9)
            cout << "image " << i << " vs image " << j << " : " << score << endl;//输出一幅图像与另外一幅图像之间的相似度评分
        }
        cout << endl;
    }

    // or with database
    //在进行数据库查询时,DBoW对上面的分数进行排序,给出最相似的结果
    cout << "comparing images with database " << endl;
    DBoW3::Database db(vocab, false, 0);
    for (int i = 0; i < descriptors.size(); i++)
        db.add(descriptors[i]);
    cout << "database info: " << db << endl;//输出database info(数据库信息)为
    for (int i = 0; i < descriptors.size(); i++)
    {
    
    
        DBoW3::QueryResults ret;
        db.query(descriptors[i], ret, 4);      // max result=4
        cout << "searching for image " << i << " returns " << ret << endl << endl;
    }
    cout << "done." << endl;
}

2.3.2.1 读取已有字典数据构建字典库

    if (argc != 2) {
    
    
        cout << "Usage: 需要字典" << endl;
        return 1;
    }
    string zidian_file = argv[1];
    DBoW3::Vocabulary vocab(zidian_file);

    // read the images and database(读取图像和数据库)
    cout << "reading database" << endl;//输出reading database(读取数据)
    //DBoW3::Vocabulary vocab("../src/vocabulary.yml.gz");//vocabulary.yml.gz路径
    //DBoW3::Vocabulary vocab("../src/vocab_larger.yml.gz");  // use large vocab if you want:
    if (vocab.empty()) {
    
    
        cerr << "Vocabulary does not exist." << endl;//输出Vocabulary does not exist
        return 1;
    }
    cout << "reading images... " << endl;//输出reading images...
2.3.2.1.1 判断字典库是否已加载数据
    if (vocab.empty()) 
    {
    
    
    }

2.3.2.2 读取要进行回环检测的采集数据

    cout << "reading images... " << endl;//输出reading images...
    vector<Mat> images;
    for (int i = 0; i < 10; i++) {
    
    
        string path = "../data/" + to_string(i + 1) + ".png";//图像读取路径
        images.push_back(imread(path));
    }

2.3.2.3 提取每张图片的ORB特征点并计算描述子

    // NOTE: in this case we are comparing images with a vocabulary generated by themselves, this may lead to overfit.
    // 这里我们用它们生成的字典比较它们本身的相似性,这可能会产生过拟合
    // detect ORB features
    cout << "detecting ORB features ... " << endl;//输出detecting ORB features ...(正在检测ORB特征)
    Ptr<Feature2D> detector = ORB::create();//默认图像500个特征点
    vector<Mat> descriptors;//描述子  将10张图像提取ORB特征并存放在vector容器里
    for (Mat &image:images) {
    
    
        vector<KeyPoint> keypoints;//关键点
        Mat descriptor;//描述子
        detector->detectAndCompute(image, Mat(), keypoints, descriptor);//检测和计算
        descriptors.push_back(descriptor);
    }

2.3.2.4 图像之间的直接比较

    // we can compare the images directly or we can compare one image to a database
    // images :
    cout << "comparing images with images " << endl;//输出comparing images with images
    for (int i = 0; i < images.size(); i++)
    {
    
    
        DBoW3::BowVector v1;
        //descriptors[i]表示图像i中所有的ORB描述子集合,函数transform()计算出用先前字典来描述的单词向量,每个向量中元素的值要么是0,表示图像i中没有这个单词;要么是该单词的权重
        //BoW描述向量中含有每个单词的ID和权重,两者构成了整个稀疏的向量
        //当比较两个向量时,DBoW3会为我们计算一个分数
        vocab.transform(descriptors[i], v1);
        for (int j = i; j < images.size(); j++)
        {
    
    
            DBoW3::BowVector v2;
            vocab.transform(descriptors[j], v2);
            double score = vocab.score(v1, v2);//p296式(11.9)
            cout << "image " << i << " vs image " << j << " : " << score << endl;//输出一幅图像与另外一幅图像之间的相似度评分
        }
        cout << endl;
    }
2.3.2.4.1 定义词袋描述向量
DBoW3::BowVector v1;
DBoW3::BowVector v2;
2.3.2.4.2 将描述子与字典匹配,计算词袋描述向量
  1. descriptors[i]表示图像i中所有的ORB描述子集合,函数transform()计算出词袋描述向量,每个向量中元素的值要么是0,表示图像i中没有这个单词;要么是该单词的权重
  2. BoW(p296)描述向量中含有每个单词的ID和权重,两者构成了整个稀疏的向量
  3. 当比较两个向量时,DBoW3会为我们计算一个分数
vocab.transform(descriptors[i], v1);
2.3.2.4.3 计算一幅图像与另外一幅图像之间的相似度评分
double score = vocab.score(v1, v2);//p296式(11.9)

2.3.2.5 图像与数据库之间的比较

    // or with database
    //在进行数据库查询时,DBoW对上面的分数进行排序,给出最相似的结果
    cout << "comparing images with database " << endl;
    DBoW3::Database db(vocab, false, 0);
    for (int i = 0; i < descriptors.size(); i++)
        db.add(descriptors[i]);
    cout << "database info: " << db << endl;//输出database info(数据库信息)为
    for (int i = 0; i < descriptors.size(); i++)
    {
    
    
        DBoW3::QueryResults ret;
        db.query(descriptors[i], ret, 4);      // max result=4
        cout << "searching for image " << i << " returns " << ret << endl << endl;
    }
2.3.2.5.1 定义数据字典库
DBoW3::Database db(vocab, false, 0);
2.3.2.5.2 添加所要查询的图片的描述子
    for (int i = 0; i < descriptors.size(); i++)
        db.add(descriptors[i]);
2.3.2.5.3 输出字典库的信息
  • 使用数据库查询时,DBoW对上面的分数进行排序,给出最相似的结果
    cout << "database info: " << db << endl;//输出database info(数据库信息)为
2.3.2.5.4 定义并输出查询结果
    for (int i = 0; i < descriptors.size(); i++)
    {
    
    
        DBoW3::QueryResults ret;
        db.query(descriptors[i], ret, 4);      // max result=4
        cout << "searching for image " << i << " returns " << ret << endl << endl;
    }

猜你喜欢

转载自blog.csdn.net/qq_45954434/article/details/126109594