视觉SLAM--回环检测

embedded/2024/10/18 6:01:12/

文章目录

  • 创建字典
  • 相似度计算
  • 增加字典规模

回环检测的意义:可以使 后端位姿图得到一个 全局一致估计。
视觉SLAM的主流做法: 基于外观的回环检测方法,仅 根据两幅图像的相似性确定回环检测关系。这种方法,摆脱了累计误差,使得回环检测模块可以称为SLAM系统中相对独立的模块。

创建字典

词袋,Bag-of-Words(BoW),目的是用"图像上有哪几种特征"来描述一幅图像。

ch11\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 featurescout<<"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;
}

相似度计算

ch11\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 featurescout << "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=4cout << "searching for image " << i << " returns " << ret << endl << endl;}cout << "done." << endl;
}

增加字典规模

ch11\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;
}

参考资料:
1、书籍:《视觉SLAM十四讲:从理论到实践(第2版)》
2、代码:https://github.com/gaoxiang12/slambook2


http://www.ppmy.cn/embedded/85650.html

相关文章

SAPUI5基础知识20 - 对话框和碎片(Dialogs and Fragments)

1. 背景 在 SAPUI5 中&#xff0c;Fragments 是一种轻量级的 UI 组件&#xff0c;类似于视图&#xff08;Views&#xff09;&#xff0c;但它们没有自己的控制器&#xff08;Controller&#xff09;。Fragments 通常用于定义可以在多个视图中重用的 UI 片段&#xff0c;从而提…

鸿蒙界面开发

界面开发 //构建 → 界面 build() {//行Row(){//列Column(){//文本 函数名(参数) 对象.方法名&#xff08;参数&#xff09; 枚举名.变量名Text(this.message).fontSize(40)//设置文本大小.fontWeight(FontWeight.Bold)//设置文本粗细.fontColor(#ff2152)//设置文本颜色}.widt…

VScode 修改 Markdown Preview Enhanced 字体以及大纲编号

修改字体和背景颜色 按快捷键 Ctrl , 打开设置&#xff0c;搜索 markdown-preview-enhanced.previewTheme&#xff0c;选择一个黑色主题的css&#xff0c;如 github-dark.css. 修改自动编号和背景颜色 背景颜色 按 F1 或者 Ctrl Shift P&#xff0c;输入 Customize CSS…

基于 HTML+ECharts 实现智慧销售数据可视化大屏(含源码)

智慧销售数据可视化大屏&#xff1a;基于 HTML 和 ECharts 的实现 在当今的商业环境中&#xff0c;销售数据的实时监控和分析对于企业的成功至关重要。通过数据可视化&#xff0c;销售团队可以更直观地理解销售趋势、客户行为和产品表现。本文将介绍如何利用 HTML 和 ECharts 实…

20240723opencv中的透视变换

文章目录 1.实验环境2.实验目的3.实验代码4.实验结果展示5.本实验拓展1.实验环境 pycharm + opencv3.4.1 2.实验目的 针对图像中斜视现象,我们采用透视变换法进行矫正,代码如下,有更好的方法欢迎各位大佬评论区留言。 3.实验代码 # @File: 14.5透视变换.py # @Author: …

【漏洞复现】APP分发签名系统index-uplog.php存在任意文件上传漏洞

漏洞描述 APP分发签名系统index-uplog.php存在任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵…

利用crypto.subtle.generateKey()写公钥和私钥,并用exportKey将公私钥导出

crypto.subtle.generateKey 需要在支持 Web Crypto API 的环境中运行&#xff0c;比如现代浏览器&#xff0c;或在nodejs环境当中 密钥生成和导出操作是异步的&#xff0c;因此需要使用 async/await 或者 .then() 和 .catch() 来处理。 generateKey 函数的第三个参数是一个数组…

免费神器!国产AI绘画工具,速来体验!

今天介绍一个最近发现的免费绘画平台&#xff0c;支持训练模型&#xff0c;和libilibi有点像&#xff0c;目前网站功能都是免费的。 可以选择各种风格类型&#xff0c;看到好看的图也可以直接做同款。 页面相对简洁&#xff0c;图片比例支持自定义&#xff0c;最高一次可以出8张…