当前位置: 首页 > article >正文

ORB-SLAM2源码学习:LocalMapping.cc: LocalMapping::MapPointCulling剔除不合格的地图点

前言

新增地图点需要经过比较严苛的筛选才能留下,只有这样才能提高定位和建图的准确性、控制地图建图规模、降低计算量。

新增地图点主要来自a.双目相机和RGB-D相机模式下的跟踪线程产生的地图点b.局部建图线程中关键帧之间生成的新的地图点。 

函数声明

void LocalMapping::MapPointCulling()

函数定义

地图点(即关键帧中生成的 3D 点)的删除条件

满足以下任意一个条件的地图点会被删除:

条件一:地图点的观测相机数量相对于预测相机数量的比例小于 25%。

解释:每个地图点在被创建时都有一个预计的观测相机数量,这些观测相机可以看到或检测到这个地图点。当实际观测到该地图点的相机数量小于预测数量的 25% 时,该地图点将被删除。这一条件的设立目的是删除那些在实际观测中少于预期的地图点,减少冗余数据。

条件二:从地图点建立开始,已经超过了 2 个关键帧,且该地图点的观测相机数未超过阈值 cnThObs。

cnThObs 的具体定义:对于单目相机,cnThObs = 2。对于双目或 RGB-D 相机,cnThObs = 3。

相机观测计数方法:每观测一次,观测相机数加 1。如果用双目或 RGB-D 相机观测一次,则相机数加 2。

解释:此条件设立是为了清除那些在创建后无法被足够多的相机观测到的地图点。当一个地图点建立后,如果经过了 2 个关键帧的时间周期,且观测到该点的相机数量仍不足,则说明该点的观测数据较少,可能并不是一个稳定的、可靠的地图点,因此会将其删除。这一操作有助于保持地图点的准确性和有效性。

void LocalMapping::MapPointCulling()
{
    // Check Recent Added MapPoints
    list<MapPoint*>::iterator lit = mlpRecentAddedMapPoints.begin();
    const unsigned long int nCurrentKFid = mpCurrentKeyFrame->mnId;

    // Step 1:根据相机类型设置不同的观测阈值
    int nThObs;
    if(mbMonocular)
        nThObs = 2;
    else
        nThObs = 3;
    const int cnThObs = nThObs;
	
	// Step 2:遍历检查新添加的地图点
    while(lit!=mlpRecentAddedMapPoints.end())
    {
        MapPoint* pMP = *lit;
        if(pMP->isBad())
        {
            // Step 2.1:已经是坏点的地图点仅从队列中删除
            lit = mlpRecentAddedMapPoints.erase(lit);
        }
        else if(pMP->GetFoundRatio()<0.25f)
        {
            // Step 2.2:跟踪到该地图点的帧数相比预计可观测到该地图点的帧数的比例小于25%,从地图中删除
            // (mnFound/mnVisible) < 25%
            // mnFound :地图点被多少帧(包括普通帧)看到,次数越多越好
            // mnVisible:地图点应该被看到的次数
            // (mnFound/mnVisible):对于大FOV镜头这个比例会高,对于窄FOV镜头这个比例会低
            pMP->SetBadFlag();
            lit = mlpRecentAddedMapPoints.erase(lit);
        }
        else if(((int)nCurrentKFid-(int)pMP->mnFirstKFid)>=2 && pMP->Observations()<=cnThObs)
        {
            // Step 2.3:从该点建立开始,到现在已经过了不小于2个关键帧
            // 但是观测到该点的相机数却不超过阈值cnThObs,从地图中删除
            pMP->SetBadFlag();
            lit = mlpRecentAddedMapPoints.erase(lit);
        }
        else if(((int)nCurrentKFid-(int)pMP->mnFirstKFid)>=3)
            // Step 2.4:从建立该点开始,已经过了3个关键帧而没有被剔除,则认为是质量高的点
            // 因此没有SetBadFlag(),仅从队列中删除
            lit = mlpRecentAddedMapPoints.erase(lit);
        else
            lit++;
    }
}

结束语

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


http://www.kler.cn/a/419250.html

相关文章:

  • 浪潮X86服务器NF5280、8480、5468、5270使用inter VROC Raid key给NVME磁盘做阵列
  • 【论文笔记】Towards Online Continuous Sign Language Recognition and Translation
  • cmake一些常用指令
  • 行列式与线性方程组解的关系
  • JAVA篇08 —— String类
  • C++学习日记---第14天(蓝桥杯备赛)
  • 使用 Docker 容器创建一个 Web 服务器:从入门到实践
  • 怎么选拔人才
  • MySQL--SQL优化
  • 私有库gitea安装
  • DRM(数字权限管理技术)防截屏录屏----ffmpeg安装
  • 图片预处理技术介绍4——降噪
  • VM+Ubuntu18.04+XSHELL+VSCode环境配置
  • 探索Scala:文本分析与文件操作的艺术
  • Ubuntu 22.04 离线安装软件包
  • PyTorch 模型转换为 ONNX 格式
  • LVS 负载均衡面试题及参考答案
  • 服务器命令行复制文件
  • Unity类银河战士恶魔城学习总结(P148 Main Menu主菜单)
  • 力扣112. 路径总和
  • 基于 SpringBoot 的致远汽车租赁系统
  • nuxt2 如何限制移动端手动缩放 safari meta失效解决方案
  • pytorch中的.clone() 和 .detach()
  • 解决docker 拉取镜像报错问题
  • Ubuntu20.04运行R-VIO2
  • ARIMA-神经网络混合模型在时间序列预测中的应用