【SLAM十四讲】ch11 回环检测 词袋法实验 得出相似分数后计算PR曲线 VPR实验 编辑中

【SLAM十四讲】ch11 回环检测 词袋法实验 得出相似分数后计算PR曲线

在这里插入图片描述

本文将从DBow3库的安装,再到高博十四讲的第ch11词袋法代码,最后再将词袋法的得分输入PR曲线代码来得到VPR(visual place recognition,视觉场景识别)实验结果。
————————————————————————————————————————————————
之前很长一段时间都是使用WORD来记录实验,今天心血来潮来试试一边做一边写在CSDN上。毕竟最近硬盘不好,不知道什么时候会不会掉盘。
目前手头上有的实验记录,如果兄弟们感兴趣可以在下边留言,我周末的时候抽空整理发在CSDN上(虽然感觉其他人的博客应该也已经有写了)
未整理的实验记录:
ORB3 v1.0 Ubuntu20.04 部署与测试(VMWare16.04版本,WSL2版本,Docker版本)。
Windwos11上的Docker Desktop部署Ubuntu20.04。
Windwos11上的WSL2部署。
Windows CARLA0.8.2,0.9.4部署与坑。

DBow3库安装

对于DBow3库,高博将其放置在了自己仓库的3rdparty中。
如果想要进行下载有以下几种方式

  1. 下载高博的库,然后使用git submodule下载子模块
git clone https://github.com/gaoxiang12/slambook2
cd slambook2
git submodule init
git submodule update --init --recursive

然后高博设置的Dow3库就会被吓着到3rdparty中,下载链接来记录于仓库内的.gitmodules中。
submodule要求网络对外部网络连接非常良好,下不动的可以把.gitmodules中的链接替换为git镜像站中的链接。

2.直接使用将.gitmomdules文件中记录的URL给clone下来

git clone https://github.com/rmsalinas/DBow3

下载好DBow3库之后,进行编译与安装,DBow3是一个常规的CMAKE工程,所以使用以下命令安装:

cd DBow3
mkdir build
cd build
cmake ..
make -j8
sudo make install

ch11编译

对于ch11的编译,需要对高博的部分代码进行修改。
在ch11/CMakeLists.txt中,高博将libDBoW3库设置为静态库libDBoW3.a,而当前版本的DBow3仓库默认安装之后给出的库文件是动态库.so
所以:

// 将第14行的
set( DBoW3_LIBS "/usr/local/lib/libDBoW3.a" )
// 修改为
set( DBoW3_LIBS "/usr/local/lib/libDBoW3.so" )

而后正常进行编译即可

# 在ch11目录中
mkdir build
cd build
cmake ..
make -j8

参考:https://blog.csdn.net/CSSDCC/article/details/123387255

ch11 词袋法代码运行

ch11中的代码有三个,feature_training.cpp loop_closure.cpp 以及 gen_vocab_large.cpp
feature_training.cpp
feature_training.cpp用于训练词袋法中的词典,训练图像越多效果越好,高博这里只使用了十张图像作为示例。

// feature_training.cpp
int main( int argc, char** argv ) {
    // read the image 
    cout<<"reading images... "<<endl;
    vector<Mat> images; 
    for ( int i=0; i<10; i++ )
    {
        string path = "./data/"+to_string(i+1)+".png";
        images.push_back( imread(path) );
    }
    // detect ORB features
    cout<<"detecting ORB features ... "<<endl;
    Ptr< Feature2D > detector = ORB::create();
    vector<Mat> descriptors;
    for ( Mat& image:images )
    {
        vector<KeyPoint> keypoints; 
        Mat descriptor;
        detector->detectAndCompute( image, Mat(), keypoints, descriptor );
        descriptors.push_back( descriptor );
    }
    
    // create vocabulary 
    cout<<"creating vocabulary ... "<<endl;
    DBoW3::Vocabulary vocab;
    vocab.create( descriptors );
    cout<<"vocabulary info: "<<vocab<<endl;
    vocab.save( "vocabulary.yml.gz" );
    cout<<"done"<<endl;
    
    return 0;
}

该程序输入为data目录下的所有图像。
输出为vocabulary.yml.gz字典文件
在这里插入图片描述
loop_closure.cpp用于计算图像间的相似度,最终给出图像两两间的相似度评分,横向对比机器学习就是给出个分类评分,有这个东西之后PR曲线就好画了。

// loop_closure.cpp
int main(int argc, char **argv) {
    // read the images and database  
    cout << "reading database" << endl;
    DBoW3::Vocabulary vocab("./vocabulary.yml.gz");
    // DBoW3::Vocabulary vocab("./vocab_larger.yml.gz");  // use large vocab if you want: 
    if (vocab.empty()) {
        cerr << "Vocabulary does not exist." << endl;
        return 1;
    }
    cout << "reading images... " << endl;
    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;
    Ptr<Feature2D> detector = ORB::create();
    vector<Mat> descriptors;
    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;
    for (int i = 0; i < images.size(); i++) {
        DBoW3::BowVector v1;
        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);
            cout << "image " << i << " vs image " << j << " : " << score << endl;
        }
        cout << endl;
    }

    // or with database 
    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;
    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;
}

输入词典文件vocabulary.yml.gz,待评分图像(这里设置为data下的所有图像),
最终输入待评分图像间的两两评分,或者是与数据库中图像的评分排行(前四(本质前3,因为有个是自己的)
在这里插入图片描述

在这里插入图片描述
gen_vocab_large.cpp这个程序用来训练更大的字典,整体结构等同于feature_training。

// gen_vocab_large.cpp
int main( int argc, char** argv )
{
    string dataset_dir = argv[1];
    ifstream fin ( dataset_dir+"/associate.txt" );
    if ( !fin )
    {
        cout<<"please generate the associate file called associate.txt!"<<endl;
        return 1;
    }

    vector<string> rgb_files, depth_files;
    vector<double> rgb_times, depth_times;
    while ( !fin.eof() )
    {
        string rgb_time, rgb_file, depth_time, depth_file;
        fin>>rgb_time>>rgb_file>>depth_time>>depth_file;
        rgb_times.push_back ( atof ( rgb_time.c_str() ) );
        depth_times.push_back ( atof ( depth_time.c_str() ) );
        rgb_files.push_back ( dataset_dir+"/"+rgb_file );
        depth_files.push_back ( dataset_dir+"/"+depth_file );

        if ( fin.good() == false )
            break;
    }
    fin.close();
    
    cout<<"generating features ... "<<endl;
    vector<Mat> descriptors;
    Ptr< Feature2D > detector = ORB::create();
    int index = 1;
    for ( string rgb_file:rgb_files )
    {
        Mat image = imread(rgb_file);
        vector<KeyPoint> keypoints; 
        Mat descriptor;
        detector->detectAndCompute( image, Mat(), keypoints, descriptor );
        descriptors.push_back( descriptor );
        cout<<"extracting features from image " << index++ <<endl;
    }
    cout<<"extract total "<<descriptors.size()*500<<" features."<<endl;
    
    // create vocabulary 
    cout<<"creating vocabulary, please wait ... "<<endl;
    DBoW3::Vocabulary vocab;
    vocab.create( descriptors );
    cout<<"vocabulary info: "<<vocab<<endl;
    vocab.save( "vocab_larger.yml.gz" );
    cout<<"done"<<endl;
    
    return 0;
}

PR曲线代码

# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve, auc

# 生成一些随机数据
y_true = np.random.randint(0, 2, size=100) # 真实的正负标签
y_score = np.random.rand(100) # 分类评分

# 手动导入数据
'''
y_true = np.array(
    [1,0,0,0,0,0,0,0,0,1],
)
y_score = np.array(
    [1,
    0.0305829,
    0.0221928,
    0.0308756,
    0.0231492,
    0.0240249,
    0.0240589,
    0.0246117,
    0.0287788,
    0.0542239
    ]
)
'''

# 计算PR曲线的坐标点
precision, recall, thresholds = precision_recall_curve(y_true, y_score)

# 计算PR曲线下的面积(AUC)
pr_auc = auc(recall, precision)

# 绘制PR曲线
plt.plot(recall, precision, label=f'PR Curve (AUC={pr_auc:.2f})')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend()
plt.show()

鸽了,待更新(23-6-10,9:45)

VPR实验方案

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值