阅读orbslam和orbslam2的论文
ORB-SLAM1
ORB-SLAM3是目前比较牛的VSLAM系统,所以打算从ORB-SLAM1开始看起,先通过论文初步了解一下
ORB-SLAM: A Versatile and Accurate Monocular SLAM System
(为了方便区分,就称为最初版的ORB-SLAM为ORB-SLAM1,但是实际上,应该只有ORB-SLAM、ORB-SLAM2和ORB-SLAM3)
ORB-SLAM1是沿用了PTAM系统的思想,ORB-SLAM1是使用单目相机,使用ORB特征来完成前端视觉里程计、局部优化、后端的全局优化以及回环检测等任务;ORB-SLAM1使用共视图用于局部轻量级优化;而位姿图则用于后端全局优化;为了降低计算量,ORB-SLAM1使用关键帧来完成优化任务,并非所有帧都参与计算;此外,ORB-SLAM1在跟踪失败后可以快速重建。
在ORB-SLAM1之前的技术框架
ORB-SLAM1一方面是有创新型工作;但同时它也是一系列工作的集大成者。下面就来说一下ORB-SLAM出来前的一些已有的工作
单目初始化
由于单目相机构成的SLAM系统在开始的时候没有办法获取到深度信息,所以需要计算本质矩阵或单应矩阵来完成地图的初始化工作。
但是初始化需要通过三角测量来完成,这也就需要使用对极约束来实现,但是这需要稳定的匹配,所以最简单的做法就是:选用标志性的物体用于初始化。但是这依然不能保证计算准确,所以一般还需要加入高斯噪声模型,不过一般是认为深度的倒数的噪声服从高斯分布(也就是逆深度模型)。
而在重建的时候,如果是在平面上进行平移,那么计算单应矩阵效果更好;而如果是在空间中进行平移,那么计算本质矩阵效果更好。但是显然这两种方法都有各自的缺点,所以ORB-SLAM1采用了两种方法的结合,也就是先计算本质矩阵,然后计算单应矩阵,最后选择重投影误差小的那个。而如果两者误差都比较大,那么会先不初始化,而是等待深度稳定后再执行初始化操作。
跟踪与建图
对于单目SLAM而言,因为帧率很高,一开始使用滤波技术来处理每一帧,但是短时间内的帧一般都是非常相似的物体,并且会导致误差很容易累计起来。所以后来就使用了关键帧来完成跟踪与建图,使用关键帧来进行优化,能提升准确率和优化精度。在PTAM中,就是通过关键帧来完成跟踪与建图,但是PTAM不进行回环检测,且重定位精度比较低。
另外,对于Strasdat提出的大型单目SLAM系统,其前端是在GPU上实现的光流法,并使用FAST特征匹配和局部BA,另外,还有一个基于滑动窗口全局BA。通过具有相似性约束7自由度的姿态图优化来解决回环检测问题,从而校正单目SLAM中出现的尺度漂移。但是他的回环检测也是几月窗口的,只有窗口够大才能覆盖所有的关键帧。在LSD-SLAM中,则是使用直接法来进行半稠密重建,但是它缺乏回环检测且定位精度较低。当然,还有一些其他的工作,比如SVO、DSO等。ORB-SLAM1从这些算法中借鉴了许多跟踪思想,比如使用关键帧、局部BA、回环检测、ORB算子;但是ORB-SLAM1也有自己的创新之处,比如使用共视图来完成局部BA、关键帧使用适者生存(插入关键帧很容易,但是不合适的关键帧会被很快删除)
回环检测
回环检测也是十分重要的,在SLAM中,一般使用词袋模型来完成回环检测。比如FAB-MAP是基于概率的词袋模型;而DBoW2是使用FAST角点和BRIEF特征描述子来构建的。而在ORB-SLAM1中,DBoW2是使用ORB特征来实现的,这样就能在显著降低运算量的同时保证较好的旋转、尺度不变性。(DBoW2是模板化的,因此它可以与任何类型的描述符一起使用,也相当于使用oFAST代替了FAST)
ORB-SLAM1系统
系统的架构如图所示,它有三个线程:跟踪线程、局部地图线程、回环检测线程。每一帧首先被跟踪线程提取处ORB特征,并检测是否需要初始化地图,并根据每一帧来进行重定位跟踪与关键帧跟踪,这里会使用位姿图BA进行优化;接下来进行局部地图的跟踪,并决定是否将当前帧设置为关键帧。
剩下的所有操作都是基于关键帧的,关键帧首先进入局部建图线程,生成地图点并进行局部BA优化;然后进入回环检测线程,但是ORB-SLAM1是没有全局BA的。
特征选择
ORB-SLAM1顾名思义,只使用ORB特征:特征检测、视觉里程计、优化、回环检测都是仅使用ORB特征。
选用ORB特征的原因首先是它快,它比SIFT、SURF这些算子快很多,同时也具有旋转、尺度不变性。另外ORB特征使用BRIEF作为特征描述子,这些特征描述子不是记录梯度或是小波变换,而是记录特定位置的像素亮度的大小,这样在SLAM这种光照经常变换的应用中具有更好的效果(因为特征不变时,光照变化,那么像素趋向于是同时变小,如果是记录梯度、小波变换这种,那么描述子的分量也会相应变化,而如果是仅仅比较两个像素的定性量,那么由于亮度同时变换,那么描述子基本不会发生改变)。此外,ORB特征使用BRIEF描述子,仅仅256位,且可以使用汉明距离进行匹配,特征子长度远远小于SIFT或SURF,这样可以大大降低计算量。
特征跟踪、局部建图与回环检测
在ORB-SLAM1中,存在三个线程,分别是特征跟踪线程、局部建图线程和回环检测线程。
先来说一下特征跟踪线程。这个线程负责读取所有的帧,然后提取ORB特征,然后进行特征匹配和位姿估计,此时的位姿估计仅仅使用纯轨迹图,也就是不优化特征点,仅仅优化相机位姿。如果跟踪失败,那么就会使用关键帧来进行重定位,如果在历史关键帧中检测出存在共视图的关键帧,那么就会使用共视图来重建局部地图,此时还需要执行BA优化来优化重定位的位姿。此外,特征跟踪线程还会决定是否需要把当前视频帧作为关键帧插入。
而对于局部建图线程而言,它仅仅接受关键帧,然后使用局部关键帧的BA去优化局部位姿(这是第二个BA了,第一个BA是在跟踪线程中)。由于新的关键帧肯定是与之前的关键帧存在一定的共视关系,所以利用这个共视点可以完成三角测量。此外,这个线程还会剔除掉不合适的关键帧,从而生成高质量的地图点。
而对于回环检测线程,就是在每一个新的关键帧中,都会检测是否存在回环,如果存在回环,那么就会使用回环关键帧的位姿图进行BA优化,从而优化整个位姿图,并消除累进误差。
地图点和关键帧的选择
地图点就是可以被跟踪的特征点的空间位置,他是一个三维点,ORB-SLAM会存储每个地图点的空间坐标系坐标、所有观测视角、OBR特描述子、根据ORB旋转不变性限制下的最大最小深度。
而关键帧则是具有典型性的信息的帧,它会存储相机位姿、相机内参、所有帧内的ORB特征点
在ORB-SLAM1中,地图点和关键帧的创建条件很宽松,但是能够持续保留下来则比较困难(也就是删除和创建都很容易),通过这种适者生存的方案,可以兼顾在纹理少时提取足够的地图点,而在纹理多时又选出高质量的地图点。
共视图和本质图
ORB-SLAM1只使用关键帧用于后续的位姿估计、回环检测,可以看成是使用关键帧来对视频流进行采样。而这些相邻两个关键帧之间一般会观察到一些同样的特征点,这些特征点相当于被共同看到了,所以可以认为是一种共视的关系,通过这种共视的关系组织成的优化图便是共视图。
如果两个相邻的关键帧之间的共视点数目超过15个,那么就认为这两个关键帧之间存在一条边。
理论上通过这些共视图就可以完成优化,但是共视图的边的数目太多,导致进行图优化时计算量大且困难,所以又延伸出了本质图。
利用所有关键帧来构建出生成树,这个生成树提供了以最少边数目连接共视图结点的一个子图。(也就相当于是最小生成树,共视图中的每个边都有一个表示共视点数目的权重,所以这样生成出来最小生成树可以看成是共视图中仅仅保留最优的共视关系),这样的话,由于丢弃了大量的边,所以计算量大大降低。并且这种方式也不会显著降低BA精度。
词袋回环检测
使用关键帧的ORB特征来构建一个很大视觉向量单词本,然后通过特征词向量进行查询即可获取到对应的回环关键帧。
地图初始化
由于单目相机需要使用三角测量来进行像素深度估计从而完成地图初始化,而ORB-SLAM1恰好是一个单目相机的SLAM系统。
由于如果是平移变化,那么只需要计算本质矩阵/基础矩阵即可;而如果是在平面上的旋转运动,那么计算单应矩阵会更加合适。在ORB-SLAM1中,使用计算出ORB特征和较好匹配关系,然后会同时使用两种方法来计算初始化方式,并选择最好的计算结果。
在计算好基础矩阵和单应矩阵后,会首先计算有效的内点(也就是良好匹配的点),如果两种方法的内点数目都比较少,那么会重新采集数据并计算基础和单应矩阵。
在计算本质和单应矩阵时,使用的时RANSAC算法,会使用卡方检验来估计内点与外点,并按照检验结果为本质矩阵和单应矩阵计算一个分数,接下来使用一个经验公式来判断到底使用哪个模型来进行估计。在计算完位姿后,还会有一个全局BA来进一步优化位姿。
使用这种方法,虽然有时不能立刻初始化,但是这种方法能获取到较好的初始化结果。
特征跟踪
下面来详细阐述一下跟踪线程的内容。特征跟踪线程就是读取所有视频帧、提取ORB特征、进行特征匹配和位姿估计。
ORB特征提取
由于ORB要保证尺度等价性,所以要使用图像金字塔来进行检测角点,ORB-SLAM1会尽可能从不同的尺度下提取近似相等的角点数目,这样可以保证在不同的尺度下都能提取到角点。而同样为了保证特征点在不同区域之间是均匀的,会把一个图像分程若干个网格区域,在每个网格内尽可能选择数目相等的点。
位姿估计
如果当前帧与上一时刻的帧能够完成匹配与跟踪,那么就是用等速运动模型来预测相机位姿,也就是假设运动速度是相等的,可以直接计算出位姿,而不需要去重投影什么的。但是如果利用恒速运动模型计算出来的大量新的特征点的附近无法搜索到观测到的特征点,那么就认为这个恒速运动模型是不合理的,此时就会使用重投影误差最小化来计算位姿。当然,恒速模型在进行匹配的时候也可以使用BA来优化位姿的,从而计算一个较好的位姿。
如果恒速运动模型的匹配结果不好,那么就会扩大搜索范围,如果还是找不到,那么就认为是跟丢了,需要进行重定位。
在重定位中,首先计算出帧的词袋模型,然后在数据库里查询词袋从而实现全局重定位。如果能够找到合适的关键帧,那么就会使用PnP算法来计算位姿,并且会使用全局BA来进一步优化位姿。
这三种跟踪模式仅仅跟踪了一帧图像中的特征,没有全局的信息,因此获取的位姿误差较大。
跟踪局部地图
一旦我们通过上面三种模型获取了初始的相机位姿和初始的特征匹配,就可以将完整的地图投影到当前帧中去搜索更多的匹配。这里用局部地图而不是之前所有的关键帧也是为了减少复杂度。这个局部地图包含了关键帧集合К1和К2,其中К1包含了与当前帧有共视关系的所有关键帧, К2包含了К1的每一帧在共视图中的临近帧。之后在局部地图中再次优化当前帧的位姿。
匹配过程如下:
- 抛弃投影范围超出相机画面的
- 抛弃观测视角和地图平均观测方向相差60°以上的
- 抛弃特征点的尺度和地图点的尺度不匹配的
- 计算当前帧中特征点的尺度
- 将地图点的描述自和当前帧的ORB特征描述子匹配,根据地图点的尺度位姿获取的粗略投影位置附近进行搜索
相机姿势最终会使用帧中找到的所有地图点进行优化,这样就相对准确。
插入关键帧
最后一步是确定当前帧是否生成为新关键帧。由于存在剔除冗余关键帧的机制,因此我们会尽快插入关键帧,因为这样可以使跟踪对具有相机移动时的变化(通常是旋转)更加可靠。要插入新关键帧,必须满足以下所有条件:
- 距离上一次重定位至少20帧
- 局部地图线程空闲,或者距离上一次加入关键帧过去了20帧。如果需要关键帧插入(过了20帧)而LocalMapping线程忙,则发送信号给LocalMapping线程,停止局部地图优化,使得新的关键帧可以被及时处理(20帧,大概过去了不到1s)
- 当前帧跟踪至少50个点,确保了跟踪定位的精确度
- 当前帧跟踪到LocalMap中参考帧的地图点数量少于90%,确保关键帧之间有明显的视觉变化
局部建图
在局部建图线程中,它仅仅使用关键帧来进行处理,在这个线程中,它会首先把新获取的关键帧插入到目前的结构中,然后去掉不太好的地图点并且生成新的地图点,最后使用局部BA来优化关键帧的位姿。在做完这些后,他还会删掉一些不太好的关键帧。
关键帧插入
首先,将更新共视图,为当前关键帧
地图坏点剔除
所有地图点都必须在它被创建后的前三帧内进行检查,如果不满足条件,那么就会被剔除:
- 地图点创建中涉及到了多个关键帧(理论上两帧三角测量即可),那么必须要存在至少三个关键帧能够观测到该地图点
如果地图点满足了上述条件,那么它就会被保留。不过如果出现关键帧被剔除,且地图点只能被3个以下的关键帧观测到,那么这个地图点也会被剔除。
地图点的生成
只需要使用ORB特征进行匹配,然后计算深度、投影误差,并保证满足对极约束即可。匹配完成后进行三角测量,那么就能得到特征点的地图点。
可能会在多个帧中匹配到相同的地图点,此时要把其余帧中特征点投影到某两个帧上,然后进行计算深度信息。
局部BA
局部BA是利用之前的共视图的局部关系,来优化位姿,同时还涉及到异常点的提剔除。
也就是使用二阶邻域关系来构建的局部地图。
关键帧剔除
因为除非新增了场景,否则理论上关键帧数目应该是不会发生变化的(因为总信息有限),所以可以剔除掉重复的关键帧。
在ORB-SLAM1中,会把90%地图点已经在其他至少3个关键帧中可以被观测到的关键帧给删掉。
回环检测
回环检测线程就是检测回环,并尝试闭合路径。
回环的检测
在检测回环的过程中,首先会计算关键帧和他在共视图中的所有相邻关键帧的词袋向量,并统计这些词袋向量的相似性,计算出这些最低的相似分数
在上述计算完成后,可能会得到一些关键帧,此时还需要剔除掉所有与当前关键帧向量的候选回环帧(因为没有正确回环肯定是一种长距离上的累进误差造成的),剩下的与当前关键帧不相连的帧就都被作为候选回环帧
计算相似变换
在匹配到回环帧后,下面就需要计算变换,在单目里有7个自由度(平移3+旋转3+深度1),所以下面就需要计算这些变换。
会首先匹配两者之间的地图点,然后计算3D-3D的变换,因为可能存在多个后端回环帧,所以需要为每一对都计算变换,接下来,使用RANSAC迭代法,结合Horn方法来计算出变换,童话故事也能得到一个针对内点的相似度,如果内点的相似度够大,那么就会进一步去搜索更多的内点,然后再次计算相似性变化,如果内点够多,那么就认为这个回环是有效的。
回环校正
回环校正是针对共视图中的结点而言的,因为检测出回环,相当于多了一条边。
此时使用计算出来的相似变化来完成两个结点的对齐,然后还需要同时更新关键帧的相邻结点的地图点匹配关系,共视图中所有涉及到的关键帧都需要更新他们的边,从而保证有效闭合
本质图优化
在得到回环后的共视图后,下一步为了尽可能好的确定位姿关系,所以需要对新的到的本质图进行一次BA优化,这样就能更好的确定位姿关系。
实验结果
ORB-SLAM1在文中很大的篇幅是在做对比实验,但是总是ORB-SLAM1的实验结果都是较好的,所以这里就不再赘述了。
ORB-SLAM2
ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras
ORB-SLAM2是对ORB-SLAM1的一次改进,它现在支持单目、双目和RGBD相机了,而之前的ORB-SLAM1仅仅支持单目相机。ORB-SLAM2且不一定需要ROS环境,而ORB-SLAM1则完全基于ROS。另外,ORB-SLAM2可以使用双目、RGBD相机来解决在纯旋转运动时的漂移与丢失。
在流程方面,ORB-SLAM2比ORB-SLAM1多了一个数据预处理部分,这是为了适配多种传感器的必要手段。而且ORB-SLAM2也多了一个全局BA的模块,可以更好的优化位姿。另外ORB-SLAM2还有一个仅定位模式,当对地图进行重建后,可以使用此模式来完成定位,而不需要进行建图,速度更快。
相关技术
在ORB-SLAM2之前,也存在一些基于双目视觉、RGBD相机的SLAM方案,下面来简要介绍一下。
双目SLAM
在此之前,就已经有研究认识到使用双目视觉时,由于基线的限制,导致远点的深度估计是不完全准确的(当点的深度小于基线的40倍时可以准确的三角测量)。大多数的双目SLAM都是基于关键帧并使用局部BA来优化位姿,因为局部BA才能保证计算量相对较小,但是这又导致地图较大时可能全局优化位姿。还有一些双目SLAM是基于光流法的半稠密重建,它不需要特征,但是可能在相机曝光时间较短时无法准确估计。
RGBD SLAM
由于使用RGBD直接测量了深度,所以得到的都是三维的点,可以直接使用ICP来估计。目前基本上都是把深度融合进图像中,然后使用ICP来跟踪帧与帧之间的特征点运动关系,从而估计出位姿。
当然由于ORB-SLAM2需要同时处理单目、双目、RGBD相机的输入,所以一般都会把双目和RGBD转化成一种统一的深度格式数据,相当于多了一个适配器,用于转换数据格式,从而不影响后续的处理流程。
ORB-SLAM2系统
ORB-SLAM2和ORB-SLAM1的系统基本上是保持一致的,所以这里主要再介绍下更新的部分。
3+1线程
ORB-SLAM2沿用了3个常驻线程,也就是特征跟踪、局部建图和回环检测线程,但是从图上可以看到一个额外的全局BA线程。
当回环检测成功后,那么会唤醒全局BA线程来执行一次全局BA优化。
双目与RGBD相机的预处理
ORB-SLAM2会对数据进行预处理,只使用一种格式来表示多种传感器的数据。
对于双目相机的数据,则使用三角测量出深度;对于RGBD相机,则直接把测量的深度融合。这样就能得到一种统一的深度数据格式。
其中双目坐标可以理解成是用于表示深度的坐标;而单目坐标则是双目但是深度不准确或者是单目相机拍摄的图像坐标。
单目与双目、近远点
对于双目相机:首先必须对双目相机进行外参校正,使其满足对极约束。然后分别从左图和右图计算出ORB特征描述子,对于左图的ORB特征点,沿着右图对应的极线进行搜索匹配的特征(因为已经满足了对极约束),如果用
对于RGBD相机:它没有右图,所以可以使用已知的深度来计算出一个等效的
上述得到的坐标看起来都是具有深度信息的深度特征点(stereo keypoints),但是由于RGBD是存在测量极限的,而对于双目相机,超过基线40倍的深度也是无法测量的,所以ORB-SLAM2将其分为近点与远点,对于近点,使用双目坐标,直接通过两帧或RGBD读数测量出深度信息;对于远点,只使用多个帧来测量深度。
因此,近点使用(
上面描述了双目和RGBD相机,而对于单目相机而言:所有特征点都是远点,也就是mono keypoints,必须要通过多个帧来估计深度。
地图初始化
仅有单目SLAM需要初始化,而双目和RGBD相机不需要初始化,因为他们一开始就能获取到深度信息。
不同的BA
在ORB-SLAM2中,在跟踪线程中使用位姿图执行仅运动BA来估计出相机位姿;在局部建图线程中,使用位姿和地图点来执行局部BA来优化位姿和地图点;在回环检测线程后,使用位姿和地图点来执行全局BA来优化位姿和地图点。
回环检测与全局BA
回环检测的步骤与ORB-SLAM1中的类似,但是在ORB-SLAM2中,由于使用了双目/RGBD相机,所以不会出现非常大的漂移现象。另外,回环检测成功后,会唤醒全局BA线程来执行一次全局BA优化,这样就能更好的优化位姿。
不过由于全局BA非常耗时,所以全局BA在单独一个线程中完成。但是又可能会出现在执行全局BA过程中,又重新检测到回环,这时会立刻终止全局BA,等到回环检测完成后再根据新的共视图来执行全局BA。
关键帧插入
由于ORB-SLAM2又引入了近远点的分类,所以一般会选择近点多的作为关键帧,因为近点的深度估计更加准确,所以可以更好的估计位姿。
仅定位模式
当完成建图后,如果地图中场景不会发生显著改变,那么可以考虑使用仅定位模式。在这种模式里,局部地图线程和回环检测线程都会被关闭,相机仅仅通过重定位的方式完成定位。此时,特征跟踪线程使用视觉里程计来完成与地图点的匹配,然后就可以解算出位姿。
实验结果
ORB-SLAM2也同样做了很多对比试验,这里就不再赘述了。