通俗易懂理解ORBSLAM2跟踪模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通俗易懂理解ORBSLAM2跟踪模块相关的知识,希望对你有一定的参考价值。

参考技术A

[1] 计算机视觉Life ORB-SLAM2源码讲解专题四:单目Tracking线程源码

帧间跟踪

(1)正常模式:

(2)出现意外:

(3)实在不行,垂死挣扎:

局部地图跟踪

关键帧判断和产生

EPNP的使用原则 好像只有重定位才用到。
比如匀速运动模型或者是参考关键帧模型,都不用,因为他们的匹配点比较好。

纯跟踪是什么意思? 地图更不更新是什么意思? 为什么有一个产生地图点的事。
纯视觉里程计,没有产生关键帧,所以没有局部建图,所以没有新的地图点产生。只有匹配地图点使得某帧对应的地图点不为NULL。

关键帧确定的原则是什么 :
当前帧对应的地图点被观测的数量小于最新关键帧对应的地图点被观测的数量的90%并且当前帧对应的地图点被观测的数量小于15

词袋匹配具体利用词袋后,然后怎么做?****跟踪中他们的共性是什么
先缩小范围(词袋、重投影),再计算描述子距离,得到最佳匹配,再用旋转直方图进行剔除误匹配。

跟踪局部地图,出了提升位姿的准确性,对地图点有什么影响呢 ,增加地图点? 局部地图的局部关键帧选择,重复了怎么办???
不增加地图点。只有匹配地图点使得某帧对应的地图点不为NULL。有一个判重按钮。

Tracking线程的局部地图跟踪是什么
Tracking线程的局部地图跟踪,首先每次更新当前帧的局部关键帧,再由局部关键帧得到局部地图点。而当前帧的局部关键帧是:(1)和当前帧共视(有共同地图点)的关键帧,(2)以及(1)中每个关键帧的最强共视关键帧10帧,(3)还有(1)中的的孩子和父亲关键帧统统拉入伙。然后通过局部关键帧得到局部地图点,用于Tracking线程的位姿跟踪。

1.使用匀速运动模型进行特征点匹配?
将上一帧的 每个非NULL地图点 投影到当前帧进行特征点匹配,在地图点的投影点附近进行找到特征点集合,然后从中找到描述子间距离最小的特征点,将该地图点作为该特征点对应的地图点,然后把他们的旋转角度差存入旋转直方图,用于去除错误的匹配。
匹配步骤:缩小范围(重投影);利用描述子距离寻找最佳匹配点;利用旋转直方图去除误匹配
匹配点数量大于阈值进行pose only BA.
2.单目追踪过程中地图点从哪里来,即单目地图点补充?
单目初始化+局部地图中地图点创建。
3.为什么不PNP呢?
[1]匀速运动模型进行特征点匹配,如果有足够数量的匹配,直接pose only BA, PnP没有必要了,PnP还得RANSAC,得到的结果也不一定使得所有匹配点重投影误差最小,还不如直接Pose Only BA.
[2]如果相机的运动问题使得匀速运动模型不成立,那么怎么办?得到的匹配点就不是很多, 比如重定位模式下 ,这时候需要PnP为Pose Only BA 提供初始值了。
4.如何进行pose only BA?一元边?
一元边:就一个优化变量
进行4次优化
[1]每次优化10次,误差太大(基于卡方分布的自由度得到的,比如自由度为2, 服从高斯分布,误差小于1个像素,这个事发生的概率超过95%对应有一个值),设为外点,不优化
[2]前2次需要鲁棒核函数,其他不需要,因为误差已经明显下降了
[3]返回内点数量

上一帧的地图点是怎么得到的呢?通过特征点匹配得到的。
初始化成功之后,什么情况下进行三角化呢?对于单目而言,那就只有在local mapping创建地图点环节。

对单目而言,没有。

描述子最优距离和描述子次优距离,有的时候需要判断2者差别明显,匹配才是比较可信的。
[1]匀速运动模型=>重投影搜索,只有 最优

[2]追踪参考帧,重定位=>词袋搜索, 最优和次优 ,比例:0.7

[3]初始化=>小窗口搜索, 最优和次优 ,比例比较高,0.9

上一帧的参考关键帧 就是最近的关键帧

local mapping中当前关键帧的参考关键帧:和当前帧共视程度最高的关键帧
tracking 中的参考关键帧是 最新的关键帧

重定位的时候,通过检测当前帧和那个关键帧最接近,来确定当前的位置和姿态
主要就是利用词袋数据,在已有的关键帧中查找和当前帧最接近的关键帧集合。
主要过程:
// 得到和当前帧有共同单词的关键帧集合,得到共同单词数最多的数量
// 将大于共同单词数阈值的关键帧放入一个集合
// 对于集合中的每一个,找他的最强共视关键帧10帧,
// 得到该组中的累计得分和得分最高的关键帧(这个组的代表)
// 累计得分大于阈值的组并把该组的代表放入候选关键帧集合中

垂死挣扎!

有关键帧的地图点和当前帧的地图点,当前帧的地图点初始化都是NULL,如果当前帧和关键帧特征匹配上的话,那么他们的地图点是同一个,将关键帧对应的地图点赋值给普通帧的地图点。

匹配步骤:缩小范围(词袋);利用描述子距离寻找最佳匹配点和次佳匹配点;利用旋转直方图去除误匹配

// (1)更新局部关键帧 mvpLocalKeyFrames 和局部地图点 mvpLocalMapPoints

Tracking线程的局部地图跟踪,首先每次更新当前帧的局部关键帧,再由局部关键帧得到局部地图点。而当前帧的局部关键帧是:(1)和当前帧共视(有共同地图点)的关键帧,(2)以及(1)中每个关键帧的最强共视关键帧10帧,(3)还有(1)中的的孩子和父亲关键帧统统拉入伙。然后通过局部关键帧得到局部地图点,用于Tracking线程的位姿跟踪。

// (2)在局部地图中查找与当前帧匹配的MapPoints

// (3)位姿优化

(1)遍历当前帧的所有地图点,对isBad的地图点进行置为NULL。
(2)对于局部地图点,判断局部地图点是否在视野中,并进行统计数量。
(3)对视野范围内的地图点进行重投影匹配。

(1)把地图点转换到当前帧相机坐标系下,如果深度为负,那么返回false.
(2)把地图点转换到当前帧像素坐标系下,如果超出图像边界,那么返回false.
(3)如果地图点和当前相机位置的距离不在最大和最小范围内,返回false
(4)计算从当前相机指向地图点的方向和地图点的平均观测方向大于60度,返回false
(5)根据地图点到光心的距离预测地图点一个尺度,仿照特征点金字塔层级

Tracking中的参考关键帧就是最新的关键帧 。参考关键帧对应的地图点(该地图点被多次观测,比如2或者3)的数量
mnMatchesInliers:
当前帧对应的地图点被观测(大于0就行)的数量
thRefRatio :单目0.9,频繁插入

结论: 当前帧对应的地图点被观测的数量小于最新关键帧对应的地图点被观测的数量的90%并且 当前帧对应的地图点被观测的数量小于15 ,插入。还有就是间隔多少帧插入一下。其他不care.

no care:
ratioMap:1
thMapRatio: 0.35

【译】理解LSTM(通俗易懂版)

参考技术A

人对一个问题的思考不会完全从头开始。比如你在阅读本片文章的时,你会根据之前理解过的信息来理解下面看到的文字。在理解当前文字的时候,你并不会忘记之前看过的文字,从头思考当前文字的含义。

传统的神经网络并不能做到这一点,这是在对这种序列信息(如语音)进行预测时的一个缺点。比如你想对电影中的每个片段去做事件分类,传统的神经网络是很难通过利用前面的事件信息来对后面事件进行分类。

而循环神经网络(下面简称RNNs)可以通过不停的将信息循环操作,保证信息持续存在,从而解决上述问题。RNNs如下图所示

可以看出A是一组神经网络(可以理解为一个网络的自循环),它的工作是不停的接收 并且输出 。从图中可以看出A允许将信息不停的再内部循环,这样使得它可以保证每一步的计算都保存以前的信息。

这样讲可能还是有点晕,更好的理解方式,也是很多文章的做法,将RNNs的自循环结构展开,像是将同一个网络复制并连成一条线的结构,将自身提取的信息传递给下一个继承者,如下图所示。

这种链式的结构揭示了RNNs与序列和列表类型的数据密切相关。好像他们生来就是为了处理序列类型数据的。

谁说不是呢!在过去的几年里,RNNs在语音识别、文字建模、翻译、字幕等领域有很成功的应用。在Andrej Karpathy写的博客 The Unreasonable Effectiveness of Recurrent Neural Networks 中讨论了RNNs取得的惊人成果,这里就不详细讨论了。

很对成功的案例都有一个共性,就是都用了一种叫LSTMs的特殊的RNNs网络结构。下面就来看看什么是LSTMs。

从之前的描述可以看出来,RNNs理论上是可以将以前的信息与当前的任务进行连接,例如使用以前的视频帧来帮助网络理解当前帧。如果RNNs能做到这一点,那将会是非常的有用。但是他们能做到这点吗?答案是不一定。

有时候我们需要利用近期的信息来执行来处理当前的任务。例如,考虑用一个语言模型通过利用以前的文字信息来预测下一个文字。如果我们需要预测“the clouds are in the sky”这句话的最后一个字,我们不需要其他的信息,通过前面的语境就能知道最后一个字应该是sky。在这种情况下,相关信息与需要该信息的位置距离较近,RNNs能够学习利用以前的信息来对当前任务进行相应的操作。如下图所示通过输入的 信息来预测出

假设现在有个更为复杂的任务,考虑到下面这句话“I grew up in France… I speak fluent French.”,现在需要语言模型通过现有以前的文字信息预测该句话的最后一个字。通过以前文字语境可以预测出最后一个字是某种语言,但是要猜测出French,要根据之前的France语境。这样的任务,不同之前,因为这次的有用信息与需要进行处理信息的地方之间的距离较远,这样容易导致RNNs不能学习到有用的信息,最终推导的任务可能失败。如下图所示。

理论上RNNs是能够处理这种“长依赖”问题的。通过调参来解决这种问题。但是在实践过程中RNNs无法学习到这种特征。 Hochreiter (1991) [German] 和 Bengio, et al. (1994) 深入研究过为什么RNNs没法学习到这种特征。

幸好LSTMs这种特殊的RNNs是没有这个问题的。

Long Short Term Memory networks(以下简称LSTMs),一种特殊的RNN网络,该网络设计出来是为了解决长依赖问题。该网络由 Hochreiter & Schmidhuber (1997) 引入,并有许多人对其进行了改进和普及。他们的工作被用来解决了各种各样的问题,直到目前还被广泛应用。

所有循环神经网络都具有神经网络的重复模块链的形式。 在标准的RNN中,该重复模块将具有非常简单的结构,例如单个tanh层。标准的RNN网络如下图所示

LSTMs也具有这种链式结构,但是它的重复单元不同于标准RNN网络里的单元只有一个网络层,它的内部有四个网络层。LSTMs的结构如下图所示。

在解释LSTMs的详细结构时先定义一下图中各个符号的含义,符号包括下面几种

图中黄色类似于CNN里的激活函数操作,粉色圆圈表示点操作,单箭头表示数据流向,箭头合并表示向量的合并(concat)操作,箭头分叉表示向量的拷贝操作

LSTMs的核心是细胞状态,用贯穿细胞的水平线表示。

细胞状态像传送带一样。它贯穿整个细胞却只有很少的分支,这样能保证信息不变的流过整个RNNs。细胞状态如下图所示

LSTM网络能通过一种被称为门的结构对细胞状态进行删除或者添加信息。

门能够有选择性的决定让哪些信息通过。其实门的结构很简单,就是一个sigmoid层和一个点乘操作的组合。如下图所示

因为sigmoid层的输出是0-1的值,这代表有多少信息能够流过sigmoid层。0表示都不能通过,1表示都能通过。

一个LSTM里面包含三个门来控制细胞状态。

前面提到LSTM由三个门来控制细胞状态,这三个门分别称为忘记门、输入门和输出门。下面一个一个的来讲述。

LSTM的第一步就是决定细胞状态需要丢弃哪些信息。这部分操作是通过一个称为忘记门的sigmoid单元来处理的。它通过查看 和 信息来输出一个0-1之间的向量,该向量里面的0-1值表示细胞状态 中的哪些信息保留或丢弃多少。0表示不保留,1表示都保留。忘记门如下图所示。

下一步是决定给细胞状态添加哪些新的信息。这一步又分为两个步骤,首先,利用 和 通过一个称为输入门的操作来决定更新哪些信息。然后利用 和 通过一个tanh层得到新的候选细胞信息 ,这些信息可能会被更新到细胞信息中。这两步描述如下图所示。

下面将更新旧的细胞信息 ,变为新的细胞信息 。更新的规则就是通过忘记门选择忘记旧细胞信息的一部分,通过输入门选择添加候选细胞信息 的一部分得到新的细胞信息 。更新操作如下图所示

更新完细胞状态后需要根据输入的 和 来判断输出细胞的哪些状态特征,这里需要将输入经过一个称为输出门的sigmoid层得到判断条件,然后将细胞状态经过tanh层得到一个-1~1之间值的向量,该向量与输出门得到的判断条件相乘就得到了最终该RNN单元的输出。该步骤如下图所示

还是拿语言模型来举例说明,在预测动词形式的时候,我们需要通过输入的主语是单数还是复数来推断输出门输出的预测动词是单数形式还是复数形式。

之前描述的LSTM结构是最为普通的。在实际的文章中LSTM的结构存在各种变式,虽然变化都不会太大,但是也值得一提。
其中一个很受欢迎的变式由 Gers & Schmidhuber (2000) 提出,它在LSTM的结构中加入了“peephole connections.”结构,peephole connections结构的作用是允许各个门结构能够看到细胞信息,具体如下图所示。

上图描绘的是所有门都能看到细胞信息,还有一些变式是在其中的某些门引入细胞信息。

还有一种变式是在忘记门与输入门之间引入一个耦合。不同于之前的LSTM结构,忘记门和输入门是独立的,这个变式是在忘记门删除历史信息的位置加入新的信息,在加入新信息的位置删除旧信息。该结构如下图所示。

一种比其他形式变化更为显著的LSTM变式是由 Cho, et al. (2014) 提出的门循环单元(GRU)。它将忘记门和输入门合并成一个新的门,称为更新门。GRU还有一个门称为重置门。如下图所示

其中重置门为上图中前面那个门,决定了如何将新的输入信息与前面的记忆相结合。更新门为上图中后面那个门,定义了前面记忆保存到当前时间步的量。 由于该变式的简单有效,后来被广泛应用。

这里介绍的只是一些较为有名的LSTM变式,关于LSTM的变式其实还有很多种,像 Yao, et al. (2015) 提出的Depth Gated RNNs。还有其他用于解决长依赖问题的方法,如由 Koutnik, et al. (2014) 提出的 Clockwork RNNs。

至于哪种变式效果最好?各种差异对LSTM的影响有多少?这些问题 Greff, et al. (2015) 做了一些对比,结论是他们基本是一样的。 Jozefowicz, et al. (2015) 测试了一万多种RNN结构,发现在某些指定任务上有些变式还是由于标准LSTMs的。

之前也提到过RNNs取得了不错的成绩,这些成绩很多是基于LSTMs来做的,说明LSTMs适用于大部分的序列场景应用。
一般文章写法会堆一堆公式吓唬人,希望本文一步一步的拆分能有助于大家的理解。
LSTMs对于RNNs的使用是一大进步。那么现在还有个问题,是否还有更大的进步?对于很多研究者来说,但是是肯定的,那就是attention的问世。attention的思想是让RNN在每一步挑选信息的时候都能从更大的信息集里面挑选出有用信息。例如,利用RNN模型为一帧图片生成字母,它将会选择图片有用的部分来得到有用的输入,从而生成有效的输出。事实上, Xu, et al. (2015) 已经这么做了,如果你想更深入的了解attention,这会是一个不错的开始。attention方向还有一些振奋人心的研究,但还有很多东西等待探索......

在RNN领域attention并不是唯一一个可以研究的点。比如 Kalchbrenner, et al. (2015) 提出的Grid LSTMs, Gregor, et al. (2015) , Chung, et al. (2015) , 和 Bayer & Osendorfer (2015) 将RNNs用于生成模型的研究都非常有意思。
在过去几年RNNs方面的研究非常的多,相信以后的研究成果也会更为丰富。

同原文

欢迎加入OCR交流群:785515057(此群已满)
欢迎加入OCR交流群2:826714963

原文链接

以上是关于通俗易懂理解ORBSLAM2跟踪模块的主要内容,如果未能解决你的问题,请参考以下文章

【译】理解LSTM(通俗易懂版)

十分钟入门 Kafka,通俗易懂地理解分布式消息系统!!

Python-Thread(通俗易懂)

脚本(script)——通俗易懂去理解

麻烦用比较通俗易懂的语言帮我介绍一下JMS,中间件,webService,WSDL以及SOAP之间的关系.

Java:最通俗易懂地理解0-1背包问题