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++;
}
}
结束语
以上就是我学习到的内容,如果对您有帮助请多多支持我,如果哪里有问题欢迎大家在评论区积极讨论,我看到会及时回复。