ORB-SLAM2 单目部分技术路线(三)

图像金字塔

# 本部分代码主要位置:src/ORBextractor.cc

        在上一讲中,我们大概了解了tracking流程,那么其中最重要的流程,就是ORB特征提取器的建立,其中,给函数传入的参数包括:nFeatures:要提取的特征点数量;fScaleFactor:金字塔层次的尺度因子;nLevels:金字塔的层数;fIniThFAST:FAST角点检测的初始阈值;fMinThFAST:FAST角点检测的最小阈值,这几个值都是在提前设置过的配置文件中设置好的。

mpORBextractorLeft = new ORBextractor(nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);

 1. 金字塔参数初始化 

         我们进入ORB特征提取器的函数中,首先是对金字塔的相关初始化:

mvScaleFactor.resize(nlevels);
mvLevelSigma2.resize(nlevels);
mvScaleFactor[0] = 1.0f;
mvLevelSigma2[0] = 1.0f;
for (int i = 1; i < nlevels; i++) {
    mvScaleFactor[i] = mvScaleFactor[i - 1] * scaleFactor;
    mvLevelSigma2[i] = mvScaleFactor[i] * mvScaleFactor[i];
}

mvInvScaleFactor.resize(nlevels);
mvInvLevelSigma2.resize(nlevels);
for (int i = 0; i < nlevels; i++) {
    mvInvScaleFactor[i] = 1.0f / mvScaleFactor[i];
    mvInvLevelSigma2[i] = 1.0f / mvLevelSigma2[i];
}

mvImagePyramid.resize(nlevels);

         初始化中,mvImagePyramid是每一层金字塔的图像,mvScaleFactor是尺度因子的数组,对应mvLevelSigma2是尺度的平方数组,设置第0层就是最底层了,那么逐层往上,这个尺度因子逐步变大;为了简便运算,我们进而设置了尺度因子的逆数组,即尺度因子的倒数:mvInvScaleFactor与mvInvLevelSigma2,下面是一个图像金字塔的示意图象:

2. 计算特征点数量:

        先附上相应的代码:

mnFeaturesPerLevel.resize(nlevels);
float factor = 1.0f / scaleFactor;
float nDesiredFeaturesPerScale = nfeatures * (1 - factor) / (1 - (float)pow((double)factor, (double)nlevels));

int sumFeatures = 0;
for (int level = 0; level < nlevels - 1; level++) {
    mnFeaturesPerLevel[level] = cvRound(nDesiredFeaturesPerScale);
    sumFeatures += mnFeaturesPerLevel[level];
    nDesiredFeaturesPerScale *= factor;
}
mnFeaturesPerLevel[nlevels - 1] = std::max(nfeatures - sumFeatures, 0);

        nDesiredFeaturesPerScale表示在每个尺度上期望分配的特征点数量,这里是通过几何级数分配特征点数量的,想必在这里的代码中最难理解的也是这个部分,下面是一个大致思路:

         如何分配每层的特征点数目?

        根据金字塔图我们可以知道,金字塔层级越高,图像面积越小,对应的特征点数量也就越少。那么我们就想能否将图像特征点按照面积均摊到金字塔每层的图像上?

        假设第0层宽为W,长为L,缩放因子为s^2(这个其实就是之前已经定义过的factor),则金字塔总面积为:

        其中,C为最底层面积,则可以算出单位面积特征点数量以及第0层数量:

         进而,上一层的特征点数量上下一层的基础上乘缩放因子即可。同时,我们对已有的特征点进行计数,那么最顶层的特征点数量则是总特征点数量减去已有特征点数量。

3.  描述子初始化

        对于一个特征点,判断他是否与其他特征点相匹配的关键就是比较他周围的描述子,ORB-SLAM2中ORB特征由角点以及描述子组成,分别使用的是FAST角点(关键点)以及BRIEF描述子。角电的思想大概是如果一个像素与周围领域的像素相差较大,则他可能是角电;而描述子位于关键点周围,一般是二进制数,表示明暗关系。在ORB-SLAM2中,描述子由固定的256个点组成,最终得到128维的由0,1组成的向量,而这256个点又是用512个数表示,这里体现了其初始化过程,big_pattern_31_即是固定的描述子数组,这里将其最终存储到了pattern0中。

const int npoints = 512;
const Point* pattern0 = (const Point*)bit_pattern_31_;
std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));

4. 初始化用于方向计算的辅助数组 

        这里的初始化主要是为了后续建立灰度质心圆并满足旋转不变性做准备。这里相当于初始化了一个圆,并初始化了其u,v坐标,每一个v有一个对应的u值。

umax.resize(HALF_PATCH_SIZE + 1);

int v, v0, vmax = cvFloor(HALF_PATCH_SIZE * sqrt(2.f) / 2 + 1);
int vmin = cvCeil(HALF_PATCH_SIZE * sqrt(2.f) / 2);
const double hp2 = HALF_PATCH_SIZE * HALF_PATCH_SIZE;
for (v = 0; v <= vmax; ++v)
    umax[v] = cvRound(sqrt(hp2 - v * v));

for (v = HALF_PATCH_SIZE, v0 = 0; v >= vmin; --v) {
    while (umax[v0] == umax[v0 + 1])
        ++v0;
    umax[v] = v0;
    ++v0;
}

  

        上图就是uv对应的圆的大致示意。

### ORB-SLAM 系统架构 ORB-SLAM 是一种基于视觉的实时同步定位与地图构建(SLAM)系统,适用于单目、立体和RGB-D相机。该系统利用ORB( Oriented FAST and Rotated BRIEF )特征实现高效特征提取和匹配[^2]。 #### 架构组成 ORB-SLAM 的基本框架由大模块构成: 1. **跟踪 (Tracking)** 跟踪模块负责处理每一帧图像并估计摄像机姿态。此过程涉及初始化阶段,在初始几帧内建立局部地图;随后进入追踪状态,通过匹配当前帧中的特征点到已有地图上来更新位置信息。当遇到显著运动变化或光照条件改变时,可能会触发重定位机制以恢复丢失的姿态估计[^3]。 2. **本地建图 (Local Mapping)** 本地建图线程专注于创建和维护环境的地图模型。对于新观测到的关键帧,会执行角化操作来计算空间中未被记录过的路标位置,并将其加入全局地图数据库。此外还承担着优化现有地图结构的任务,比如剔除冗余数据以及修正可能存在的几何误差。 3. **回环检测 (Loop Closing)** 回环闭合用于识别机器人是否返回到了之前访问过的位置附近。一旦发现潜在循环路径,则启动专门算法验证假设并将相应调整应用至整个轨迹历史记录之中,从而消除累积漂移效应带来的偏差影响。这一环节至关重要,因为它能极大提高最终重建维场景的一致性和准确性。 ```mermaid graph TD; A[输入视频流] -->|提供给| B{跟踪}; B --> C[成功]; B --> D[失败/初始化]; C --> E[本地建图]; E --> F[回环检测]; F --> G[闭环校正]; D --> H[重新定位]; ``` 上述流程展示了 ORB-SLAM 如何运作:从接收摄像头传来的连续画面开始,经过一系列内部逻辑判断分支后完成各项核心功能——即跟随路线前进的同时绘制周围世界的样子,并且能够自动纠正因长时间运行而产生的细微错位现象。 #### 中文教程资源推荐 针对希望深入了解 ORB-SLAM 并获取中文资料的学习者而言,《视觉 SLAM 十四讲》是一本非常有价值的参考资料。这本书籍不仅涵盖了理论基础部分,而且提供了大量实践指导案例帮助读者更好地掌握相关技术要点。另外还有许多开源社区贡献者的博客文章和技术分享可以作为辅助阅读材料,例如关于 ORB-SLAM2 源码解析的文章就非常适合那些想要探索底层实现细节的人士参考学习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值