ORB-SLAM2 --- LocalMapping::KeyFrameCulling函数

news2024/11/26 14:53:50

目录

1.函数作用

2.code 

3.函数解析 


1.函数作用

        检测当前关键帧在共视图中的关键帧,根据地图点在共视图中的冗余程度剔除该共视关键帧。

        冗余关键帧的判定:90%以上的地图点能被其他关键帧(至少3个)观测到。

2.code 

/**
 * @brief 检测当前关键帧在共视图中的关键帧,根据地图点在共视图中的冗余程度剔除该共视关键帧
 * 冗余关键帧的判定:90%以上的地图点能被其他关键帧(至少3个)观测到
 */
void LocalMapping::KeyFrameCulling()
{

    // 该函数里变量层层深入,这里列一下:
    // mpCurrentKeyFrame:当前关键帧,本程序就是判断它是否需要删除
    // pKF: mpCurrentKeyFrame的某一个共视关键帧
    // vpMapPoints:pKF对应的所有地图点
    // pMP:vpMapPoints中的某个地图点
    // observations:所有能观测到pMP的关键帧
    // pKFi:observations中的某个关键帧
    // scaleLeveli:pKFi的金字塔尺度
    // scaleLevel:pKF的金字塔尺度

    // Step 1:根据共视图提取当前关键帧的所有共视关键帧
    vector<KeyFrame*> vpLocalKeyFrames = mpCurrentKeyFrame->GetVectorCovisibleKeyFrames();

    // 对所有的共视关键帧进行遍历
    for(vector<KeyFrame*>::iterator vit=vpLocalKeyFrames.begin(), vend=vpLocalKeyFrames.end(); vit!=vend; vit++)
    {
        KeyFrame* pKF = *vit;
        // 第1个关键帧不能删除,跳过
        if(pKF->mnId==0)
            continue;
        // Step 2:提取每个共视关键帧的地图点
        const vector<MapPoint*> vpMapPoints = pKF->GetMapPointMatches();

        // 记录某个点被观测次数,后面并未使用
        int nObs = 3;                     
        // 观测次数阈值,默认为3
        const int thObs=nObs;               
        // 记录冗余观测点的数目
        int nRedundantObservations=0;     
                                                                                      
        int nMPs=0;            

        // Step 3:遍历该共视关键帧的所有地图点,其中能被其它至少3个关键帧观测到的地图点为冗余地图点
        for(size_t i=0, iend=vpMapPoints.size(); i<iend; i++)
        {
            MapPoint* pMP = vpMapPoints[i];
            if(pMP)
            {
                if(!pMP->isBad())
                {
                    if(!mbMonocular)
                    {
                        // 对于双目或RGB-D,仅考虑近处(不超过基线的40倍 )的地图点
                        if(pKF->mvDepth[i]>pKF->mThDepth || pKF->mvDepth[i]<0)
                            continue;
                    }

                    nMPs++;
                    // pMP->Observations() 是观测到该地图点的相机总数目(单目1,双目2)
                    if(pMP->Observations()>thObs)
                    {
                        const int &scaleLevel = pKF->mvKeysUn[i].octave;
                        // Observation存储的是可以看到该地图点的所有关键帧的集合
                        const map<KeyFrame*, size_t> observations = pMP->GetObservations();

                        int nObs=0;
                        // 遍历观测到该地图点的关键帧
                        for(map<KeyFrame*, size_t>::const_iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++)
                        {
                            KeyFrame* pKFi = mit->first;
                            if(pKFi==pKF)
                                continue;
                            const int &scaleLeveli = pKFi->mvKeysUn[mit->second].octave;

                            // 尺度约束:为什么pKF 尺度+1 要大于等于 pKFi 尺度?
                            // 回答:因为同样或更低金字塔层级的地图点更准确
                            if(scaleLeveli<=scaleLevel+1)
                            {
                                nObs++;
                                // 已经找到3个满足条件的关键帧,就停止不找了
                                if(nObs>=thObs)
                                    break;
                            }
                        }
                        // 地图点至少被3个关键帧观测到,就记录为冗余点,更新冗余点计数数目
                        if(nObs>=thObs)
                        {
                            nRedundantObservations++;
                        }
                    }
                }
            }
        }

        // Step 4:如果该关键帧90%以上的有效地图点被判断为冗余的,则认为该关键帧是冗余的,需要删除该关键帧
        if(nRedundantObservations>0.9*nMPs)
            pKF->SetBadFlag();
    }
}

3.函数解析 

        先获取当前关键帧mpCurrentKeyFrame的一级共视关键帧vpLocalKeyFrames

        对所有的共视关键帧vpLocalKeyFrames进行遍历:

        规定第一个关键帧不能删除(初始化的第一帧),提取每个共视关键帧的地图点vpMapPointsvpLocalKeyFrames的地图点),遍历每一个地图点:

        对于双目或RGB-D,仅考虑近处(不超过基线的40倍 )的地图点。

        如果该地图点的被观测次数超过阈值thObs,获取能看见该地图点的关键帧的集合observations(map<KeyFrame*, size_t>型遍变量,存储着能观测到该地图点的所有关键帧和该地图点在该关键帧的索引),遍历观测到该地图点的关键帧,其中能被其它至少3个关键帧观测到的地图点为冗余地图点。

        如果该关键帧90%以上的有效地图点被判断为冗余的,则认为该关键帧是冗余的,需要删除该关键帧。

ORB-SLAM2 --- KeyFrame::SetBadFlag函数解析icon-default.png?t=MBR7https://blog.csdn.net/qq_41694024/article/details/128570430

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/143475.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第七次作业部分

文章目录1、获取根分区剩余大小2、获取当前机器ip地址3、统计出apache的access.log中访问量最多的5个IP4、打印/etc/passwd中UID大于500的用户名和uid5、/etc/passwd 中匹配包含root或net或ucp的任意行6、处理以下文件内容,将域名取出并根据域名进行计数排序处理(百度搜狐面试题…

透过现象看本质,我找到了Netty粘包与半包的这几种解决方案。

1、粘包与半包 啥也不说了&#xff0c;直接上代码是不是有点不太友好&#xff0c;我所谓了&#xff0c;都快过年了&#xff0c;还要啥自行车 我上来就是一段代码猛如虎 1.1 服务器代码 public class StudyServer {static final Logger log LoggerFactory.getLogger(StudyS…

ORB-SLAM2 --- ORBmatcher::Fuse函数 --- 局部建图线程调用重载版

目录 1.函数作用 2.code 3.函数解析 1.函数作用 将参数一的关键帧的地图点与参数二的地图点集合进行融合。 将地图点投影到关键帧中进行匹配和融合&#xff1b;融合策略如下&#xff1a; 1.如果地图点能匹配关键帧的特征点&#xff0c;并且该点有对应的地图点&…

六、k8s Pod控制器详解

1 Pod控制器介绍 Pod是kubernetes的最小管理单元&#xff0c;在kubernetes中&#xff0c;按照pod的创建方式可以将其分为两类&#xff1a; 自主式pod&#xff1a;kubernetes直接创建出来的Pod&#xff0c;这种pod删除后就没有了&#xff0c;也不会重建控制器创建的pod&#x…

异常处理部分

文章目录一、异常概述及体系结构分类ErrorException异常的体系结构异常处理&#xff1a;抓抛模型异常处理机制一&#xff1a;try-catch-finallyfinally的使用异常处理机制一&#xff1a;throws异常类型如何选择两种方式手动生成异常对象如何定义自定义的异常类一、异常概述及体…

JVM学习- - -虚拟机栈详解

前言&#xff1a;今天学长带领大家走进JVM学习&#xff0c;让我们一起来学习认识虚拟机栈吧~ 目录 1 虚拟机栈概述 虚拟机栈出现的背景 初步印象 内存中的栈和堆 虚拟机栈基本内容 栈的优点 2 栈的存储单位 栈中存储什么&#xff1f; 栈运行原理 栈帧的内部结构 3 局…

【云原生】k8s之存储卷

内容预知 前言 1.emptyDir存储卷 2.hostPath存储卷 3.nfs共享存储卷 4. PVC 和 PV的静态存储卷 4.1 pv和pvc的介绍 4.2 pvc 和pv的创建过程及销毁过程 4.3 对pv的操作指导 4.4 静态创建pv和pvc资源由pod运用过程 步骤一&#xff1a;在NFS主机上创建共享目录&#xff0c;…

采用rknn-toolkit导出rknn模型并部署在rock3a-rk3568芯片 上全流程

因工作需要&#xff0c;需要将目标检测模型 部署在开发板上。在走了很多弯路后 找到一个成功的案例并记载下来 这里说一下我现有的硬件设备 。 我是购买的RADXA的rock3a开发板 搭载的soc是rk3568 这是开发板的正面图&#xff0c;因为瑞芯微针对计算机视觉中的目标检测模型有一…

Java IO流 - 缓冲流的详细使用介绍

文章目录缓冲流缓冲流概述字节缓冲流字符缓存流缓冲流 缓冲流概述 缓冲流介绍: 缓冲流也称为高效流、或者高级流。之前学习的字节流和字符流可以称为原始流。 作用&#xff1a;缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能 缓冲流分为: 字节缓存输入流、字节…

做个测试工具

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

uniapp中引入vant Weapp

Vant Weapp官&#xff1a;https://vant-contrib.gitee.io/vant-weapp/#/home 步骤一&#xff1a;下载vant组件插件 从github上下载该插件https://github.com/youzan/vant-weapp 只要这个dist文件夹&#xff0c;把dist重命名为vant&#xff1b; 步骤二&#xff1a; 与pages…

301-295- 至少有 K 个重复字符的最长子串-0105

题解 本题使用分治策略,如果某个字符的出现次数小于k,则用它将数组分开,再把每个子数组组委参数递归执行.如果都大于k,则将该字符串的长度返回. 用一个字符分割,往深了分割各子字符串,这个字符分割完成,使用另一个字符进行分割,而不是一次用多个字符进行分割.这个题递归有些绕…

电脑怎么重装系统?小白也能轻松掌握这些方法

重新安装计算机系统有两种原因&#xff1a;一种是计算机系统可以正常使用&#xff0c;但是电脑比较卡&#xff0c;为了提高它的运行速度&#xff0c;所以想要通过重新安装系统来解决这个问题&#xff1b;另一种原因是计算机系统文件丢失&#xff0c;系统出现蓝屏&#xff0c;或…

MQ概念简介

队列管理器 队列管理器是MQ系统中最上层的一个概念&#xff0c;由它为我们提供基于队列的消息服务。 2) 消息 在MQ中&#xff0c;我们把应用程序交由MQ传输的数据定义为消息&#xff0c;我们可以定义消息的内容并对消息进行广义的理解&#xff0c;比如&#xff1a;用户的各种类…

机器学习100天(二十九):029 K折交叉验证

机器学习100天,今天讲的是:K 折交叉验证! 《机器学习100天》完整目录:目录 机器学习中,我们常会遇到一个问题,就是超参数的选择,超参数就是机器学习算法中的调优参数,比如上一节 K 近邻算法中的 K 值。K 折交叉验证就是帮助我们选择最优的超参数。 首先,介绍一下简…

FPGA并行计算可编程芯片

玩转Zynq可以使用Vivado创建一个FPGA工程。什么是FPGA前言自FPGA诞生以来&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;就引起了人们的关注。在1980年代中期&#xff0c;Ross Freeman和他的同事从Zilog购买了该技术&#xff0c;并创建了Xilinx&#xff0c;目标是A…

基于Java+SpringBoot+vue+node.js实现自行车租赁平台管理系统

基于JavaSpringBootvuenode.js实现自行车租赁平台管理系统 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目录基于JavaSp…

netmap: UDP 协议栈的实现

文章目录1、获取以太网数据1.1、netmap 原理1.2、netmap 环境搭建2、udp 协议栈的实现2.1、以太网帧2.2、ip 协议2.3、udp 协议2.4、问题分析3、ARP 协议的实现4、icmp 协议的实现5、netmap 代码实现1、获取以太网数据 自定义协议栈&#xff0c;需要获取原始的以太网数据&…

第50问:从连接判断应用访问数据库的异常行为

问 我发现应用有一根访问数据库的连接有异常流量&#xff0c;如何判断是应用哪个逻辑导致了异常行为 实验 先起锅烧一个数据库实例&#xff1a; 我们用 mysqlslap 作为应用&#xff1a; 假设在 MySQL 中&#xff0c;我们认为这根连接有异常流量&#xff1a; 通过 ss 找到这根…

阿里一面 | 说说你对 MySQL 死锁的理解

1、什么是死锁&#xff1f; 死锁指的是在两个或两个以上不同的进程或线程中&#xff0c;由于存在共同资源的竞争或进程&#xff08;或线程&#xff09;间的通讯而导致各个线程间相互挂起等待&#xff0c;如果没有外力作用&#xff0c;最终会引发整个系统崩溃。 2、Mysql出现死…