Advertisement

SLAM ORB-SLAM2(11)单目初始化

阅读量:

SLAM ORB-SLAM2(11)单目初始化通过以下步骤完成:
初始化工作:

  • 建立坐标系并估计初始位姿。
  • 仅凭尺度缺失需建立基础尺度。
  • 针对平面和非平面场景提供两种几何模型:单应矩阵(Homography Matrix)和基础矩阵(Fundamental Matrix)。
  • 选择两个线程计算这两种模型,并根据启发式信息选择较合适的一种。
    关键几何模型:
  • 单应矩阵用于描述平面投影变换。
  • 基础矩阵用于描述两个视图之间的几何约束。
  • 本质矩阵结合旋转和平移信息进行分解。
    初始化过程:
  • 在类Tracking的成员函数Track()中完成地图初始化。
  • 当状态尚未进行时启动MonocularInitialization()函数。
  • 使用当前帧作为参考帧,并通过匹配特征点对估算相对运动和初始地图点。
  • 建立世界坐标系并完成地图的初始构建。
    业务流程:
  • 创建单目初始化器并判断连续帧的特征点数目。
  • 在两帧间找匹配的特征点对并估算相对运动和平移量。
  • 使用三角化方法形成初始地图点,并建立世界坐标系完成地图构建。

SLAM ORB-SLAM2(11)单目初始化

  • 1. 初始化阶段

    • 1.1 单应性矩阵(Homography Matrix)
      • 1.2 基础性矩阵(Fundamental Matrix)
      • 1.3 核心性矩阵(Essential Matrix)
      • 1.4 初始化流程
  • 2. 业务流程

      • 2.1. 初始化单目校准模块
      • 2.2. 计算当前帧与上一帧之间的关键点数量
      • 2.3. 建立两帧之间的特征对应关系
      • 2.4. 估算两帧间的相对运动参数,并建立初始的地图坐标基准
      • 2.5. 构建统一的世界坐标基准系统

1. 初始化工作

初始化的核心步骤包括设定坐标系框架、估计机器人起始姿态以及构建地图模型。在单目相机系统中,则因缺乏深度信息而必须先确定基准尺度;基于此基准所构建的地图将为后续的所有地图重建提供统一的基础。

在平面场景下以及其对应的齐次坐标空间中,在非平面场景下以及其对应的四维空间中

该系统将在两个线程中同步地处理两个待处理的模型。接着,该系统将基于一些启发式的判断标准选择较为合适的模型。


1.1. 单应矩阵(Homography Matrix)

单应矩阵是一个 3×3 矩阵,用于描述 平面 投影变换

在这里插入图片描述

当两个视图(图像)之间的场景是一个平面几何形状或 仅包含旋转和平移
单应矩阵可用于将这两个视图关联起来

给定两个图像中的一对对应点 x{x}',单应矩阵 H 满足:{x}'=Hx

单应矩阵常用于图像拼接(Stitching)、图像矫正(Rectification)等应用


1.2. 基础矩阵(Fundamental Matrix)

本质矩阵是一个 3 \times 3 矩阵,并且其秩为2;它被用来表示两个不同视角下对应点之间的几何关系。

在这里插入图片描述

如果使用两幅图像分别由不同相机或相机位置拍摄生成,则基础矩阵可用于确定该图像中某一点在另一幅图中的对应位置。

在两幅图像中对应的点 x{x}'(使用齐次坐标表示)作为前提条件下,在这种情况下 基础矩阵 F 必须满足以下方程的形式:${x}'^{T} F x = 0”。

基础矩阵表示两个摄像头间的空间信息,并未包含相机参数(如各摄像头的成像中心位置等)。

」是图像经过矩阵变换之后的空间维度


1.3. 本质矩阵(Essential Matrix)

该本质矩阵也可被视为一个3×3、秩为2的特殊矩阵,在形式上与基础矩阵极为相似。值得注意的是,在不考虑相机内参数的前提下,在标准化图像坐标系下进行应用。通过SVD分解方法可得:

E = \mathbf{R} \mathbf{t}

其中,
\mathbf{R}代表旋转矩阵,
\mathbf{t}代表平移向量,
这反映了相机的旋转和平移变换。

基础矩阵F无法单独提取这些数据,因为它包含了内部参数以及旋转和位移的信息


1.4. 初始化过程

在文章《SLAM ORB-SLAM2(10)轨迹跟踪过程》中可以看到,在类Tracking的成员函数Track()中实现了地图初始化的过程。

复制代码
    /** * @brief 轨迹跟踪任务函数
     */
    void Tracking::Track()
    {
    if(mState==NO_IMAGES_YET)
    {
        mState = NOT_INITIALIZED;
    }
    
    mLastProcessedState=mState;
    
    // Get Map Mutex -> Map cannot be changed
    /* 地图对象上锁 */
    unique_lock<mutex> lock(mpMap->mMutexMapUpdate);
    
    if(mState==NOT_INITIALIZED)
    {
        /* 初始化轨迹跟踪任务 */
        if(mSensor==System::STEREO || mSensor==System::RGBD)
            StereoInitialization();
        else
            MonocularInitialization();
    
        mpFrameDrawer->Update(this);
    
        if(mState!=OK)
            return;
    }
    ...

当检测到状态mState未完成初始化时,在系统中执行相应的校准操作以确保后续工作的顺利进行。在图像处理模块中,默认情况下会启用单目相机的自动校准功能,并基于当前配置参数选择合适的优化策略以提高校准效率和精度。

其将选择两帧图像,这两帧图像需满足具有充足的匹配特征点和非零视差值,并将相对较早的那个作为基准帧进行初始化设置
通过解算得到两帧图像下相机间的相对位姿变换矩阵,并以此基准帧相机坐标系为基准建立世界坐标系

在选定的坐标系中,相机初始姿态对应于恒等变换矩阵,在该状态下没有发生旋转或平移.系统会通过三角化匹配得到特征点,并估计相对空间位置坐标;在此过程中,默认采用参考帧中特征点深度值的中值作为基准来确定基础尺度.基于上述计算结果和基准尺度信息,系统随后构建地图上的各个地图点,并最终形成初始的地图框架.


2. 业务流程


2.1. 创建单目初始化器

复制代码
    /** * @brief 单目初始化函数
     */
    void Tracking::MonocularInitialization()
    {
    
    if (!mpInitializer)
    {
        // Set Reference Frame
        /* 当图像的特征点数量超过了100个,才以当前帧作为参考帧,进行初始化操作 */
        if (mCurrentFrame.mvKeys.size() > 100)
        {
            mInitialFrame = Frame(mCurrentFrame); /* 暂时将当前帧标记为初始帧 */
            mLastFrame = Frame(mCurrentFrame);    /* 记录当前帧 */
    
            /* 记录当前帧所有特征点 */
            mvbPrevMatched.resize(mCurrentFrame.mvKeysUn.size());
            for (size_t i = 0; i < mCurrentFrame.mvKeysUn.size(); i++)
                mvbPrevMatched[i] = mCurrentFrame.mvKeysUn[i].pt;
    
            /* 删除可能已有的初始化器 */
            if (mpInitializer)
                delete mpInitializer;
    
            /* 以当前帧为参数构造初始化器 */
            mpInitializer = new Initializer(mCurrentFrame, 1.0, 200);
    
            /* 初始化时前两帧的匹配关系(匹配点的id),-1表示目前没有任何匹配 */
            fill(mvIniMatches.begin(), mvIniMatches.end(), -1);
    
            return;
        }
    }

成员变量 mpInitializer 专门用于类 Tracking 实现单目相机初始化功能。在函数执行初始步骤前会对该成员变量进行检查:如果是空指针,则使用当前帧作为参考帧来创建 mpInitializer 对象。为了确保初始化质量的可靠性,在图像特征点数量超过100个时才执行初始化操作。

在初始化 mpInitializer 之前,请您先把当前帧暂时标记为初始帧 mInitialFrame ,并同时使用另一个变量 mLastFrame 来记录下来作为参考依据。

此外还需要获取矫正畸变后的特征点并存储至容器 mvbPrevMatched 然后建立初始化器 并将所有在 mvIniMatches 中的特征点匹配值设置至-1 以表明它们尚未完成配对


2.2. 判断连续帧的特征点数目

复制代码
    /* 已创建初始化器时,判断新图像特征点数目数量是否超过100,
       即只有连续两帧的特征点个数都大于100时,才能继续进行初始化过程 */
    if ((int)mCurrentFrame.mvKeys.size() <= 100)
    {
    /* 销毁 mpInitializer 重新记录初始帧 */
    delete mpInitializer;
    mpInitializer = static_cast<Initializer *>(NULL);
    fill(mvIniMatches.begin(), mvIniMatches.end(), -1);
    return;
    }

如果该初始化对象已预先实例化,则表明已有基准参考框架。
在新一帧中进行特征点数量检查时,请注意仅当两个连续帧中的特征点数量均超过100时才可继续执行初始化流程。
否则将终止 mpInitializer 并重新设定初始框架。


2.3. 在两帧中找匹配的特征点对

复制代码
    /* 构建了一个特征点匹配器 */
    ORBmatcher matcher(0.9, true);
    int nmatches = matcher.SearchForInitialization(mInitialFrame, mCurrentFrame, mvbPrevMatched, mvIniMatches, 100);
    
    /* 如果匹配点数量少于 100 个,认为当前帧和初始帧不适合初始化 */
    if (nmatches < 100)
    {
    /* 销毁 mpInitializer 重新记录初始帧 */
    delete mpInitializer;
    mpInitializer = static_cast<Initializer *>(NULL);
    return;
    }

2.4. 估算两帧间相对运动并初始地图点

由对象 mpInitializer 的接口 Initialize() 执行初始化操作。
估算相机的姿态和平移参数,并通过对特征点实施三角测量来生成初始地图基准点。
这些结果将被存储在变量 RcwtcwvbTriangulated 中。

复制代码
    /* 定义估计相机的旋转量、平移量和对特征点进行三角化形成初始的地图点 */
    cv::Mat Rcw;                 // Current Camera Rotation
    cv::Mat tcw;                 // Current Camera Translation
    vector<bool> vbTriangulated; // Triangulated Correspondences (mvIniMatches)
    
    /* 计算基础矩阵和单应矩阵,选取两帧之间最佳的相对姿态,并进行三角化得到初始地图点 */
    if (mpInitializer->Initialize(mCurrentFrame, mvIniMatches, Rcw, tcw, mvIniP3D, vbTriangulated))
    {
    /* 剔除匹配点对中没有成功三角化的点 */
    for (size_t i = 0, iend = mvIniMatches.size(); i < iend; i++)
    {
        if (mvIniMatches[i] >= 0 && !vbTriangulated[i])
        {
            mvIniMatches[i] = -1;
            nmatches--;
        }
    }
    ...
    }

在本系统中,vbTriangulated 被定义为与每个 mvIniMatches 一一对应的布尔变量。该变量用于指示对应特征点对的三角化结果。随后将排除所有未完成三角化的特征点对。

该函数 Referencing 《SLAM ORB-SLAM2(12)估算两帧间相对运动并初始地图点》


2.5. 建立世界坐标系

基于之前的计算结果,我们成功获得了当前帧相对于参考帧的相机变换关系.在此时,我们可以将参考帧中的相机位姿视为坐标原点,从而建立世界坐标系.对于初始帧,我们将其Homogeneous矩阵初始化为单位阵,并通过刚刚估计出的Rotation矩阵和平移向量来构建当前帧对应的Homogeneous矩阵.

复制代码
    /* 建立世界坐标系,设定初始帧的齐次矩阵为单位阵 */
    mInitialFrame.SetPose(cv::Mat::eye(4, 4, CV_32F));
    
    /* 用刚刚估计的旋转矩阵和平移向量构建当前帧的齐次矩阵 */
    cv::Mat Tcw = cv::Mat::eye(4, 4, CV_32F);
    Rcw.copyTo(Tcw.rowRange(0, 3).colRange(0, 3));
    tcw.copyTo(Tcw.rowRange(0, 3).col(3));
    mCurrentFrame.SetPose(Tcw);
    
    /* 创建初始化地图点 */
    CreateInitialMapMonocular();

在末尾调用函数CreateInitialMapMonocular以执行地图初始化任务,并根据三角化的结果生成地图点


谢谢

全部评论 (0)

还没有任何评论哟~