ORB-LSAM2:ComputeKeyPointsOctTree()提取特征:maxY = iniY + hCell + 6 为怎么是+6而不是+3?

news/2024/5/11 1:31:20/文章来源:https://blog.csdn.net/weixin_58045467/article/details/130881104

如标题所示,本博客主要讲述

void ORBextractor::ComputeKeyPointsOctTree(vector<vector<KeyPoint>> &allKeypoints){}函数中maxY = iniY + hCell + 6 为怎么是+6而不是+3?

为了连续性,会介绍一下ComputeKeyPointsOctTree函数,参考博客:参考链接

 (如果对这个函数很熟悉,可以直接跳到第二部分

一: ComputeKeyPointsOctTree函数介绍

 1.这个函数要做什么

将每层图像金字塔图像分成一个个小块、并对对每一块用FAST算法提取特征点,由于提取的特征点数目肯定很多,我们需要按照ORBExtrator构造函数中要求的每层应该提取的特征点数目进行特征点筛选并分散特征点(离散化特征点并让特征点分布均匀),得到最终所有图像金字塔提取到的关键点,并且求出这些特征点的角度信息。

我们定义了双层的vector容器存储所有的特征点,注意此处为二维的vector,第一维存储的是金字塔的层数,第二维存储的是那一层金字塔图像里提取的所有特征点。
    vector < vector<KeyPoint> > allKeypoints; 
    然后我们调用函数使用四叉树的方式计算每层图像的特征点并进行分配。回忆一下,我们是要将配置文件规定的特征点数目分配到各个金字塔层中,我们在上篇文章已经讲述了怎么把nFeatures个特征点分配到nLevels中,然而只是规定了数目,具体怎么分布没定,再通俗易懂的说,上一步(下面链接)我们只是创建了金字塔规定了每层金字塔分配多少,但它还是个空金字塔,这个函数我们将此空金字塔填满!

ORB-SLAM2 ---- ORBextractor::ComputePyramid函数_Courage2022的博客-CSDN博客

 2.循环变量的定义及三层循环

 2.1 level循环的minBorderX、minBorderY、maxBorderX、maxBorderY

         我们定义了第一层(对图像金字塔的每一个level )循环变量minBorderX、minBorderY、maxBorderX、maxBorderY,如下图所示:

 因此图像的坐标边界就是原图像扩充了3个像素值,为什么扩充像素值上篇文章我已经说过,不再赘述! 

 [注]:这里的小黑色方块表示图像,红色方块表示在图像基础上向外扩展了3个像素值,为的是在图像边界的像素也有机会提取到关键点。

2.2 level循环的vToDistributeKeys、width 、height、nCols、nRows、wCell、hCell

 

  [注]:这里的width 、height为上图红色方块的;nCols、nRows表示图像块cell在行,和列上分别有多少个;wCell、hCell图像块cell所占的像素行数和列数。

2.3 第二层第三层遍历中的iniX、maxX、iniY、maxY

        假设我们第一次循环,各变量如下图所示:

        那为什么要加6呢?还是因为边缘匹配特征点的缘故,我们在图像外面加个3像素的壳子、确保边缘的部分可以提取出特征点! (这里是参考博客里的解释,我觉得不是很清晰,解释这里就是写这篇博客的目的,下面讲)

 

3.三个循环做了什么

        第一层for循环:算出每一层的循环遍变量、供下面两层使用

        第二层for循环:对每一行进行遍历,算出初始与最大行坐标,上一层的maxY和下一层的iniY如图所示,这样是因为有6的缘故。

         此外,如果初始化的iniY大于边界-3,说明已经超过图像边界了,为什么是-3呢,因为我们用FAST提取关键点时为了避免边界无法提取的情况,要在外面加上个半径为3的外壳,这也是为什么加6的原因。如果iniY大于边界-3的话,那就说明壳子到边界了。

        此外,如果该网格的最大Y坐标超越了边界坐标,就让最大的Y坐标变成边界坐标。

        列的遍历也是如此。

        在最内层循环中,我们用一个容器vector<cv::KeyPoint> vKeysCell存储当前网格提取出的特征点。调用opencv的内置函数提取特征点。
 

二:maxY = iniY + hCell + 6 为怎么是+6而不是+3? 

 先看代码:

// 计算进行特征点提取的图像区域尺寸
const float width = (maxBorderX - minBorderX);
const float height = (maxBorderY - minBorderY);

 上面两行代码表示的是上面提到的红色方块,即真实图像边界扩展来3个像素边界的图像(后续成为:扩展图像)。然后对扩展图像分块:

// 计算网格在当前层的图像有的行数和列数
const int nCols = width / W;
const int nRows = height / W;
// 计算每个图像网格所占的像素行数和列数
const int wCell = ceil(width / nCols);
const int hCell = ceil(height / nRows);

 随后两个for循环就是对图像块的个数进行遍历:

// 开始遍历图像网格,还是以行开始遍历的
for (int i = 0; i < nRows; i++)
{const float iniY = minBorderY + i * hCell;float maxY = iniY + hCell + 6;// 开始列的遍历for (int j = 0; j < nCols; j++){...}
}

解释:

按照这个代码流程,很容易让人误解为将扩展图像分为30x30的小图像块,并且分别对小图像块提取关键点...,这样想就一直不明白+6的意思了...     

因为FAST提取关键点时为了避免边界无法提取的情况,要在外面加上个半径为3的外壳,所以 送入FAST()函数中的图像块大小为36x36。这就是+6的目的是,为了保证,在FAST()函数中参与提取关键点的是每个30x30的真实图像的图像块。 

如果这样写代码:将真实图像分为30x30的图像块,对每个图像块都扩展一次3个像素的边界,然后送入FAST()函数中提取关键点,就不会误解了,但是会更多消耗计算资源。这就是+6的目的了

图片示例:

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PMP课堂模拟题目及解析(第13期)

121. 项目经理、团队成员以及若干干系人共同参与一次风险研讨会。已经根据风险管理计划生成并提供一份风险报告。若要为各个项目风险进行优先级排序&#xff0c;现在必须执行哪一项分析&#xff1f; A. 定量风险分析 B. 根本原因分析 C. 偏差分析 D. 定性风险分析 122. …

软件系统三基座之一:权限管理

软件系统三基座包含&#xff1a;权限管理、组织架构、用户管理。 何为基座&#xff0c;即是有了这些基础&#xff0c;任一相关的“建筑”就能逐步搭建起来。 万丈高楼平地起 一、为什么要权限管理 权限管理&#xff0c;一般指根据系统设置的安全规则或者安全策略&#xff0c;…

报表控件FastReport使用指南-在Ubuntu LTS中创建PDF文档

FastReport 是功能齐全的报表控件&#xff0c;可以帮助开发者可以快速并高效地为.NET&#xff0c;VCL&#xff0c;COM&#xff0c;ActiveX应用程序添加报表支持&#xff0c;由于其独特的编程原则&#xff0c;现在已经成为了Delphi平台最优秀的报表控件&#xff0c;支持将编程开…

jvm之JMX

写在前面 本文来看先jmx相关内容。 1&#xff1a;jmx介绍 jvm在运行的过程中有很多的信息&#xff0c;比如堆内存&#xff0c;线程数&#xff0c;加载的类信息&#xff0c;CPU的使用量等&#xff0c;如果我们想要将这些信息暴漏让外界获取&#xff0c;该怎么做呢?此时就需要…

池州控股集团财务共享项目启动啦!

近日&#xff0c;由用友网络承建的池州市投资控股集团有限公司财务共享项目启动会成功举办&#xff0c;也标志着池州控股集团财务共享项目正式启动&#xff01;池州控股集团总经理刘俊、用友国资事业部总经理汪发清及其他相关专家和项目组主要成员参加了此次启动会。 池州投控集…

档案馆空气质量在线3D监控系统温湿度方案

档案馆库房八防温湿度空气质量一体化解决方案 档案库房是档案事业发展的基石&#xff0c;其主要任务是集中保管国家机构及个人等在各种形式下形成的具有一定价值和保存价值的各种载体档案&#xff0c;主要包括文书档案、科技档案、会计档案、人事档案、实物档案等。随着我国经济…

Node版本管理器nvm的安装与使用

前言&#xff1a; 多项目新旧项目管理的时候&#xff0c;往往与依赖不同的node版本&#xff0c;不同的版本对其他依赖的安装有一定的影响&#xff0c;因此我们需要对node的版本进行方便快捷管理和切换&#xff0c;如果直接卸载重装对应版本&#xff0c;切换项目再次卸载重装明显…

【泛微ecology_oracle】如何把查询到的单列人力资源id合并成多人力资源格式

如何把查询到的单列人力资源id合并成多人力资源格式 在泛微ecology中&#xff0c;单列人力资源id合并成多人力资源的使用场景在泛微ecology中&#xff0c;在数据库里人员姓名存储形式那如何实现人力资源字段合并多人力资源字段呢&#xff1f; 在泛微ecology中&#xff0c;单列人…

Rancher添加集群报错:Etcd Cluster is not healthy

原因&#xff1a; 有一台虚拟机在升级内核失败后&#xff0c;回滚至快照。但由于快照版本太老旧&#xff0c;和当前的rancher版本不匹配&#xff0c;服务器上的agent等需要清楚后&#xff0c;重新在rancher添加集群&#xff1b;但是只删除了rancher镜像以及agent相关容器&#…

开源开放 生态共建 | openKylin社区单位会员突破200家!

当前&#xff0c;开放、协作、共享的开源模式已成为全球软件技术和产业创新的主导&#xff0c;也为信息技术国产自主化提供了强大助力。openKylin作为中国桌面操作系统开源社区&#xff0c;以聚焦桌面操作系统根技术为核心、以孵化相关领域关键项目为目标、以布道开源文化为抓手…

关闭linux kernel内核的启动log在控制台的输出

要关闭Linux内核的启动日志&#xff0c;你可以通过以下方法之一进行操作&#xff1a; 1. 通过引导加载器配置&#xff1a; 打开引导加载器的配置文件&#xff0c;如GRUB的配置文件 /boot/grub/grub.cfg。 在内核的启动行&#xff08;以 “linux” 或 “kernel” 开头&#xf…

[论文评析]C-Mixup: Improving Generalization in Regression, NeurIPS,2022

C-Mixup: Improving Generalization in Regression 前言C-MixupReferences 前言 Mixup方法是针对分类任务的, 这篇方法相当于时提出了regression版本的Mixup, 实验证实能够大幅提升在regression task上的泛化能力. C-Mixup 是否可以把Mixup直接用于Regression task呢? 在原…

这可能是最全面的Java学习路线了

大家好&#xff0c;我是大彬~ 我本科学的不是计算机&#xff0c;大四开始自学Java&#xff0c;并且拿到了几个互联网中大厂的offer。在学习Java这方面还是比较有经验的&#xff0c;下面我来分享下我整理的Java自学路线。 在这里也提醒学弟学妹们&#xff0c;要尽早确定以后的…

数字档案馆建设指南

数字档案馆建设指南 目 录 1.总体要求 2.管理系统功能要求 3.应用系统开发和服务平台构建 4.数字档案资源建设 5.保障体系建设 1.总体要求 1.1概述 数字档案馆是指各级各类档案馆为适应信息社会日益增长的对档案信息资源管理、利用需求&#xff0c;运用现代信息技术对数字…

【问题记录】postgreSQL使用默认密码导致kdevtmpfsi挖矿病毒注入

起因 postgreSQL我做错了这几件事情 开启了全部IP登陆权限postgreSQL用的是默认用户名和密码用户postgres也没有设置密码&#xff0c;直接用su - postgres就能登陆 不知道是什么原理&#xff0c;反正服务器被侵入&#xff0c;并且注入了病毒文件 1. 基本信息排查 linux服务器…

Kafka实时数据即席查询应用与实践

作者&#xff1a;vivo 互联网搜索团队- Deng Jie Kafka中的实时数据是以Topic的概念进行分类存储&#xff0c;而Topic的数据是有一定时效性的&#xff0c;比如保存24小时、36小时、48小时等。而在定位一些实时数据的Case时&#xff0c;如果没有对实时数据进行历史归档&#xff…

用Typescript 的方式封装Vue3的表单绑定,支持防抖等功能。

Vue3 的父子组件传值、绑定表单数据、UI库的二次封装、防抖等&#xff0c;想来大家都很熟悉了&#xff0c;本篇介绍一种使用 Typescript 的方式进行统一的封装的方法。 基础使用方法 Vue3对于表单的绑定提供了一种简单的方式&#xff1a;v-model。对于使用者来说非常方便&…

镜像二叉树和求二叉树最大深度(java)

镜像二叉树和求二叉树最大深度 镜像二叉树。有些题目叫翻转二叉树。是同一个题。二叉树的最大深度 镜像二叉树。有些题目叫翻转二叉树。是同一个题。 题目描述&#xff1a;给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例&#xff1…

基于LLMs的多模态大模型(Visual ChatGPT,PICa,MM-REACT,MAGIC)

当LLMs已经拥有了极强的对话能力后&#xff0c;如何使其拥有视觉和语音等多模态能力是紧接而来的热点&#xff08;虽然GPT4已经有了&#xff09;&#xff0c;这个系列将不定期更新一些利用LLMs做多模态任务的文章。 直觉上&#xff0c;如果直接训练一个类似chatgpt架构的多模态…

sql查询指定数据的函数(等于、and、or、in、find_in_set、like)

sql查询指定数据的函数&#xff08;等于、and、or、in、find_in_set、like&#xff09;&#xff1a; 1.查询指定单字段的指定数据&#xff1a; 举例&#xff1a;查询user表中address字段数据等于aa的数据&#xff1b; select * from user where address aa 2.查询指定多字段…