ORB_SLAM2::Initializer 用于单目情况下的初始化。

Initializer 的构造函数中传入第一张影像,这张影像被称作 reference frame(rFrame)。在获得第二张影像时传入第二张影像,这张影像被称作 current frame(cFrame)。这一部分传入的代码可以在ORB_SLAM2::Tracking::MonocularInitialization()中查看,要求 rFrame 与 cFrame 都至少具有 101 个特征点,而且 cFrame 与 rFrame 粗匹配结果不少于 100 个点对。这个粗匹配也很有意思,可以查看ORBmatcher::SearchForInitalization()(粗匹配是对每一个 rFrame 的特征点选定一定大小的窗口,以该特征点在 rFrame 上的坐标为中心,在 cFrame 上提取出覆盖网格内所有的特征点,计算 ORB 描述子的距离,距离够小就说明是匹配点)。

Initializer::Initialize()

在这个函数中完成初始化。首先生成 RANSAC 需要用的最小子集的集合mvSets。随后开两个线程同步进行FindHomographyFindFundamental,这两个函数分别返回SHSF这两个数值用于判定是使用 H 作为初始模型更好,还是用 F 作为初始模型更好。

在用SHSF判定是使用 H 还是 F 之后就是用 H (ReconstructH())或 F (ReconstructF())生成 R、t 和对应的可以三角化的点用于初始地图生成。

ReconstructH() 是使用 Motion and structure from motion in a piecewise planar
environment
生成 8 种可能结果,再使用CheckRT()确定是哪一种最为合适。

Initializer::FindHomography()

每次使用 8 个点通过 SVD 分解计算得到 H21。值得注意的是在进行 Homography 计算之前先进行归一化过程(在函数Normalize()中进行)。

Initializer::Normalize()

归一化过程是将所有的 KeyPoints 进行一次 Affine Transformation,使得变换后的 KeyPoints 均值为原点 \(0\),方差为单位阵 \(I\)。

变换公式为:

\[
x_i^{\prime} = {x_i - \bar{x} \over \sigma} \\
\bar{x} = {\Sigma{x_i} \over N} \\
\sigma = {\Sigma{\left|x_i - \bar{x}\right|} \over N}
\]

归一化的原因是计算出的 H 会依赖于特征点的位置,所以先归一化再计算。(MVG Page 104

归一化的过程可以使用一个矩阵 \(T\) 表示:

\[
x^{\prime} = Tx = \begin{bmatrix} {1 \over \sigma_x} & 0 & \bar{x}{1 \over \sigma_x} \\ 0 & {1 \over \sigma_y} & \bar{y}{1 \over \sigma_y} \\ 0 & 0 & 1 \end{bmatrix} x
\]

后面的计算过程如下:

\[
x_2^{\prime} = H_{21}^{\prime}x_1^{\prime}
\]

\[
Tx_2 = H_{21}^{\prime}Tx_1
\]

\[
x_2 = T^{-1}H_{21}^{\prime}Tx_1
\]

\[
H_{21} = T^{-1}H_{21}^{\prime}T
\]

Initializer::ComputeH21()

在归一化之后,使用归一化的坐标计算 Homography。

没啥好讲,就是 Direct Linear Transformation,参考 MVG Page 88

Initializer::CheckHomography()

用 H21 和 H12 分别将 rFrame(1) 中的特征点和 cFrame(2) 转换到另一张影像中,计算匹配点的距离误差,距离误差转换为卡方距离,卡方距离小于 5.991 说明显著性为 5%,应该认为它们匹配成功,否则不成功将这一对匹配标记为 false。注意这里有两个自由度。

https://en.wikipedia.org/wiki/Chi-squared_distribution#Table_of_.CF.872_values_vs_p-values

匹配成功能就能将于显著性相关的数值加入到评分中,评分越高说明由这八个点计算出的 Homography 越正确。即由CheckHomography()返回的评分currentScore,取 RANSAC 中评分最高的 Homography 作为最终选定的 Homography。

这个 score 会被传入Initialize()函数中的 SH,用作计算 SH/(SH+SF),判断是使用 Homography 还是 Fundamental。

Initializer::ReconstructH()

用函数FindHomography()中 RANSAC 计算得到的 Homography 分解,分解能够得到 8 种可能的 \(R, t\) 结果,用CheckRT()判断选择哪一种结果。

好像这有点错了吧,应该用所有的 inlier 匹配计算 Homography,再用这个更靠谱的 Homography 分解计算 \(R, t\)。

函数ReconstructH()最后也输出三角化成功的三维点。

Initializer::FindFundamental()

FindFundamental()的计算过程与 FindHomography 类似,都是需要进行归一化操作

函数ComputeF21()用八点法计算 Fundamental,计算得到的实际 Fundamental 通过设置最小特征值为 0 投影到 Fundamental 空间,作为输出。

函数CheckFundamental()是将点与线的距离作为误差,计算卡方距离,注意这里有一个自由度,所以显著性检验使用的卡方距离为 3.84。

都差不多,没啥好说的。

Initializer::CheckRT()

这个函数挺重要的,因为分解 H 和 F 都会有很多可能的结果,使用这个函数能够分辨出什么结果是靠谱的。

函数CheckRT()接受 \(R, t\) ,一组成功的匹配。最后给出的结果是这组匹配中有多少匹配是能够在这组 \(R, t\) 下正确三角化的(即 \(Z\) 都大于0),并且输出这些三角化之后的三维点。

如果三角化生成的三维点 \(Z\) 小于等于0,且三角化的“前方交会角”(余弦是 cosParallax)不会太小,那么这个三维点三角化错误,舍弃。

通过了 \(Z\) 的检验,之后将这个三维点分别投影到两张影像上,计算投影的像素误差,误差大于2倍中误差,舍弃。

总结

ORB 里面对通过“最大值”确定的结果都非常小心。一般要求这个“最大值” outstanding,如 ORBmatcher 的构造函数中就有会传入一个 (0,1) 的数值给成员变量 mfNNratio,只有最小距离小于次小距离的 mfNNratio 倍才能算是匹配成功,不允许出现相似的匹配,而取好那么一点点的匹配作为匹配结果。

Initializer::ReconstructH()中最后 8 个可能结果中,最好模型 inlier 数要大于次好模型 inlier 的 1/0.75 倍。

ORB_SLAM2 源码阅读 ORB_SLAM2::Initializer的更多相关文章

  1. ORB_SLAM2 源码阅读 ORB_SLAM2::Initializer::ComputeF21 (OpenCV 细节)

    ORB_SLAM2 计算 F21 的代码是这样的. cv::Mat Initializer::ComputeF21(const vector<cv::Point2f> &vP1,c ...

  2. ORB_SLAM2 源码阅读 ORB_SLAM2::ORBextractor

    整体架构 构造函数进行初始化,传入设定几个重要的成员变量.nfeatures(特征点的个数).nlevels(构造金字塔的层数).scaleFactor(金字塔中相邻层图像的比例系数).iniThFA ...

  3. 应用监控CAT之cat-client源码阅读(一)

    CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...

  4. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  5. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  6. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  7. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  8. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  9. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

随机推荐

  1. Caffe使用step by step:使用自己数据对已经训练好的模型进行finetuning

    在经过前面Caffe框架的搭建以及caffe基本框架的了解之后,接下来就要回到正题:使用caffe来进行模型的训练. 但如果对caffe并不是特别熟悉的话,从头开始训练一个模型会花费很多时间和精力,需 ...

  2. CSS3 Selectors All In One

    CSS3 Selectors All In One https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors https://www ...

  3. 【大数据】MapTask并行度和切片机制

    一. MapTask并行度决定机制 maptask的并行度决定map阶段的任务处理并发度,进而影响到整个job的处理速度 那么,mapTask并行实例是否越多越好呢?其并行度又是如何决定呢? 1.1 ...

  4. java中的变量各占得字节数

    boolen,8位1个字节int,32位,4个字节float,32位 4个字节double,64位8个字节char 16位,2个字节byte 8位1个字节short 16位 2个字节long 64位 ...

  5. 【刷题】BZOJ 2154 Crash的数字表格

    Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数.例如 ...

  6. 【BZOJ4036】按位或(Min-Max容斥,FWT)

    [BZOJ4036]按位或(Min-Max容斥,FWT) 题面 BZOJ 洛谷 题解 很明显直接套用\(min-max\)容斥. 设\(E(max\{S\})\)表示\(S\)中最晚出现元素出现时间的 ...

  7. BZOJ2530 [Poi2011]Party 【贪心】

    题目链接 BZOJ2530 题解 如果我们删去一对不连边的仍然存在的点的话,这对点肯定不同时在那个\(\frac{2}{3}n\)的团中,也就是说,每次删点至少删掉一个外点,至多删掉一个内点 那么我们 ...

  8. 洛谷 P4301 [CQOI2013]新Nim游戏 解题报告

    P4301 [CQOI2013]新Nim游戏 题目描述 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴. ...

  9. Kerberos无约束委派的攻击和防御

    0x00 前言简介 当Active Directory首次与Windows 2000 Server一起发布时,Microsoft就提供了一种简单的机制来支持用户通过Kerberos对Web服务器进行身 ...

  10. Redis中国用户组|唯品会Redis cluster大规模生产实践

    嘉宾:陈群 很高兴有机会在Redis中国用户组给大家分享redis cluster的生产实践.目前在唯品会主要负责redis/hbase的运维和开发支持工作,也参与工具开发工作 Outline 一.生 ...