目录

ORB-SLAM2源码学习:Initializer.cc:Initializer::CheckFundamental地图初始化——检查基础矩阵F并评分

前言

这部分函数是要对所有的基础矩阵F进行一个打分,比较得分,得分最高(误差最小)的选为最优的基础矩阵。

1.函数声明

cpp 复制代码
float Initializer::CheckFundamental(
    const cv::Mat &F21,             
    vector<bool> &vbMatchesInliers, 
    float sigma)            

2.函数定义

用特征点到对应极线的距离来衡量当前基础矩阵的好坏。

由对极约束得出基础矩阵恒等式:

其中:

由极线定义:

设置误差为点到对应极线的距离:

利用得分公式计算得分:

其中:thScore表示自由度为2的卡方分布在显著性水平为0.05时对应的临界域值。

cpp 复制代码
/*
 对给定的Fundamental matrix打分 与对给定的单应矩阵进行打分的方法一致(套路一致但评分机制不同)
 F21                       当前帧和参考帧之间的基础矩阵
 vbMatchesInliers          匹配的特征点对属于inliers的标记
 sigma                     方差,默认为1
 return float                        返回得分
 */
float Initializer::CheckFundamental(
    const cv::Mat &F21,             //当前帧和参考帧之间的基础矩阵
    vector<bool> &vbMatchesInliers, //匹配的特征点对属于inliers的标记
    float sigma)                    //方差
{
	// 获取匹配的特征点对的总对数
    const int N = mvMatches12.size();

	// Step 1 提取基础矩阵中的元素数据
    const float f11 = F21.at<float>(0,0);
    const float f12 = F21.at<float>(0,1);
    const float f13 = F21.at<float>(0,2);
    const float f21 = F21.at<float>(1,0);
    const float f22 = F21.at<float>(1,1);
    const float f23 = F21.at<float>(1,2);
    const float f31 = F21.at<float>(2,0);
    const float f32 = F21.at<float>(2,1);
    const float f33 = F21.at<float>(2,2);

	// 预分配空间
    vbMatchesInliers.resize(N);

	// 设置评分初始值(因为后面需要进行这个数值的累计)
    float score = 0;

    // 基于卡方检验计算出的阈值
	// 自由度为1的卡方分布,显著性水平为0.05,对应的临界阈值
    // 在点到直线距离的计算中,只涉及一个独立的几何变量------距离
    // 每次判断的是单个点是否满足极线约束,距离的分布统计符合卡方分布,且只有一个变量影响统计结果。
    const float th = 3.841;

    // 自由度为2的卡方分布,显著性水平为0.05,对应的临界阈值
    const float thScore = 5.991;

	// 信息矩阵,或 协方差矩阵的逆矩阵
    const float invSigmaSquare = 1.0/(sigma*sigma);


    // Step 2 计算img1 和 img2 在估计 F 时的score值
    for(int i=0; i<N; i++)
    {
		//默认为这对特征点是Inliers
        bool bIn = true;

	    // Step 2.1 提取参考帧和当前帧之间的特征匹配点对
        const cv::KeyPoint &kp1 = mvKeys1[mvMatches12[i].first];
        const cv::KeyPoint &kp2 = mvKeys2[mvMatches12[i].second];

		// 提取出特征点的坐标
        const float u1 = kp1.pt.x;
        const float v1 = kp1.pt.y;
        const float u2 = kp2.pt.x;
        const float v2 = kp2.pt.y;

        // Reprojection error in second image
        // Step 2.2 计算 img1 上的点在 img2 上投影得到的极线 l2 = F21 * p1 = (a2,b2,c2)
		const float a2 = f11*u1+f12*v1+f13;
        const float b2 = f21*u1+f22*v1+f23;
        const float c2 = f31*u1+f32*v1+f33;
    
        // Step 2.3 计算误差 e = (a * p2.x + b * p2.y + c) /  sqrt(a * a + b * b)
        const float num2 = a2*u2+b2*v2+c2;
        const float squareDist1 = num2*num2/(a2*a2+b2*b2);
        // 带权重误差
        const float chiSquare1 = squareDist1*invSigmaSquare;
		
        // Step 2.4 误差大于阈值就说明这个点是Outlier 
        // ? 为什么判断阈值用的 th(1自由度),计算得分用的thScore(2自由度)
        // ? 可能是为了和CheckHomography 得分统一?
        if(chiSquare1>th)
            bIn = false;
        else
            // 误差越大,得分越低
            score += thScore - chiSquare1;

        // 计算img2上的点在 img1 上投影得到的极线 l1= p2 * F21 = (a1,b1,c1)
        const float a1 = f11*u2+f21*v2+f31;
        const float b1 = f12*u2+f22*v2+f32;
        const float c1 = f13*u2+f23*v2+f33;

        // 计算误差 e = (a * p2.x + b * p2.y + c) /  sqrt(a * a + b * b)
        const float num1 = a1*u1+b1*v1+c1;
        const float squareDist2 = num1*num1/(a1*a1+b1*b1);

        // 带权重误差
        const float chiSquare2 = squareDist2*invSigmaSquare;

        // 误差大于阈值就说明这个点是Outlier 
        if(chiSquare2>th)
            bIn = false;
        else
            score += thScore - chiSquare2;
        
        // Step 2.5 保存结果
        if(bIn)
            vbMatchesInliers[i]=true;
        else
            vbMatchesInliers[i]=false;
    }
    //  返回评分
    return score;
}

结束语

以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
西红柿土豆丶10 分钟前
人脸考勤管理一体化系统(人脸识别系统,签到打卡)
python·深度学习·opencv·人脸识别·人脸识别系统·考勤管理系统·签到打卡
机器鱼11 分钟前
C++计算机视觉实战:100个实际案例分析
人工智能·计算机视觉
肖恩想要年薪百万17 分钟前
如何在idea中快速搭建一个Spring Boot项目?
java·数据库·spring boot·后端·学习·mysql·intellij-idea
yong158585534319 分钟前
C++ 获取一整行(一行)字符串并转换为数字
开发语言·c++
一大Cpp32 分钟前
随笔1 认识编译命令
linux·opencv·ubuntu
虾球xz43 分钟前
游戏引擎学习第205天
学习·游戏引擎
巷9551 小时前
OpenCV轮廓检测全面解析:从基础到高级应用
人工智能·opencv·计算机视觉
郭涤生1 小时前
Chapter 6: Concurrency in C++20_《C++20Get the details》_notes
开发语言·c++·笔记·c++20
White_Can1 小时前
《C++探幽:STL(string类源码的简易实现(上))》
开发语言·c++
朝阳同学2 小时前
C++中高精度运算问题
开发语言·c++