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


    0 前言

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

    1 下载DBoW3

    2 DBoW3使用

    2.1 头文件的使用

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

    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} )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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" );//保存字典压缩包
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.3.1.1 定义字典构造工具

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

    2.3.1.2 确定字典构造的输入

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

    2.3.1.3 输出字典的信息

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

    2.3.1.4 保存字典压缩包

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

    2.3.2 使用字典进行回环检测

    #include "DBoW3/DBoW3.h"//词袋支持头文件
    #include //opencv核心模块
    #include //gui模块
    #include //特征点头文件
    #include 
    #include 
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    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...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    2.3.2.1.1 判断字典库是否已加载数据
        if (vocab.empty()) 
        {
        }
    
    • 1
    • 2
    • 3

    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));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    2.3.2.4.1 定义词袋描述向量
    DBoW3::BowVector v1;
    DBoW3::BowVector v2;
    
    • 1
    • 2
    2.3.2.4.2 将描述子与字典匹配,计算词袋描述向量
    1. descriptors[i]表示图像i中所有的ORB描述子集合,函数transform()计算出词袋描述向量,每个向量中元素的值要么是0,表示图像i中没有这个单词;要么是该单词的权重
    2. BoW(p296)描述向量中含有每个单词的ID和权重,两者构成了整个稀疏的向量
    3. 当比较两个向量时,DBoW3会为我们计算一个分数
    vocab.transform(descriptors[i], v1);
    
    • 1
    2.3.2.4.3 计算一幅图像与另外一幅图像之间的相似度评分
    double score = vocab.score(v1, v2);//p296式(11.9)
    
    • 1

    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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2.3.2.5.1 定义数据字典库
    DBoW3::Database db(vocab, false, 0);
    
    • 1
    2.3.2.5.2 添加所要查询的图片的描述子
        for (int i = 0; i < descriptors.size(); i++)
            db.add(descriptors[i]);
    
    • 1
    • 2
    2.3.2.5.3 输出字典库的信息
    • 使用数据库查询时,DBoW对上面的分数进行排序,给出最相似的结果
        cout << "database info: " << db << endl;//输出database info(数据库信息)为
    
    • 1
    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;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    【2023最新版】Python全栈知识点总结
    impdp导出出现ORA-39155、ORA-48128、ORA-19505、ORA-27037错误
    【java计算机毕设】 留守儿童爱心捐赠管理系统 springboot vue html mysql 送文档ppt
    Vue.extend()实在是妙啊
    #AcWing--合并两个排序的链表
    解决尚医通com.aliyun.oss 和com.aliyun 爆红
    Javascript自定义页面复制事件
    【算法与数据结构】236、LeetCode二叉树的最近公共祖先
    position定位总结+元素选择器+window对象的子对象
    低功耗无线扫描唤醒技术,重塑物联网蓝牙新体验
  • 原文地址:https://blog.csdn.net/qq_45954434/article/details/126109594