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;
}

结束语

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

相关推荐
十五年专注C++开发11 分钟前
cargs: 一个轻量级跨平台命令行参数解析库
linux·c++·windows·跨平台·命令行参数解析
宁静致远202111 分钟前
【C++设计模式】第二篇:策略模式(Strategy)--从基本介绍,内部原理、应用场景、使用方法,常见问题和解决方案进行深度解析
c++·设计模式·策略模式
·前路漫漫亦灿灿22 分钟前
C++-类型转换
开发语言·c++
肥肠可耐的西西公主24 分钟前
后端(fastAPI)学习笔记(CLASS 1):扩展基础
笔记·学习·fastapi
CHANG_THE_WORLD25 分钟前
C++ 并发编程指南 并发设计模式:Actor vs. CSP (生活场景版)
c++·设计模式·生活
mahuifa36 分钟前
C++(Qt)软件调试---bug排查记录(36)
c++·bug·软件调试
對玛祷至昏1 小时前
算法学习路径
学习·算法·排序算法
qq_386322695 小时前
华为网路设备学习-32(BGP协议 七)路由反射器与联邦
网络·学习
萘柰奈5 小时前
Unity学习----【进阶】Addressables(二)--加载资源与打包及更新
学习·unity
CV缝合救星5 小时前
【Arxiv 2025 预发行论文】重磅突破!STAR-DSSA 模块横空出世:显著性+拓扑双重加持,小目标、大场景统统拿下!
人工智能·深度学习·计算机视觉·目标跟踪·即插即用模块