| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 人工智能 -> (01)ORB-SLAM2源码无死角解析-(34) 跟踪线程→恒速模型跟踪当前普通帧TrackWithMotionModel() -> 正文阅读 |
|
[人工智能](01)ORB-SLAM2源码无死角解析-(34) 跟踪线程→恒速模型跟踪当前普通帧TrackWithMotionModel() |
本人讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解的(01)ORB-SLAM2源码无死角解析-接如下: 有兴趣的朋友可以加微信 17575010159 相互讨论技术 - 文末公众号也可关注 ? 一、前言在上一篇博客中,讲解了如何通过关键帧来估算当前帧的位姿,但是其最重要的核心函数 Optimizer::PoseOptimization(&mCurrentFrame) 没有进行讲解,这个知识点暂且搁置一下,先来看看恒速模型跟踪普通帧是如何实现的,恒速模型跟踪也叫做视觉里程计(不是很明白的朋友可以百度一下)。使用这种方式追踪呢,其假设相机移动的速度是均匀的,进一步利用微分的实现,就是上一帧变换的位姿与当前帧变换位姿是相同(或者说接近相同)。 如果两帧之间的速度(位姿变化)大致相同,另外两帧之间的时间间隔是比较小,一般为几十毫秒, 这里假设连续的三帧分别为 f 1 , f 2 , f 3 f1,f2,f3 f1,f2,f3。基于前面的推论, f 1 f1 f1 到 f 2 f2 f2,与 f 2 f2 f2 到 f 3 f3 f3 的位姿变换大致相同即 R 21 ≈ R 32 R_{21}\approx R_{32} R21?≈R32?, t 21 ≈ t 32 t_{21}\approx t_{32} t21?≈t32?(注意,这里使用的是约等于)。如果已知 R 21 R_{21} R21?,先令 R 21 = R 32 R_{21}= R_{32} R21?=R32?, t 21 = t 32 t_{21}=t_{32} t21?=t32?。那么 f 2 f_2 f2? 的一个特征点 p 2 p_2 p2? 根据 R 32 , t 32 R_{32},t_{32} R32?,t32? 就能映射到 f 3 f3 f3 中为 p 3 ′ p'_3 p3′?。这里就需要注意了,通常情况 p 2 p_2 p2? 与 p 3 ′ p'_3 p3′? 不是匹配的特征点对,但是与 p 2 p_2 p2? 匹配的特征代 p 3 p_3 p3? 肯定就在 p 3 ′ p'_3 p3′? 的附近。根据这里原理,对 p 3 ′ p'_3 p3′? 周边的像素进行搜索,找到与 p 2 p_2 p2? 匹配的特征点 p 3 p_3 p3?。 或者这样说大家还不是很明确,那么请看图示如下: ? 二、代码流程通过 一、前言 对 恒速模型跟踪当前普通帧 进行了简单的原理介绍,代码为src/Tracking.cc中的Tracking::UpdateLastFrame() 函数,下面是其实现流程:
(
01
)
:
\color{blue}{(01)}:
(01): 调用 UpdateLastFrame() 函数更新上一帧的位姿,源码运行的过程中保存关键帧于mpReferenceKF变量中,但是并没有把所有视频帧都保存于缓存中。通过追踪函数 TrackReferenceKeyFrame(), TrackWithMotionModel() 或者 Relocalization() 计算出位姿之后,其并没有马上赋值,而运行到下一帧才对当前帧的位姿进行赋值。另外 TrackReferenceKeyFrame() 函数并没有调用 UpdateLastFrame(), 因为只有在刚完成初始化,或者恒速跟踪失败,才进行参考帧跟踪。 ( 02 ) : \color{blue}{(02)}: (02): 根据之前估算的速度(或者说位姿变换),用恒速模型得到当前帧的初始位姿。代表速度的变量为 mVelocity。该变量在 Tracking::Track() 函数中被赋值。如果当前帧追踪成功,那么速度被赋值为 mVelocity = mCurrentFrame.mTcw*LastTwc。其中mCurrentFrame.mTcw相机坐标系变换到当前帧坐标系(弈可以理解为当前帧相机在世界坐标系下的位姿),LastTwc表示上一帧世界相机坐标系到世界坐标的变换矩阵。所以mCurrentFrame.mTcw*LastTwc 表示上一帧相机位姿到当前帧位姿的变换矩阵。 ( 03 ) : \color{blue}{(03)}: (03): 设置特征匹配的搜索半径(以像素为单位),因为单目相机存在尺度漂移,所以搜索范围会大一些。然后利用重投影进行匹配,如果没有匹配点不够则扩大搜索路径重来一次。通过重投影进行特征点匹配的函数为SearchByProjection(),稍等会进行详细讲解。 ( 04 ) : \color{blue}{(04)}: (04): 利用3D-2D投影关系,优化当前帧位姿。其核心为代码为 Optimizer::PoseOptimization(&mCurrentFrame);该函数比较重要,在上一章节已经提及到,该篇博客不进行讲解,后面再为大家进行分析。 ( 05 ) : \color{blue}{(05)}: (05): 该步骤十分简单,主要就是根据判断地图点是否为外点,如果为外点,则清除他的所有关系。普配数目也同时更新。如果追踪匹配地图点超过10个则认为匹配成功。另外,纯定位模式下,如果追踪地图点非常少,那么 mbVO 标志就会定位。 其上 UpdateLastFrame() 与 SearchByProjection() 两个函数都是比较复杂。下面首先针对这两个函数进行讲解,然后再对TrackWithMotionModel() 进行整体的讲解(后面有代码注解)。 ? 三、UpdateLastFrame()该函数的实现位于 src/Tracking.cc 文件中,实现逻辑如下:
计算相对姿态
T
c
r
=
T
c
w
?
T
w
r
,
T
w
r
=
T
r
w
?
1
Tcr = Tcw * Twr, Twr = Trw^{-1}
Tcr=Tcw?Twr,Twr=Trw?1。
T
c
r
Tcr
Tcr 表示参考帧到当前帧的变换矩阵,然后赋值给成员变量 mlRelativeFramePoses。②如果当前帧的位姿为空(也就是说明当前帧没有跟踪到),那么 mlRelativeFramePoses 使用上一帧的值。 ( 02 ) : \color{blue}{(02)}: (02): 如果上一阵为关键帧,或者是单目的情况,则退出该函数。因为针对双目或rgbd相机,还会为上一帧生成临时地图点(普通帧生成的地图点使用过后会被删除掉)。生成过程如下:获得到上一帧的所有特征点(不一定是地图点),循环判断该点的深度是否有效,对有效特征点依照深度进行排序。然后再次进入循环,如果这个点对应在上一帧中的地图点没有,或者创建后就没有被观测到,那么就生成一个临时的地图点,地图点被创建后就没有被观测,认为不靠谱,也需要重新创建。创建新的地图点,主要使用反射影函数UnprojectStereo()。完成之后,加入到上一帧的地图点之中。 其具体代码实现如下:
? 四、SearchByProjection()下面再来分析 SearchByProjection() 函数,该函数位于 ORBmatcher.cc 文件中,该函数实现的就是 一、前言 中的图示过程。具体如下: ( 01 ) : \color{blue}{(01)}: (01): 建立旋转差直方图,用于检测旋转一致性,最后会剔除不一致的匹配。
(
02
)
:
\color{blue}{(02)}:
(02): 首先获当前帧相机位姿
R
c
w
,
t
c
w
R_{cw},t_{cw}
Rcw?,tcw?,以及上一帧的位姿
R
l
w
,
t
l
w
R_{lw},t_{lw}
Rlw?,tlw?,然后令变换矩阵如下:
(
03
)
:
\color{blue}{(03)}:
(03): 对上一帧的每一个地图点,通过相机投影模型,得到得到投影到当前帧的像素坐标。获取上一帧中地图点对应二维特征点所在的金字塔层级,根据相机的前后前进方向来判断搜索尺度范围。 ( 04 ) : \color{blue}{(04)}: (04): 达到缩小搜索特征匹配范围目的之后,则进行两帧之间的特征点配对, 如果最佳匹配距离要小于设定阈值。则认为匹配成功,最后再计算匹配点旋转角度差所在的直方图,进行旋转一致检测,剔除不一致的匹配。 其具体代码实现如下:
? 五、TrackWithMotionModel()了解 UpdateLastFrame() 与 SearchByProjection() 函数之后,最后再来看看,TrackWithMotionModel() 函数,其实现于 src/Tracking.cc 文件中:
? 六、源码注释通过该篇博客,已经非常详细的分析了 TrackWithMotionModel() 。同时对 UpdateLastFrame() 与 SearchByProjection() 进行了详细的讲解。另外还有一个要点,就是如何计算出当前帧相对于上一帧相机的平移向量,并且根据该向量去判断相机处于前进还是后退状态。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 2:36:28- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |