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 初始化流程
- 1.1 单应性矩阵(Homography Matrix)
-
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() 执行初始化操作。
估算相机的姿态和平移参数,并通过对特征点实施三角测量来生成初始地图基准点。
这些结果将被存储在变量 Rcw、tcw 和 vbTriangulated 中。
/* 定义估计相机的旋转量、平移量和对特征点进行三角化形成初始的地图点 */
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以执行地图初始化任务,并根据三角化的结果生成地图点
谢谢
