详谈ORB-SLAM2的单目初始化器Initializer

单目初始化器Initializer类,这个类只用于单目初始化,因为这是ORB-SLAM里遗留的一个类,也是祖传代码,双目和RGBD相机只需要一帧就能初始化,因为双目和RGBD相机拍到的点都是有信息的,但是单目相机就不一定了,单目相机必须至少有两副图像才能初始化,对单目初始化器来说有两个帧,一个是参考帧,另一个是当前帧,这是连续的两帧。

一、各成员变量/函数

成员变量名中:1代表参考帧(reference frame)中特征点编号,2代表当前帧(current frame)中特征点编号
在这里插入图片描述

各成员函数/变量访问控制意义
vectorcv::KeyPoint mvKeys1private参考帧(reference frame)中的特征点
vectorcv::KeyPoint mvKeys2private当前帧(current frame)中的特征点
vector<pair<int,int>> mvMatches12private从参考帧到当前帧的匹配特征点对
vector mvbMatched1private参考帧特征点是否在当前帧存在匹配特征点
cv::Mat mKprivate相机内参
float mSigma, mSigma2private重投影误差阈值及其平方
int mMaxIterationsprivateRANSAC迭代次数
vector<vector<size_t>> mvSetsprivate二维容器N✖8
每一层保存RANSAC计算H和F矩阵所需的八对点

二、初始化函数: Initialize()

在参考帧创建Initializer对象,并且把创建参考的帧,在当前帧就是参考帧临近的下一帧,在这个帧里调用Initialize这个函数,就是把当前两个帧之间进行特征点匹配,然后计算f矩阵和h矩阵。单目相机初始化有两种方法:单应矩阵和基础矩阵。
在这里插入图片描述
首先设置RANSAC算法用到的点对,单目相机初始化有两种途径,而实际上在初始化成功之前那个矩阵演算出来的结果是准确的,所以使用暴力算法,把两个矩阵都解算出来,对两个矩阵根据冲突点误差计算得分,哪个矩阵的冲突点误差较小(得分比较高),就是用其恢复运动,如果恢复的特征点数目足够多视差角足够大,就算初始化成功(实际上如果恢复100个特征点视差角在比较可靠的情况下认为是恢复成功的)。

bool Initializer::Initialize(const Frame &CurrentFrame,
                             const vector<int> &vMatches12,
                             cv::Mat &R21, cv::Mat &t21,
                             vector<cv::Point3f> &vP3D,
                             vector<bool> &vbTriangulated) {

    // 初始化器Initializer对象创建时就已指定mvKeys1,调用本函数只需指定mvKeys2即可
    mvKeys2 = CurrentFrame.mvKeysUn;		// current frame中的特征点
    mvMatches12.reserve(mvKeys2.size());
    mvbMatched1.resize(mvKeys1.size());

    // step1. 将vMatches12拷贝到mvMatches12,mvMatches12只保存匹配上的特征点对
    for (size_t i = 0, iend = vMatches12.size(); i < iend; i++) {
        if (vMatches12[i] >= 0) {
            mvMatches12.push_back(make_pair(i, vMatches12[i]));
            mvbMatched1[i] = true;
        } else
            mvbMatched1[i] = false;
    }

	// step2. 准备RANSAC运算中需要的特征点对
    const int N = mvMatches12.size();
    vector<size_t> vAllIndices;
    for (int i = 0; i < N; i++) {
        vAllIndices.push_back(i);
    }
    mvSets = vector<vector<size_t> >(mMaxIterations, vector<size_t>(8, 0));
    for (int it = 0; it < mMaxIterations; it++) {
    	vector<size_t> vAvailableIndices = vAllIndices;
        for (size_t j = 0; j < 8; j++) {
            int randi = DUtils::Random::RandomInt(0, vAvailableIndices.size() - 1);
            int idx = vAvailableIndices[randi];
            mvSets[it][j] = idx;
            vAvailableIndices[randi] = vAvailableIndices.back();
            vAvailableIndices.pop_back();
        }
    }

	// step3. 计算F矩阵和H矩阵及其置信程度
    vector<bool> vbMatchesInliersH, vbMatchesInliersF;
    float SH, SF;
    cv::Mat H, F;

    thread threadH(&Initializer::FindHomography, this, ref(vbMatchesInliersH), ref(SH), ref(H));
    thread threadF(&Initializer::FindFundamental, this, ref(vbMatchesInliersF), ref(SF), ref(F));
    threadH.join();
    threadF.join();

	// step4. 根据比分计算使用哪个矩阵恢复运动
    float RH = SH / (SH + SF); 
    if (RH > 0.40)
        return ReconstructH(vbMatchesInliersH, H, mK, R21, t21, vP3D, vbTriangulated, 1.0, 50);
    else
        return ReconstructF(vbMatchesInliersF, F, mK, R21, t21, vP3D, vbTriangulated, 1.0, 50);
}

此博客参考ncepu_Chen的《5小时让你假装大概看懂ORB-SLAM2源码》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客范儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值