视觉SLAM十四讲 读书编程笔记 Chapter12 回环检测

视觉SLAM十四讲:回环检测-知识点+代码 目录基于外观的几何关系1. 基础知识1.1 准确率和召回率1.2 词袋模型1.3 字典1.4 字典的数据结构1.5 相似度的计算1.6 相似度评分的处理1.7 检测回环后的验证2. 实践与代码解析2.1 创建字典 回环检测的关键是,如何有效地检测出相机经过同一个地方。如果能够成功地检测到这件事,就可以为后端的位姿图提供更多有效的数据,使之得到更好的估计,特别是得到一个全局一致的估计。我们可以利用回环检测进行重定位。 回环检测的方法: 暴力匹配。 对任意两幅图像都进行特征匹配,根据正确匹配的数量确定哪两幅图 阅读详情

词袋模型(BoW)

  1. 确定BoW的单词,从而组成字典。
  2. 确定一副图像中出现了哪些在字典中定义的概念,从而把一副图像转换成了一个向量的描述。
  3. 比较上一步中描述的相似程度。

字典

字典的结构

  • 字典生成问题类似于一个聚类问题,聚类问题常用K-means方法:根据K-means,我们可以把已经提取的大量特征点聚类成一个含有k个单词的字典。
  • 字典的存储结构:
    使用一种k叉树来表达字典,假设我们有N个特征点,希望构建一个深度为d,每次分叉为k的树,那么做法如下:
  1. 在根节点,用K-means把所有样本聚成k类,这样得到了第一层。
  2. 对第一层的每个节点,把属于该节点的样本再聚成N类,得到下一层。
  3. 以此类推,最后得到叶子层。叶子层即所谓的Words
  4. 经过上述步骤,构建了一个k分支,深度为d的树,可以容纳kd个单词,在查找某个特定的单词时,只需将它与每个中间节点的聚类中心比较(一共d次),即可找到最后的单词,保证了对数级别的查找效率。

在这里插入图片描述

实践:创建字典

  1. 安装BoW库,下载地址:https://github.com/rmsalinas/DBow3
    它是一个cmake工程,编译并且安装它。
  2. 完整代码:
    feature_training.cpp
//2019.08.18
#include "DBoW3/DBoW3.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <vector>
#include <string>

using namespace cv;
using namespace std;


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;//构造字典生成器对象,默认k=10,d=5,也可以程序员指定
	vocab.create(descriptors);
	cout<<"vocabulary info:"<<vocab<<endl;
	vocab.save("vocabulary.yml.gz");
	cout<<"done"<<endl;

	return 0;
}

CMakeLists.txt

cmake_minimum_required( VERSION 2.8 )
project( loop_closure )

set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

# opencv 
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )

# 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( feature_training feature_training.cpp )
target_link_libraries( feature_training ${OpenCV_LIBS} ${DBoW3_LIBS} )

运行结果:
在这里插入图片描述

相似度的计算

理论部分

我们希望对单词的区分性或重要性加以评估,给它们不同的权值以起到更好的效果。在文本检索中,常用的一种做法称为TF-IDF(Term Frequency-Inverse Document Frequency)。
TF部分的思想是,某单词在一副图像中经常出现,它的区分度就高。
IDF的思想是,某单词在字典中出现的频率越低,则分类图像时区分度就越高。

在词袋模型中,在建立字典时可以考虑IDF部分。我们统计某个叶子节点wi中的特征数量相对于所有特征数量的比例作为IDF部分。假设所有的特征数量为n,wi中的特征数量为ni,那么该单词的IDF为:IDFi=log(n/ni)
用来描述一个单词的特征点数量越少,说明这个单词越纯净,区分度也越好。

另一方面,TF部分则是指某个特征在单幅图像中出现的频率。假设图像A中单词wi出现了ni次,而一共出现的单词次数为n,那么TF为:TFi=ni/n
在一幅图像中,某个单词出现的次数相比于它在所有图像中出现的次数占比越大,那么这个单词区分度越高。

某一个单词的权重定义为TF与IDF之积:
etai = TFi×IDFi
考虑权重之后,对于某幅图像A,它的特征点可对应到许多个单词,组成它的Bag-of-Words:
A = {(w1,etai),(w2,etai),…,(wN,etaN)} = vA
由于相似的特征可能落到同一个类中,因此实际的**vA中会存在大量的零。这个向量vA**是一个稀疏的向量,它的非零部分指示了图像A中含有哪些单词,而这些部分的值为TF-IDF的值。

给定vA,vB,用L1范数计算它们的差异:

在这里插入图片描述

实践:相似度计算

loop_closure.cpp

//2019.08.18
#include "DBoW3/DBoW3.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <vector>
#include <string>

using namespace cv;
using namespace std;


int main(int argc,char **argv)
{
	//read the images and database
	cout << "reading database"<<endl;
	DBoW3::Vocabulary vocab("../vocabulary.yml.gz");
	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 leed to overfitting.
	//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;

	return 0;
}

CMakeLists.txt

cmake_minimum_required( VERSION 2.8 )
project( loop_closure )

set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

# opencv 
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )

# 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( loop_closure loop_closure.cpp )
target_link_libraries( loop_closure ${OpenCV_LIBS} ${DBoW3_LIBS} )

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相似性评分的处理

绝对相似性评分鲁棒性不是很好,我们取一个先验相似度s(vt,vt-deltat),它表示某时刻关键帧图像与上一时刻的关键帧的相似性。然后,其他的分值都根据这个值进行归一化:
在这里插入图片描述

如果当前帧与之前的某关键帧的相似度超过当前帧与上一个关键帧相似度的3倍,就认为可能存在回环。

关键帧的处理

如果关键帧选得太近,那么将导致两个关键帧之间的相似性过高,相比之下不容易检测出历史数据中的回环。比如,检测结果经常是第n帧和第n-2帧,第n-3帧最为相似,这种结果似乎太平凡了,意义不大。从实践来说,用于回环检测的帧最好是稀疏一些,彼此之间不太相同,又能涵盖整个环境。
另一方面,如果成功检测到了回环,比如说出现在第1帧和第n帧。那么很可能第n+1帧、第n+2帧都会和第1帧之间构成回环。但是,确认第1帧和第n帧之间存在回环对轨迹优化是有帮助的,而再接下去的第n+1帧、第n+2帧都会和第1帧构成回环产生的帮助就没那么大了。所以,我们会把"相近"的回环聚成一类,使算法不要反复地检测同一类的回环。

检测之后的验证

词袋的回环检测算法完全依赖于外观而没有利用任何的几何信息,这导致外观相似的图像容易被当成回环。并且由于词袋不在乎单词顺序,只在意单词有无的表达方式,更容易引发感知偏差。所以,在回环检测之后,我们通常还会有一个验证步骤。
验证的方法有很多。其一是设立回环的缓存机制,认为单次检测到的回环并不足以构成良好的约束,而在一段时间中一直检测到的回环,才认为是正确的回环。这可以看成时间一致性检测。
另一方法是在空间上的一致性检测,即对回环检测到的两个帧进行特征匹配,估计相机的运动。然后,再把运动放到之前的位姿图中,检查与之前的估计是否有很大的出入。总之,验证部分通常是必须的,但如何实现却是见仁见智的问题。

loop_closure_闭环检测_loopclosure_ 实现机器人运动的闭环检测,是为同时与建图增加约束条件,提高精度 立即下载

相关推荐

SMIC Memory配置与Library Compiler实战:从lib到db的高效转换

本文详细介绍了SMIC Memory Compiler的配置要点与使用Library Compiler将.lib文件高效转换为.db文件的完整流程。文章深入解析了关键配置参数对性能和面积的影响,并提供了从交互式操作到自动化脚本的实战指南,帮助数字芯片设计工程师顺利完成存储器模型的生成与集成,确保Design Compiler能正确调用。

weixin_28314575的博客 336

视觉SLAM--回环检测

回环检测的意义:可以使后端位姿图得到一个全局一致估计。

xiner0114的博客 812

2024最新Typora配置指南:从安装到打造学术写作环境(含LaTeX/参考文献解决方案)

本文提供2024年最新Typora配置指南,详细讲解如何从安装开始,结合Pandoc、Zotero和LaTeX,打造高效的学术写作环境。指南涵盖Typora深度定制、学术主题配置、参考文献自动管理以及一键生成出版级PDF的完整解决方案,旨在帮助科研人员和学生实现内容与格式分离,大幅提升论文写作效率。

weixin_29258297的博客 213

回环检测(SLAM十四讲ch12)

概述        无论在单目、双目还是RGBD中,追踪得到的位姿都是有误差的。随着路径的不断延伸,前面帧的误差会一直传递到后面去,导致最后一帧的位姿在世界坐标系里的误差有可能非常大。除了利用优化方法在局部和全局调整位姿,也可以利用回环检测(loop closure)来优化位姿。 问题的关键是:如何判断两帧图片的相似度。最直观的做法是:特征匹配,比较匹配的数量是否足够多。此时,可以采用词袋模型...

赤豆几维 2302

别光看教程了!手把手带你用STM32F103C8T6最小系统板点亮第一个LED(附完整电路图)

本文详细介绍了如何使用STM32F103C8T6最小系统板点亮第一个LED,从硬件连接到软件开发环境搭建,再到编写和下载程序,手把手教你完成STM32入门的第一步。适合初学者快速上手STM32开发,附完整电路图和代码示例。

weixin_28678831的博客 196

别再让PyCharm吃光你的C盘!保姆级教程:安全迁移config、plugins和remote sources到D盘

本文提供了一份详细的PyCharm配置与缓存文件迁移指南,帮助开发者将config、plugins和remote sources等占用大量C盘空间的文件安全转移到D盘。通过修改data.properties文件和正确迁移顺序,确保PyCharm功能不受影响,同时释放宝贵的系统盘空间。

weixin_28836989的博客 424

什么是SLAM中的回环检测,如果没有回环检测会怎样

最近看SLAM相关论文,产生一个疑问,闭环检测是SLAM算法中的一个关键环节,但是假如在主体机器人运动的轨迹当中没有产生闭环,是否闭环检测就失去了意义,也就是闭环检测这个环节是否就不是必须的环节。请教了身边做SLAM的同学的观点,告知没有产生闭环的时候需要用全局BA优化,不过因为计算量的问题,无法达到实时性,那么是否如果想要达到实时性,就必须要求机器人运动的轨迹的实验场景必须存在闭环呢? ...

Turn life into a dream, and then turn dreams into reality 1897

从原理到应用:深入解析双编码器在机器人关节力矩感知中的实现

本文深入解析了双编码器方案在机器人关节力矩感知中的实现原理与应用。该方案通过在电机侧和输出侧分别安装编码器,利用两者位置差异间接高精度计算外力,克服了传统电流环精度不足和扭矩传感器成本高昂的缺点。它为实现协作机器人的丝滑拖动示教、灵敏碰撞检测以及足式机器人的动态平衡与柔顺控制提供了关键技术支撑,是目前高性能机器人力控的主流选择。

t8u9v0w1x的博客 664

《视觉SLAM十四讲》-- 回环检测

前端提供特征点的提取和轨迹、地图的初值,后端负责数据的优化。但是如果像视觉里程计那样只考虑相邻时间上的关键帧,则会出现累积误差,无法构建全局一致的轨迹和地图。回环检测的关键是有效地检测出相机经过同一个地方这件事。

qq_44175983的博客 950

消费级显卡跑大模型:RTX 3060 12G 部署 70 亿参数 AI 编程助手的优化实战

本文详细介绍了如何在消费级显卡RTX 3060 12G上,通过量化、投机解码和分页KV-Cache等核心优化技术,成功部署并流畅运行70亿参数的CodeLlama-7B编程助手。文章提供了从环境配置、模型准备到参数调优的完整实战笔记,实测显存占用降至7.3GB,生成速度达21.7 token/秒,为开发者和技术爱好者提供了可行的本地AI部署方案。

weixin_29053067的博客 1262

1688店铺所有商品API接口(整店商品查询API接口)

1688店铺所有商品API接口、1688店铺列表API接口,1688店铺API接口,1688店铺查询商品API接口,1688店铺商品API接口,1688店铺详情接口,1688商品API接口

tbprice的博客 1570

《视觉SLAM十四讲 第二版》笔记及课后习题(第一讲)

前言 之所以想要写这个系列的博客,是因为想要总结一下高博的《SLAM视觉十四讲第二版》的各章内容以及自己对书后习题的一些做法,也算是对自己学习过程的一个总结和回顾。那么,正式开始! 第一讲、预备知识 SLAM 是Simultaneous Localization and Mapping 的缩写,中文译作“同时定位与地图构建”。它是指搭载特定传感器的主体,在没有环境先验信息的情况下,于运动过程中建...

weixin_43619346的博客 4459

以太网_RGMII接口与GMII接口的转化_03

RGMII接口转GMII接口!

weixin_42499230的博客 379

《视觉SLAM十四讲 第二版》笔记及课后习题(第二讲)

读书笔记: 这一讲算是全书的一个大纲,最关键的就是介绍了经典视觉SLAM框架。 小萝卜的例子 小萝卜要解决的问题分为两个: 要明白自身的状态 这就是location 要明白外在的环境 这就是mapping 对于视觉SLAM而言,熟悉各类相机的优缺点很有必要: SLAM问题的数学表述: 运动方程和观测方程: 经典视觉SLAM框架: 我们把整个视觉 SLAM 流程分为以下几步: 传感器...

weixin_43619346的博客 4037

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

《视觉SLAM十四讲 第二版》笔记及课后习题(第七讲)

读书笔记:视觉里程计1

weixin_43619346的博客 4539

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

《第12讲 回环检测》 读书笔记

本文是《视觉SLAM十四讲》第12讲的个人读书笔记,为防止后期记忆遗忘写的。 12.1 回环检测概述 12.1.1 回环检测的意义 VO 仅考虑相邻时间上的关联,使得整个 SLAM 会出现累积误差,无法构建全局一致的轨迹和地图。比方说前端给出的只是局部的位姿间约束,可能 是 x1 − x2, x2 − x3 等等。由于 x1 的估计存在误差,而 x2 是根据 x1 决定的,x3 又是由 x2...

LWHGMAN的博客 1635

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

《视觉SLAM十四讲 第二版》笔记及课后习题(第十一讲)

读书笔记:回环检测

weixin_43619346的博客 1855

《视觉SLAM十四讲 第二版》笔记及课后习题(第十二讲)

读书笔记:建图

weixin_43619346的博客 3109

【读书笔记】《视觉SLAM十四讲(高翔著)》 第12讲

文章目录12.3.2 实践:创建字典12.4.2 实践:相似度的计算12.5.1 增加字典规模 本博客的内容是本章程序编译运行方法,记录调通本章程序的过程、处理遇到报错的解决方法。 本章程序的详细解析可参考robinhjwy的优快云博客:https://blog.youkuaiyun.com/robinhjwy/article/details/78632978 12.3.2 实践:创建字典 本程序的功能:根...

dahailuoa6的博客 1150

视觉SLAM十四讲 读书编程笔记 Chapter 1&2

视觉SLAM十四讲 读书编程笔记 Chapter 1&21.有线性方程组Ax=b,若已知A,b,需要求解x,该如何求解?这对A和b有哪些要求?2.单目SLAM有哪些特性?3.双目相机有哪些特性?4.整体视觉SLAM流程图5.视觉SLAM流程图的一些理解6.SLAM问题的数学表达 1.有线性方程组Ax=b,若已知A,b,需要求解x,该如何求解?这对A和b有哪些要求? 答:x=A-1b,其中A...

wolfcsharp的博客 899

视觉SLAM十四讲(2):初识SLAM

这一讲主要介绍视觉SLAM的结构,并完成第一个SLAM程序:HelloSLAM。 目录 2.1 小萝卜的例子 单目相机 双目相机 深度相机 2.2 经典视觉SLAM框架 2.3 SLAM问题的数学表述 2.4 编程实践 Hello SLAM 使用cmake 使用库 【高翔】视觉SLAM十四讲 2.1 小萝卜的例子 这一节高翔博士首先介绍了自己组装的“小萝卜”机器人,小萝卜要想具有自主运动的能力,首先要知道自身的姿态,然后是了解外界的环境。这两类问题都需要使用传感器,视觉SL.

10点43的博客 3418

《视觉SLAM十四讲》学习笔记

双目相机:由已知i基线的双单目组成,通过基线(双单目间距)估计各像素空间位置,但配置与标定较为复杂,视差计算耗费资源,深度量程和精度受双目基线和分辨率限制。(1)g++ stoi.cpp -o stoi -std=c++11 使用标准c++11来编译程序, 将stoi.cpp 编译为名为stoi的可执行文件。SLAM问题其实就是状态估计问题,一致运动测量读数u和传感器读数z,求解定位问题和建图问题,对x和y进行估计。功能:主要有O1,O2,O3,Os,分别优化大小,功能,功能,大小。

qq_51164061的博客 557

《视觉slam十四讲》阅读笔记及课后习题详解——第一讲

前言 今天开始,开启这一系列博客,记录自己的学习过程。博客大致分为阅读笔记和课后习题。 更新计划: 2020.08.19——2020.08.31:更新第一、二、三、四讲 2020.09.01——2020.09.31:更新第五、六、七讲 2020.10.01——2020.10.31:更新第八、九、十、十一讲 2020.11.01——2020.11.31:更新第十二、十三、十四讲 读书笔记 1.1 主要内容 SLAM: SLAM,全称是Simultaneous Localization and Mapping,

qq_42910179的博客 480

《视觉SLAM十四讲》读书笔记--前八讲

一.初识SLAM 1.单目相机局限性:平移之后才能计算深度以及无法确定真实尺度。 双目相机测量原理:由两个单目相机构成,由两个相机之间的距离-基线估计每个像素的空间位置。基线距离越大测量的越远。 局限性:深度量程和精度受基线和分辨率限制,视差计算量大非常耗资源(主要问题),需GPU和FPGA加速才能实时输出 图像距离信息。 深度...

zhang__shuang_的博客 6560

【读书笔记】《视觉SLAM十四讲(高翔著)》 第7讲

文章目录7.1 特征点法 (P132)7.2 实践:特征提取和匹配 (P138) 7.1 特征点法 (P132) 视觉SLAM→前端(视觉里程计VO)→特征点法(主流)、直接法 →后端 【7.1.1 特征点】 特征点概念的引入:特征点——图像中比较有代表性的点。特征点应该在相机运动之后保持稳定。 目前知名的特征点:SIFT SURF ORB等,这些人工设计的特征点具备如下性质:可重复性,可区别性...

dahailuoa6的博客 785

视觉SLAM十四讲 读书编程笔记 Chapter7 视觉里程计1

Chapter7 视觉里程计1特征点法ORB特征特征匹配实践:特征提取与匹配2D-2D:对极几何对极约束的推导本质矩阵E的求解 特征点法 ORB特征 ORB(Oriented FAST and Rotated BRIEF)特征的关键点是"Oriented FAST",这是一种带有方向信息的FAST角点 ORB的描述子称为BRIEF(Binary Robust Independent Elemen...

wolfcsharp的博客 946
上一篇: 视觉SLAM十四讲 读书编程笔记 Chapter11 后端2
下一篇: 视觉SLAM十四讲 读书编程笔记 Chapter5 相机与图像
Leo-Ma
博客等级 码龄11年 1701粉丝 124原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值