第1周课件-全网最详细的ORB-SLAM2精讲

rgbdslam_v2在Ubuntu18.04+ROS_melodic的运行以及相关问题解决

https://blog.csdn.net/weixin_44436677/article/details/105587986

https://blog.csdn.net/XindaBlack/article/details/102499364/


目录

1. ORB_SLAM 2简介

1.1 ORB_SLAM 2简介

1.2 ORB_SLAM2 框架

主体框架

数据输入的预处理

2. TUM 数据集使用

2.1 ORB_SLAM2 在TUM数据集上的表现

2.2 TUM RGB-D 数据集 简介

2.3 运行RGBD模式时的预处理

2.4. 不同颜色地图点的含义

3. ORB 特征

3.1 FAST关键点

3.2 BRIEF 特征

3.3 ORB 特征

3.4 为什么要重载小括号运算符 operator() ?

3.5 金字塔的计算

3.6 特征点数量的分配计算

3.7 使用四叉树对图层中的特征点进行平均和分发


 
 
 
本周课程学前准备:
1. Ubuntu 操作系统,不建议装虚拟机。版本 16.04 18.04 20.04 均可 win10 + Ubuntu18.04 双系统安装教程可参考:
https://www.cnblogs.com/masbay/p/10844857.html
https://www.jianshu.com/p/fe4e3915495e
https://www.cnblogs.com/tanrong/p/9166595.html
Linux 入门教程:
鸟哥的 Linux 私房菜 -- 基础学习篇
http://cn.linux.vbird.org/linux_basic/linux_basic.php
Linux 命令 快速索引
http://cn.linux.vbird.org/linux_basic/1010index.php

 

本周课程重点
1. 熟悉Ubuntu操作系统,掌握Linux基础语法。
2. 初步了解ORB-SLAM2的优点及应用。
3. 成功编译并运行ORB-SLAM2 单目模式。
4. 掌握ORB特征及均匀化原理及实现。

 

1. ORB_SLAM 2简介

1.1 ORB_SLAM 2简介

首个( 2017 年发布时)支持单目,双目和 RGB-D 相机的完整的开源 SLAM 方案,具有回环检测和重 新定位的功能。 能够在CPU 上进行实时工作,可以用于移动终端如 移动机器人、手机、无人机、汽车。
特征点法的巅峰之作,定位精度极高,可达厘米级。 能够实时计算出相机的位姿,并生成场景的稀疏三维重建地图。 代码非常工整,可读性强,包含很多实际应用中的技巧,非常实用。 支持仅定位模式,该模式适用于轻量级以及在地图已知情况下长期运行,此时不使用局部建图和回 环检测的线程。 双目和RGB-D 相对单目相机的主要优势在于,可以直接获得深度信息,不需要像单目情况中那样 做一个特定的SFM 初始化。
 

1.2 ORB_SLAM2 框架

主体框架

第1周课件-全网最详细的ORB-SLAM2精讲_第1张图片

数据输入的预处理

为了兼容不同相机(双目相机与 RGBD 相机) , 需要对输入数据进行预处理,使得交给后期处理的数据格式一致( 这一点做的很好,兼容性很好 ),具体流程如下:

第1周课件-全网最详细的ORB-SLAM2精讲_第2张图片

 

2. TUM 数据集使用

2.1 ORB_SLAM2 在TUM数据集上的表现

第1周课件-全网最详细的ORB-SLAM2精讲_第3张图片

2.2 TUM RGB-D 数据集 简介

注意两点:深度的表达方式 以及 数据的存储格式

第1周课件-全网最详细的ORB-SLAM2精讲_第4张图片

2.3 运行RGBD模式时的预处理

关于 associate.py  , 注意:只能在Python2 环境下运行
 
Python 下运行
python associate.py rgb.txt depth.txt > associate.txt
python associate.py associate.txt groundtruth.txt > associate_with_groundtruth.txt
 
注意:
直接 association 后出问题,生成的结果 associate.txt 1641行; associate_with_groundtruth.txt 1637行;也就是说,associate 的不一定有 groundtruth ,所以要以 associate_with_groundtruth.txt 的关联结果 为准

 

2.4. 不同颜色地图点的含义

红色 点表示参考地图点,其实就是 tracking 里的 local mappoints
void Tracking::UpdateLocalMap()
 { // This is for visualization 
   mpMap->SetReferenceMapPoints(mvpLocalMapPoints); 

   // Update UpdateLocalKeyFrames(); 
   UpdateLocalPoints();
 }
黑色 点表示所有地图点,红色点属于黑色点的一部分

第1周课件-全网最详细的ORB-SLAM2精讲_第5张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第6张图片

 

3. ORB 特征

3.1 FAST关键点

第1周课件-全网最详细的ORB-SLAM2精讲_第7张图片

1、选取像素p,假设它的亮度为Ip设置一个阈值T(比如Ip20%);
2、以像素p为中心,选取半径为3的圆上的16个像素点;
3、假如选取的圆上,有连续的N个点的亮度大于Ip+T或小于Ip-T,那么像素p可以被认为是特征点;
4、循环以上4步,对每一个像素执行相同操作。
 

3.2 BRIEF 特征

https://blog.csdn.net/hltt3838/article/details/105912580

论文: BRIEF: Binary Robust Independent Elementary Features
BRIEF 算法的核心思想是在 关键点P的周围以一定模式选取N个点对,把这 N个点对的比较结果 组合起来作为描述子 。为了保持踩点固定,工程上采用特殊设计的固定的 pattern  来做

第1周课件-全网最详细的ORB-SLAM2精讲_第8张图片

 

问题1: FAST特征点的数量很多,并且不是确定,而大多数情况下,我们希望能够固定特征点的数量。
解决方法: 在ORB当中,我们可以指定要提取的特征点数量。对原始的FAST角点分别计算Harris的响应值,然后选取前N个点具有最大相应值的角点,作为最终角点的集合。
问题2: FAST角点不具有方向信息和尺度问题。
解决方法: 尺度不变性构建的图像的金字塔,并且从每一层上面来检测角点。 
灰度质心法: 质心是指以图像块灰度值作为权重的中心。(目标是为找找到方向:几何中心 ——>  Q为灰度质心).

理解:为什么要考虑尺度的问题? 因为相机在运动的过程中,可能离物体越来越远或者越来越近这时候出现的情况是:近看图像上的特征点,在远看图像上就没有啦,因为图像的平滑,那么更别说特征点的匹配了! 为了让它们能匹配上,需要对图构建尺度空间,获得图片不同尺度下的表达,并获取特征点,具体的做法就是图像的金字塔。比如:我们要提取1000个特征点,而金字塔的层数是8,把这1000个特征点按照面积比例分别在 每层图像提取,这样的话就是说在不同尺度的图片上都能提取到特征点,这样就可以解决前面说的相机在运动的过程中,可能离物体越来越远或者越来越近这时候出现的情况是:近看图像上的特征点,在远看图像上就没有啦” 问题!

 

参考:https://blog.csdn.net/RobotLife/article/details/87194017?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=48c2bb06-67c0-42b6-8a5d-4ead425a80a7&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control   具体的理解可以看后面的内容+代码理解!

 

3.3 ORB 特征

原始的 FAST 关键点没有方向信息,这样当图像发生旋转后, brief 描述子也会发生变化( 图像的灰度值可能发生改变 ) ,使得特征点对旋转不鲁棒 ; 解决方法: orientated FAST ,使用灰度质心法计算特征点的方向, 什么是灰度质心法?

第1周课件-全网最详细的ORB-SLAM2精讲_第9张图片

在一个圆内计算灰度质心 ,下图P为几何中心,Q为灰度质心

第1周课件-全网最详细的ORB-SLAM2精讲_第10张图片

https://blog.csdn.net/qq_18661939/article/details/52900524
 
理解:半径为R的圆内,选取 FAST关键点,描述子, 且在圆内质心是唯一的,不变的,那么 特征点和质心的连接便可以确定方向 ! 至此,不仅仅提取了FAST角点,还找出了角点的角度。这个角度可以用来指导描述子的提取,保证每次都在相同的方向上计算描述子,实现角度不变性。 这就是Oriented FAST。
 
有的人看到上面的解释后,可能还不理解为什么灰度质心法为什么保证了图像的旋转不变性,下面进行更加详细的解析! 仔细理解!
 
其中 x、y为图像块中的像素在关键点坐标系中的坐标。需要知道,当图片旋转时,图像块(方格区域)的质心在图像块中的位置并未改变 ( 质心在垂直坐标系中的坐标是变化的)
在这里插入图片描述
上图表示, 在FAST关键点的基础上,进行描述子的计算时,当图像发生旋转后,图像上的随机像素对的坐标将会发生变化,使得描述子的差异很大,非常影响后期的特征匹配。如何能够让图片发生旋转时,所选的随机像素对的坐标不发生改变呢?如下图所示:
在这里插入图片描述
我们知道,ORB在进行FAST角点提取时,计算出了关键点的方向,上图左的向量OC,方向角为θ。
 
在这里插入图片描述
 
前面我们说过, 当图片发生旋转时,质心在图像块中的位置不变,因此,我们可以 将随机像素对在FAST关键点坐标系中的坐标(垂直坐标系)通过旋转θ角度,转换为其在Oriented FAST关键点坐标系中的坐标(向量OC为x轴的坐标系) (这一步才是关键,上图中的左图表示了坐标关系,而右图则表示,当图片旋转时,随机像素对在虚线坐标系(以向量OC为x轴坐标系)中的坐标不变,即旋转不变性。
 

 

下面求圆内的坐标范围 ,umax: 1/4 圆的每一行的 u 轴坐标边界(下图中橙色线段 FG
cvFloor 返回不大于参数的最大整数值, cvCeil 返回不小于参数的最小整数值,cvRound 则是四舍五入
vmax = cvFloor(HALF_PATCH_SIZE * sqrt(2.f) / 2 + 1);
vmin = cvCeil(HALF_PATCH_SIZE * sqrt(2.f) / 2); 

// 对应从D到B的红色弧线,umax坐标从D到C 
for (v = 0; v <= vmax; ++v) 
umax[v] = cvRound(sqrt(hp2 - v * v)); // 勾股定理,hp2 是半径

// 对应从B到E的蓝色弧线,umax坐标从C到A 
for (v = HALF_PATCH_SIZE, v0 = 0; v >= vmin; --v) 
{ 
   while (umax[v0] == umax[v0 + 1]) ++v0; 
   umax[v] = v0; 
   ++v0; 
}

第1周课件-全网最详细的ORB-SLAM2精讲_第11张图片

参考:
https://blog.csdn.net/liu502617169/article/details/89423494
https://www.cnblogs.com/wall-e2/p/8057448.html
 

问题:Umax和Vmax这些到底有什么用?

答案:主要是确定圆内横纵坐标的边界用的,方便索引像素值。这部分有点麻烦,详见课程第2讲; 认真理解一下,我们在索引像素值的时候,一定是个 for() 循环,那这个for()  循环的的边界值是多大?就是用这个方法确定的! 有人可能会说,边界值是R呀,但是你想一下,像素点的坐标 u,v轴是存在一个关系的,没有必要每次都最大范围R的搜索!

 

3.4 为什么要重载小括号运算符 operator() ?

可以用于仿函数(一个可以实现函数功能的对象) ,仿函数(functor )又称为函数对象( function object )是一个能行使函数功能的类。仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载operator() 运算符
1.  仿函数可有拥有自己的数据成员和成员变量,这意味着这意味着仿函数拥有状态。这在一般函数中是 不可能的。
2.  仿函数通常比一般函数有更好的速度。
 
扩展阅读   https://blog.csdn.net/jinzhu1911/article/details/101317367

 

3.5 金字塔的计算

ORBextractor::ComputePyramid

第1周课件-全网最详细的ORB-SLAM2精讲_第12张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第13张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第14张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第15张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第16张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第17张图片

尺度不变的理解:在orb_slam2中,为了实现特征尺度不变性采用了图像金字塔,金字塔的缩放因子为1.2, 其思路就是对原始图形(第0层)依次进行1/1.2缩放比例进行降采样得到共计8张图片(包括原始图像),然后分别对得到的图像进行特征提取,并记录特征所在金字塔的第几层,这样得到一帧图像的特征点。现在假设在第二层中有一特征点F,为了避免缩放带来特征点F在纵向的移动,为简化叙述,选择的特征点F位于图像中心。根据相机成像 “物近像大,物远像小” 的原理,假设 摄像机原始图像即金字塔第0层对应图2中成像视野I0 ,则图像金字塔第2层图像可以相应对应于图中成像视野I2 。其中特征点F所在patch的相应关系。根据得到 结论1: d2 / d0 = 1.22

有了以上铺垫现在,来说说,尺度不变性,这里不直接说明,而是看看对于第m层上的一个特征点,其对应尺度不变时相机与特征点对应空间位置之间距离(简称物距)的范围。假设第m层上有一特征点Fm,其空间位置与拍摄时相机中心的位置为dm ,显然这是原始图像缩放1/1.2m倍后得到的特征点patch,考虑 “物远像小” 的成像特点,要使得该第m层特征点对应patch变为图像金字塔第0层中同样大小的patch,其相机与空间点的距离d=dm * 1.2m ,即尺度不变的最大物距 dmax = dm*1.2m 。要求尺度不变的最小物距则这样考虑:根据 “物近像大” 的成像特点,使得当前第m层的特征点移到第7层上则,真实相机成像图像得放大1.27-m倍,故对应最小物距dmin=dm *1.2m-7 。

 

3.6 特征点数量的分配计算

来自: https://zhuanlan.zhihu.com/p/61738607

第1周课件-全网最详细的ORB-SLAM2精讲_第18张图片

 

3.7 使用四叉树对金字塔每一图层中的特征点进行平均和分发

DistributeOctTree
1、如果图片的宽度比较宽,就先把分成左右 w/h 份;一般的 640×480 的图像开始的时候只有一个 node
2、如果 node 里面的点数 >1 ,把每个 node 分成四个 node ,如果 node 里面的特征点为空,就不要了, 删掉。
3、新分的 node 的点数 >1 ,就再分裂成 4 node 。如此,一直分裂。
4、终止条件为: node 的总数量 > [ 公式 ] ,或者无法再进行分裂。
5、然后从每个 node 里面选择一个质量最好的 FAST 点。

 

第1周课件-全网最详细的ORB-SLAM2精讲_第19张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第20张图片

第1周课件-全网最详细的ORB-SLAM2精讲_第21张图片

参考: https://zhuanlan.zhihu.com/p/61738607
ExtractorNode::DivideNode

 

第1周课件-全网最详细的ORB-SLAM2精讲_第22张图片

节点分裂顺序:后加的先分裂

 

第1周课件-全网最详细的ORB-SLAM2精讲_第23张图片

理解:

ORB-SLAM中并没有使用OpenCV的实现,因为OpenCV的版本提取的ORB特征过于集中,会出现扎堆的现象。这会降低SLAM的精度,对于闭环来说,也会降低一幅图像上的信息量。具体的对ORB-SLAM的影响可以参考我的另一篇文章 杨小东:[ORB-SLAM2] ORB特征提取策略对ORB-SLAM2性能的影响;ORB-SLAM中的实现提高了特征分布的均匀性。最简单的一种方法是把图像划分成若干小格子,每个小格子里面保留质量最好的n个特征点。这种方法看似不错,实际上会有一些问题。当有些格子里面能够提取的数量不足n个的时候(无纹理区域),整幅图上提取的特征总量就达不到我们想要的数量。严重的情况下,SLAM就会跟丢喽,ORB-SLAM中的实现就解决了这么一个问题,当一个格子提取不到FAST点的时候,自动降低阈值。ORB-SLAM主要改进了FAST角点提取步骤。

上面步骤的内容理解如下:

第1周课件-全网最详细的ORB-SLAM2精讲_第24张图片

 

 

你可能感兴趣的:(ORB-SLAM,解析)