转载请注明出处,谢谢
原创作者:Mingrui
原创链接:https://www.cnblogs.com/MingruiYu/p/12358458.html


本文要点:

  • ORB-SLAM2 单目初始化部分 论文内容介绍
  • ORB-SLAM2 单目初始化部分 代码结构介绍

写在前面

之前的 ORB-SLAM2 系列文章中,我们已经对 Tracking 线程做了介绍,但是当时我们跳过了 Tracking 线程中一个很重要的部分 —— 单目初始化。我们将在本文中,对 ORB-SLAM2 系统的单目初始化部分进行介绍。

依旧祭出该图,方便查看:

也再次献上我绘制的程序导图全图:ORB-SLAM2 程序导图

老规矩,还是分两部分:以 ORB-SLAM 论文为参考 和 以 ORB-SLAM2 代码(程序导图)为参考。

以 ORB-SLAM 论文为参考

对于任何一个单目 SLAM 系统来说,在系统运行之初都要进行初始化,其目的在于,要计算出某两帧的相对位姿,以此来通过三角化得到一些初始 MapPoints,从而得到一个初始的 Map,这样之后的跟踪也好优化也好都在这个基础上进行。在 ORB-SLAM 之前的单目 SLAM 系统的初始化,往往需要依赖真实场景中某样确定的物体(eg. MonoSLAM)或者需要人工介入(eg. PTAM),而 ORB-SLAM 的单目初始化是完全自动的。

对 SLAM 基础知识有过了解的同学会知道,恢复两帧之间的相对运动,有两种模型:基础矩阵(Fundamental)(等同于本质矩阵)模型和单应矩阵(Homography)模型。正常情况下基础矩阵模型应该可以应付,但如果特征点共面(初始化场景中主要是一个平面),或者两帧之间的相对位姿未纯旋转时,基础矩阵的自由度会下降,也就是所谓的退化,类似于方程数少于变量数。此时为了保证运动恢复的精度,就不能再用基础矩阵模型。由此提出了单应矩阵,其假设特征点落在同一平面上,从而适用于这种场景下的运动恢复。

ORB-SLAM 在初始化时,它也不知道场景中的特征点在不在同一平面,所以它选择两种模型各自算一遍(开两个线程同时算),之后计算两种模型各自进行运动恢复的得分,取得分高的模型,再根据该模型,计算两帧之间的相对位姿并进行初始化。

单目初始化具体步骤

1. 提取 ORB 特征点

在当前帧和参考帧中提取 FeaturePoints(只在最优的尺度),同时将当前帧和参考帧的 FeaturePoints 做匹配。如果匹配点不够多,重新初始化。

2. 同时计算两种模型

  • 单应矩阵 \(H_{cr}\):DLT 算法 + RANSAC 迭代
  • 基础矩阵 \(F_{cr}\):8点法 + RANSAC 迭代

同时计算两种模型各自的得分,计算公式如下:

\(S_{M}=\sum_{i}\left(\rho_{M}\left(d_{c r}^{2}\left(\mathbf{x}_{c}^{i}, \mathbf{x}_{r}^{i}, M\right)\right)+\rho_{M}\left(d_{r c}^{2}\left(\mathbf{x}_{c}^{i}, \mathbf{x}_{r}^{i}, M\right)\right)\right)\)

\(\rho_{M}\left(d^{2}\right)=\left\{\begin{array}{ll} {\Gamma-d^{2}} & {\text { if } \quad d^{2}<T_{M}} \\ {0} & {\text { if } \quad d^{2} \geq T_{M}} \end{array}\right.\)

其中 \(d_{c r}^{2}\) \(d_{r c}^{2}\) 是对称转换误差。\(\rho_{M}()\) 的作用是令大的误差对低的得分,其中 \(T_M\) 阈值是算出来的:假设测量值误差的标准差为1像素,通过95%的 \(\chi^{2}\) 检验得到的。对于每种模型,在 RANSAC 迭代过程中保留得分最高的模型。如果最终没能求出解(对于 RANSAC,inliers不够多),则重新初始化。

3. 选择合适的模型

根据两种模型各自的得分:

\(R_{H}=\frac{S_{H}}{S_{H}+S_{F}}\)

如果 \(R_H\) > 0.45(代码中是 0.4),则选用单应矩阵;反之则选基础矩阵模型。大概就是选得分高的,此处的 0.4 应该是经验值。

4. 进行运动恢复,求解两帧相对位姿(\(R, t\))并通过三角化得到初始 MapPoints

在求出 \(H_{cr}\) 或 \(F_{cr}\) 后,就要根据该矩阵求出相对位姿(\(R, t\))。但这个过程的求出的解不是唯一的。ORB-SLAM 采取的筛选办法是:对这些解全部进行三角化恢复 MapPoints,哪个解恢复出来的 MapPoints 大部分都在相机前方且重投影误差小,就选哪个解。如果不能明确选出一个最合适的,则重新初始化。

5. BA 优化

最后,进行一次全局 BA,优化以下,得到最终的初始化结果。

从以上步骤可以看出,ORB-SLAM 在单目初始化花了很多心思。有一个很明显的特点:只要出现一点不妥,ORB-SLAM 就会选择重新初始化。论文中说,这种高标准严要求的初始化准则,是 ORB-SLAM 系统鲁棒性非常好的重要原因之一。因为如果初始化就不合适或出错,后面的跟踪只会一错再错,错上加错。

以 ORB-SLAM2 代码(程序导图为参考)

在上图中 MonocularInitialization() 就是初始化的程序,我们可以看到它在 Tracking 线程中的位置。

上图是 MonocularInitialization() 部分的程序框图,其大体和论文中介绍的步骤是完全一致的,这样图已经很清晰了,这里就不多描述了。

PS: 从中上图我们可以看到,在恢复出两帧之间的相对运动后,程序中还要使用 Tracking::CreateInitalMapMonocular() 来建立初始化的地图。这部分在论文里几乎没有笔墨提到,但在程序里需要很大篇幅来实现。这个细节就反映了我在本系列博文开篇就提到过的读通 ORB-SLAM2 代码的困难之处。以我现在小菜鸡的水平,我根本想象不出 ORB-SLAM2 这样复杂而环环相扣的工程是怎么写出来的(流泪)。

ORB-SLAM2 系列博文

ORB-SLAM2 初体验 —— 配置安装

ORB-SLAM2 论文&代码学习 —— 概览

ORB-SLAM2 论文&代码学习 —— Tracking 线程

ORB-SLAM2 论文&代码学习 —— 单目初始化

ORB-SLAM2 论文&代码学习 —— 单目初始化的更多相关文章

  1. ORB-SLAM2 论文&代码学习 —— LocalMapping 线程

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12360913.html 本文要点: ORB-SLAM2 Local ...

  2. ORB-SLAM2 论文&代码学习 ——Tracking 线程

    本文要点: ORB-SLAM2 Tracking 线程 论文内容介绍 ORB-SLAM2 Tracking 线程 代码结构介绍 写在前面 上一篇文章中我们已经对 ORB-SLAM2 系统有了一个概览性 ...

  3. ORB-SLAM3 细读单目初始化过程(上)

    作者:乔不思 来源:微信公众号|3D视觉工坊(系投稿) 3D视觉精品文章汇总:https://github.com/qxiaofan/awesome-3D-Vision-Papers/ 点击上方&qu ...

  4. ORBSLAM2单目初始化过程

    ORBSLAM2单目初始化过程 转自博客:https://blog.csdn.net/zhubaohua_bupt/article/details/78560966 ORB单目模式的初始化过程可以分为 ...

  5. ORB-SLAM (四)tracking单目初始化

    单目初始化以及通过三角化恢复出地图点 单目的初始化有专门的初始化器,只有连续的两帧特征点均>100个才能够成功构建初始化器. ); 若成功获取满足特征点匹配条件的连续两帧,并行计算分解基础矩阵和 ...

  6. ORB-SLAM2 论文&代码学习 —— 概览

    转载请注明出处,谢谢 原创作者:MingruiYU 原创链接:https://www.cnblogs.com/MingruiYu/p/12347171.html *** 本文要点: ORB-SLAM2 ...

  7. ORB-SLAM2 论文&代码学习 —— LoopClosing 线程

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12369339.html 本文要点: ORB-SLAM2 LoopC ...

  8. ORB-SLAM (四)Initializer单目初始化

    一. 通过对极约束并行计算F和H矩阵初始化 VO初始化目的是为了获得准确的帧间相对位姿,并通过三角化恢复出初始地图点.初始化方法要求适用于不同的场景(特别是平面场景),并且不要进行人为的干涉,例如选取 ...

  9. 单目、双目和RGB-D视觉SLAM初始化比较

    无论单目.双目还是RGB-D,首先是将从摄像头或者数据集中读入的图像封装成Frame类型对象: 首先都需要将彩色图像处理成灰度图像,继而将图片封装成帧. (1) 单目 mCurrentFrame = ...

随机推荐

  1. String.valueOf(null)

    public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); ...

  2. 关于neo4j初入门(5)

    neo4j和Java Neo4j提供JAVA API以编程方式执行所有数据库操作. 它支持两种类型的API: Neo4j的原生的Java API Neo4j Cypher Java API Neo4j ...

  3. sqlachemy查询对象转化成字典/json使用

    https://www.cnblogs.com/sanduzxcvbnm/p/10220718.html

  4. 安装xpath helper

    1.下载 版本是:2.02的 链接:https://pan.baidu.com/s/1YdyTbWElL904EMQ-9Ougnw 提取码:bxxa 2.无效安装的解决方案 参考链接:https:// ...

  5. 2017-10-28 noip模拟赛by WISCO 信息组

    第一次做模拟赛,自我感觉良好(大概是这套题比较简单) T1 名称为“数据结构”,这也太坑了点……233 要维护一个数列(初始为零),支持区间加与查询. 查询的是一个区间中有多少数满足min<=( ...

  6. # 团队项目-Beta冲刺2(七个小矮人)

    团队项目-Beta冲刺2(七个小矮人) 一.格式描述 这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/GeographicInformationScien ...

  7. Dynamics 365 CRM 在 Connected Field Service 中部署 IoT Central (一)- 配置 IoT Central和IoT alert

    今天这个系列给大家带来怎样在connected field service中部署IoT Central 并且做连接. 首先, 这里提供微软官方的tutorial的链接https://docs.micr ...

  8. Java多态之Father f=new Son();

    成员变量静态方法看左边,非静态方法编译看左边,运行看右边. 左边Father f其实是定义了一个Father类的对象,而右边new Son()可以只理解为是一个重写了Father类方法的对象. 因此, ...

  9. nmap详解之基础概述

    概述 nmap是一个网络探测和安全扫描程序,系统管理者和个人可以使用这个软件扫描大型的网络,获取那台主机正在运行以及提供什么服务等信息.nmap支持很多扫描技术,例如:UDP.TCP connect( ...

  10. 云原生 - Istio可观察性之监控(四)

    作者:justmine 头条号:大数据与云原生 微信公众号:大数据与云原生 创作不易,在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处. 为了方便阅读,微信公众号已按分类排版,后续的文 ...