SLAM学习——回环检测
1.回环检测
回环检测的关键,就是如何有效的检测出相机经过同一个地方这件事。它关系到我们估计的轨迹和地图在长时间下的正确性。
由于回环检测提供了当前数据与所有历史数据的关联,在跟踪算法丢失后,我们还可以利用重定位。有些时候,我们把仅有前端和局部后端的系统称为VO,把带有回环检测和全局后端的系统称为SLAM。
回环检测的方法:基于里程计的几何关系和基于外观。
基于几何关系是说,当我们发现当前相机运动到了之前的某个位置时,检测它们有没有回环关系。但是由于误差积累的存在,我们往往没办法正确发现“运动到了之前的某个位置附近”这个事实。
基于外观的(主流做法),它和前端、后端的估计都无关,仅根据俩副图像的相似性确定回环检测关系,这种做法摆脱了积累误差,使回环检测模块成为SLAM一个相对独立的模块。
在基于外观回环检测算法中,核心问题是如何计算图像间的相似性。比如对于图像A和图像B,我们要计算它们之间的相似性评分:s(A,B)。如果单单用俩副图像相减然后取范数 s(A,B)=||A−B|| s ( A , B ) = | | A − B | | s(A,B)=||A-B||。但是由于一副图像在不同角度或者不同光线下其结果会相差很多,所以不使用这个函数。
程序判断与实际总有误差,以下是我们的分类结果:
其中假阳性又称为感知偏差,假阴性称为感知变异。为方便,则真阳性(True Positive)简称TP,假阳性称为(False Positive)简称FP,以此类推。当然,所有的结果我们都希望FP和FN尽可能要低。对于某特定算法,我们可以统计它在某个数据集上的TP、FP、FP、FN的出现次数,并统计俩个统计量:准确率Presicion=TP/(TP+FP)和召回率Recall=TP/(TP+FN)。
从上述公式可以得到,准确率描述的是,算法提取的所有回环中确实是真实回环的概率。而召回率是说在所有真实回环中被正确检测出来的概率。一般而言,我们更倾向于提高算法的准确性,稍微牺牲下召回率。如果出现假阳性,那么就会在后端的Pose graph添加错误的边,导致误差不准。
2.词袋模型
1.确定概念,例如一副图像上有人、狗等,那么“人”“狗” 等概念就是Bag-of-Words中的“单词”,许多单词放在一起,组成了“字典”。
2.确定一副图像中出现了哪些在字典中定义的概念——用单词出现的情况(直方图)描述整副图像,转换成向量。
3.比较上一步中的描述的相似程度。
举个例子,若“人”“狗”都在字典里(这里的字典是已经知道的),不防设为 w1,w2 w 1 , w 2 w_{1}, w_{2},假设A图像中有人没狗,则可以描述成: A=1∗w1+0∗w2 A = 1 ∗ w 1 + 0 ∗ w 2 A=1*w_{1}+0*w_{2},由于字典是固定的,那么只需要一个向量就可以描述整副图像了,例如 A=[1,0]T A = [ 1 , 0 ] T A=\begin{bmatrix} 1,0 \end{bmatrix}^{T}
通过这个词袋模型,我们可以得到俩张图片在这个词袋里面的向量 a,b∈Rw a , b ∈ R w a,b\in R^{w},那么可以计算 s(a,b)=1−1W||a−b||1 s ( a , b ) = 1 − 1 W | | a − b | | 1 s(a,b)=1-\frac{1}{W}||a-b||_{1},如果俩个向量相等,那么我们得到1,完全相反(即a为0的地方b为1)则得到0。
3.字典
假设我们对所有的图片进行特征点的提取,比如有N个。我们现在可以寻找一个有个单词的字典,每个单词可以看作相邻特征点的集合,可以用K-means均值来做:
1.随机选取k个中心点: c1,⋯cn c 1 , ⋯ c n c_{1},\cdots c_{n}。
2.对每一个样本,计算它与每个中心点之间的距离,取最小的作为它的归类。
3.重新计算每个类的中心点。
4.如果每个中心点变化很小,那么退出,算法收敛;否则返回第二步。
K-means存在小问题,就是:需要指定聚类数量,随机选取中心点等。
为了解决这个问题,我们使用一种K叉树来表达字典。假定我们构建一个深度为d、每次分叉为k的树,那么做法如下:
1.在根节点上,用K-means把所有样本聚成k类(有时候为保证聚类均匀性会使用k-means++),这样得到了第一层。
2.对于第一层的每个节点,把属于该节点的样本再聚类k类,得到下一层。
3.以此类推,最后得到叶子层。叶子层即所谓的Words。
一方面,这样一个k分支,深度为d的树,可以容纳 kd k d k^{d} 个单词。另一方面,在查找某个特征对应的单词时,只需要将它与每个中间节点的聚类中心比较(一共d次),即可找到最后的单词。
紧接着我们创建字典,直接上代码:(高博用的是opencv3,我用的是opencv2,略有不同)
#include "DBoW3/DBoW3.h" //使用了BOW这个库
#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 imagecout<<"reading images... "<<endl;vector<Mat> images;for ( int i=0; i<10; i++ )//这里选取了10张图片{string path = "/home/hansry/Slam_Book/src/Feature_traning/data/"+to_string(i+1)+".png";images.push_back( imread(path) );}// detect ORB featurescout<<"detecting ORB features ... "<<endl;Ptr< Feature2D > detector = ORB::create("FAST");//由于这里用的是opencv2,所以略有不同vector<Mat> descriptors; for ( Mat& image:images ){vector<KeyPoint> keypoints;Mat descriptor;ORB orb;orb( image, Mat(), keypoints, descriptor );descriptors.push_back( descriptor );}// create vocabularycout<<"creating vocabulary ... "<<endl;DBoW3::Vocabulary vocab;vocab.create( descriptors );cout<<"vocabulary info: "<<vocab<<endl;vocab.save( "vocabulary.yml.gz" );cout<<"done"<<endl;return 0;
}
Cmakelist如下:
cmake_minimum_required(VERSION 2.8.3)
project(Feature_traning)set(CMAKE_CXX_FLAGS "-std=c++11 -O3")
find_package(OpenCV REQUIRED )
set( DBoW3_INCLUDE_DIRS "/usr/local/include" )
set( DBoW3_LIBS "/usr/local/lib/libDBoW3.so" )
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES test
# CATKIN_DEPENDS opencv roscpp
# DEPENDS system_lib
)include_directories(include)
include_directories(${catkin_INCLUDE_DIRS}${OpenCV_INCLUDE_DIRS}
)
add_executable(Feature_traning src/Feature_traning.cpp)target_link_libraries(Feature_traning${catkin_LIBRARIES}${OpenCV_LIBRARIES}${DBoW3_LIBS}
)
结果如下图所示:
我们这里使用的是默认构造函数,所以默认分支数量为10,深度L为5,单词数量为4983,没有达到最大容量。weighting是权重,scoring是评分。
4.相似度计算
在上一part中,我们创建了字典,那么有了字典以后,给定任意特征点 fi f i f_{i},只要在字典树中逐层查找,最后都能找到与之对应的单词 wj w j w_{j},如果字典足够大,我们可以说这俩个来自同一类物体。
假设一副图像提取N个特征,找到这N个特征对应的单词之后,就相当于有了该图像在单词列表中的分布,相当于“这幅图里有一个人和一辆汽车”等。但是有的时候,我们会希望对单词的区分性或重要性加以评估,会给单词加权重。
这里,我们提供一种方法叫TF-IDE,TF的思想是:某单词在一副图像中经常出现,它的区分度就越高。另一方面,IDE的思想是,某单词在字典中出现的频率越低,则分类图像时的区分度越高。
对于IDF部分,假设所有特征数量为n,某个叶子节点的 wi w i w_{i}所含的数量特征为 ni n i n_{i},那么该单词的IDF为:
IDFi=lognni I D F i = l o g n n i IDF_{i}=log\frac{n}{n_{i}}
TF是指某个特征在单副图像中出现的频率。假设图像A中单词 wi w i w_{i}出现了 ni n i n_{i} 次,而一共出现的单词次数是n,那么TF为:
TFi=nin T F i = n i n TF_{i}=\frac{n_{i}}{n}
于是 wi w i w_{i}的权重等于TF乘IDF之积,即 ηi=TFi×IDFi η i = T F i × I D F i \eta_{i}=TF_{i}\times IDF_{i}
考虑权重以后,对于某副图像,我们就可以得到许多个单词,得到BOW:
(A是一幅图像) A={(w1,η1),(w2,η2),⋯,(wn,ηn)}=ΔvA A = { ( w 1 , η 1 ) , ( w 2 , η 2 ) , ⋯ , ( w n , η n ) } = Δ v A A=\begin{Bmatrix} (w_{1},\eta _{1}),(w_{2},\eta _{2}),\cdots ,(w_{n},\eta _{n}) \end{Bmatrix}\overset{\Delta }{= }v_{A}(是一个向量,非零部分表示含有哪些单词)
如何计算俩副图像相似度,这里使用了 L1 L 1 L_{1}范数形式:
s(vA−vB)=2∑Ni=1|vAi|+|vBi|−|vAi−vBi| s ( v A − v B ) = 2 ∑ i = 1 N | v A i | + | v B i | − | v A i − v B i | s(v_{A}-v_{B})=2\sum_{i=1}^{N}|v_{Ai}|+|v_{Bi}|-|v_{Ai}-v_{Bi}|
SLAM学习——回环检测相关推荐
- 最全综述 | SLAM中回环检测方法 收藏
在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿解算当前帧位姿,因此其中的误差便这样一帧一帧的传递下去,也就是我们所说的累积误差.一个消除误差有效的办法是进行回环检测.回环检测判断 ...
- 3D激光SLAM的回环检测方法
一.Scan-to-Scan 1.格地图或者说是概率占据栅格地图初步 在Matlab中创建一个1000*1000大小的二维数组,如果数组中每个元素取值为0到255的整数(灰度图),再把这个数组用Mat ...
- 开源!用于3D激光雷达SLAM回环检测的实时词袋模型BoW3D
点击进入->3D视觉工坊学习交流群 0. 笔者个人体会 回环检测对于SLAM系统的全局一致性有着至关重要的影响.现有的视觉SLAM回环检测大多是基于词袋模型,也就是2012年推出的BoW2库和2 ...
- 视觉SLAM十四讲学习笔记——ch11回环检测
文章目录 11.1 理论部分 11.2 实践部分 11.2.1 创建字典 11.2.2 利用已经创建的vocabulary.yml.gz字典,得到图片与图片之间相似性的评分 11.2.3 利用规模更大 ...
- 详解 | SLAM回环检测问题
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文经知乎作者fishmarch授权转载,二次转载请联系作者 原文 ...
- 综述 | SLAM回环检测方法
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨任旭倩 来源丨计算机视觉life 在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一 ...
- 视觉SLAM回环检测、词袋模型和视觉位置识别--论文记录和实验简析
一.传统方法部分(词袋模型,bag of words,BoW) 1. 预先在环境中采集足够多的图像或者所有位置的图像(成千上万张图片)之后构建视觉词汇表 参考论文:2012年的TRO顶刊 Gálvez ...
- 视觉slam十四讲 pdf_视觉SLAM十四讲|第12讲 回环检测
1. 什么是回环检测 前面有说过累积误差的问题,前一时刻的误差会积累到后面,导致画不成圈圈,如图12-1所示,而画圈圈(全局一致性)很重要,所以需要有一个步骤来纠正当前的计算偏差. 回环检测通过判断相 ...
- 视觉SLAM⑪----回环检测
目录 11.0 本章目标 11.1 概述 11.1.1 回环检测的意义 11.1.2 回环检测的方法 11.1.3 准确率和召回率 11.2 词袋模型 11.3 字典 11.3.1 字典的结构 11. ...
最新文章
- Fib(兔子问题)python实现多种方法
- 最新Transformer模型大盘点,NLP学习必备,Google AI研究员出品丨资源
- 关于html5的使用简单总结
- JavaScript快速上手入门
- SAP GUI security setting on local file access
- codeforce Gym 100500F 	Door Lock (二分)
- java学习(177):获取应用程序的路径
- python士兵突击_想自学Python进入该行业成为一名自己一直以来就很羡慕和钦佩的程序员,过来人的你有什么想分享的吗?...
- Java类的加载过程,类加载器,双亲委派原则
- 观察者模式(浅谈监听器工作原理)
- linux系统 安装mysql,在linux系统中安装MySQL
- jvm gc监控分析常用命令
- windows笔记-【内核对象线程同步】概述
- HTML,CSS基础十大重点问题
- 密码学原理与实践_浅谈SSH2工作原理
- C语言自己写代码实现的strcmp函数
- goeasy小demo
- 002--YAML工具
- js复制一个数组(浅复制、深复制)
- [翻译] 在 Overleaf 中使用参考文献
热门文章
- 软件测试书清华大学出版社,清华大学出版社-图书详情-《软件测试技术与实践》...
- 查看git当前tag_Git - git tag - 查看当前分支 tag 版本说明
- 超级实习生名企实习经历经得起背调吗?是正规实习吗?
- JavaScript预习
- squirrel 脚本_Squirrel便携式Shell和脚本语言
- 使用Squirrel创建基于Electron开发的Windows 应用安装包
- How to Play HLS Live Stream using ExoPlayer
- 协方差矩阵和相关系数矩阵(R语言)
- Maven及插件安装
- 【赛报速递】“赛博朋克,无不可测!” 2020上海国际创客大赛EdgeX专题赛赛报之赛博联物篇