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

前言

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

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

函数声明

cpp 复制代码
void LocalMapping::MapPointCulling()

函数定义

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

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

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

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

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

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

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

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

cpp 复制代码
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++;
    }
}

结束语

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

相关推荐
量子-Alex11 分钟前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
轻口味13 分钟前
命名空间与模块化概述
开发语言·前端·javascript
吉大一菜鸡16 分钟前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
晓纪同学1 小时前
QT-简单视觉框架代码
开发语言·qt
威桑1 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans1 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手2 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#