【代码阅读】SSC:Semantic Scan Context for Large-Scale Place Recognition

一、主函数

官方开源的代码提供了四个主函数,其中eval_pair.cpp和eval_top1.cpp是一组,分别用于计算两帧的相似度分数以及一帧点云在所有的51帧点云中相似度最高的25帧的相似度分数。eval_seq.cpp是在eval_top1.cpp的基础上,给了一堆序列,遍历序列中的每一帧点云并输出与之相似度足够高的25帧点云的相似度分数。eval_angle.cpp这个文件比较迷,readme里面也没有提,代码里面提到的那几个config文件开源代码也没有给出,从代码内容来看,更像是在eval_pair.cpp的基础上,计算了好多帧对的位姿变换。

主函数的具体操作基本都是类似的,先初始化config对象读取配置文件,同时利用这个配置文件初始化ssc对象,之后根据不同的需求,调用重载了许多次的ssc对象里面的getScore函数,进行相似度分数的计算。因此整个ssc算法其实都在ssc对象中实现。

二、ssc.cpp

算法的实现基本都在这个文件中,文件的结构本身不复杂,除了构造函数和析构函数,还有三个形式的读取点云函数、投影函数、计算ssc描述子的函数、两个形式的全局ICP函数、计算相似度的函数以及六个形式的计算相似度分数的函数。
在这里插入图片描述

getScore()

根据主函数的执行顺序,这里我们也从getScore函数开始。从重载函数的形式看,六个getScore函数传入的参数本质上都是一样的:两帧点云、两帧点云的语义以及变换矩阵,不同之处在于传入的形式,一二个函数传入的是XYZL形式的点云,这是pcl库中一个点云形式,L表示的是label,相当于直接把语义信息存储了进去,三四个函数这是传入了点云文件的路径和语义推理结果的路径,在函数内部分别读取两个文件,最后两个函数则是直接读取标记过语义的点云文件。从执行的路径来看,最后面四个函数都是在调整文件格式之后,转而调用了前面两个函数,所以这里我们主要看第一个形式的getScore函数。

project()

进入函数后首先对位姿变化的量进行初始化,同时利用project函数对标记过语义的点云进行投影。与其叫做投影,其实更多地是在做格式的转换。

函数首先对场景划分了扇区,扇区只对轴向做了大小的限制,而没有对径向进行约束。从代码来看,一帧点云共计划分了360个扇区,也就是每个扇区在轴向上是一度,之后初始化一个360*1的向量,每个元素为一个32位的浮点数,初始值为0。
在这里插入图片描述
之后对于函数传入下采样后的点云filtered_pointcloud,遍历点云中的每个点,对类别标记为13、14、16、18、19的这五类点进行点云格式的转换。查看配置文件可以发现,选择的这五类对应的是building、fence、trunk、pole以及traffic-sign,而没有选择出现次数更多的ground等类别。对于水平距离足够远的点,算法会根据夹角信息计算其所在的扇区,之后将这个点到中心的距离、点在水平方向上的坐标以及该点的语义坐标进行存储。
在这里插入图片描述
这里就存在一个问题,代码183行到186行对点信息的存储,是直接覆盖的,而不是添加的,这就会导致当一个扇区内同时存在13、14、16、18、19这五类点的时候扇区的描述子实际上是多次覆盖过的。查看作者的原论文,里面写的是每个扇区内部只保留距离中心最近的点,个人推测这里的这种写法是作者默认了filtered_pointcloud是从远到近的排列,因为在之前看的salsanext代码中有对点云重排列的部分,这里作者并没有调用下采样相关的内容,可能是在输入的bin文件点云中已经调整过顺序。

globalICP()

回到getScore函数,在计算出ssc_dis之后,函数进入到globalICP进行一个位姿的计算。这里对应的是原论文中的全局语义ICP的部分。由于描述子的设计具有旋转不变性,所以代码首先利用描述子径向上的距离,计算了两帧点云描述子轴向上应该旋转的量。

具体来说其实就是一个遍历的过程,对于下面的这个二层循环,第一层的i表示的是轴向上应该移动的距离,单位是扇区数量,第二层则是遍历每个扇区,之后计算旋转后两个描述子第一维也就是到中心的距离的差,差值统计在dis_count这个量里面,取最小值对应的i作为两个描述子或者两帧点云在轴向上应该旋转的值。
在这里插入图片描述
得到角度之后,就可以将描述子进行旋转,让两个描述子对齐,描述子一共四个维度,其中第一个和最后一个是不用换的,只有第二和第三个的坐标需要调整,也就是根据正弦和余弦进行投影。
在这里插入图片描述
之后进行共计100轮次的迭代计算,这一次需要计算的是xy方向上面的平移。每一次迭代首先会取出一个合法扇区,根据先前计算出的径向旋转得到投影之后的位置,在这个位置左右各10个扇区共计20个扇区范围内进行检验。指标是扇区描述子中二三维度对应的点的几何距离。
在这里插入图片描述
对于当前扇区找到的最近点扇区,如果坐标偏差足够小则进行统计计算,对偏移量进行累计。
在这里插入图片描述
遍历完所有扇区之后,对所有的偏差取平均,作为当前这一次迭代计算中的偏差值,这个偏差值表示的是xy方向上面的偏移,直接对点云描述子进行校正,同时存储所有的偏差。
在这里插入图片描述
最终,diff_x、diff_y以及angle将会被作为两帧点云之间的位姿差异传递回主函数。从这整个过程来看,globalICP这个函数就是将位姿变化拆分为旋转和平移进行计算,旋转依赖的是扇区描述子的旋转不变性,通过最小化轴向距离差值来找到最优的径向旋转偏差,而平移则是依靠得到的旋转结果进行调整,在计算平移时则不利用径向距离,而是利用扇区之间点的几何距离来调优,迭代100轮以完成平移的计算。这里说一下个人感觉不足的地方,在整个的计算过程中点云被十分过分地简化,按照代码默认的配置文件,径向上划分了360个扇区,就算不考虑语义类别,一帧点云顶天也就只保留了360个点用于构建这个描述子,从数量上来看简化的有些过分。另外,在计算的过程中,旋转和平移被完全拆分开来,先只计算旋转,计算平移时则固定旋转,这种方法未必得到的就是最优的结果,平移和旋转应该作为整体共同进行调整,而没见过这种拆分固定的计算策略。最后,扇区的划分很大程度上会影响结果的准确性,由于选择扇区的点的时候只考虑了到中心点的距离这一个指标,而在径向上完全不做考虑,这就有可能导致一个扇区对应的1度范围内,0.0001度的点和0.9999度的点进行了对齐,有可能导致径向上1度的偏差,而在固定旋转调整平移的过程中更有可能错上加错,所以这一策略或者是开源的代码本身其实是有较大的不足的。

calculateSSC()

回到getScore函数,globalICP计算出的位姿变化会被存储在diff_x、diff_y以及angle中,利用这个变化关系将点云进行投影,之后调用calculateSSC函数进行ssc描述子的计算。这个函数要简单的多,首先初始化径向和轴向的步长,得到一个二维的矩阵用于存放描述子,矩阵的每个位置存放的都是一个8位无符号数。
在这里插入图片描述
之后遍历点云内的每个点,对于需要统计的类别的点,确定其在二维矩阵中的位置。原论文提到了写在描述子中的类别是根据优先级选择的,从代码来看,这个优先级就是提前写死在order_vec里面了。在确定好的位置中,如果已经写入了,就根据优先级进行判断,选择覆盖或者保持不变。
在这里插入图片描述

calculateSim()

完成ssc描述子的计算后,就会调用calculateSim函数计算相似度,相似度的计算也很简单,就是比较相同位置上的语义是否相同,最终统计相同的占总合法位置中的比例,这个比例会作为相似度分数返回给主函数。
在这里插入图片描述

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

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

相关文章

【Java Web】会话管理

目录 一、为什么需要会话管理? 二、会话管理机制 三、Cookie概述 四、HttpSession概述 4.1 HttpSession时效性 一、为什么需要会话管理? HTTP协议在设计之初就是无状态的,所谓无状态就是在浏览器和服务器之间的通信过程中,服务器并…

简过网:上万元的学费,考公到底要不要报个培训班?

考公报不报班一直是很多朋友比较纠结一件事,报班了学费太贵,不报班又怕考不上,如果你也有这种困扰,那么,不妨看看这篇文章! 首先,对于报班VS自学这个问题,小编的建议是:…

LICEcap-开源GIF 屏幕录制工具

LICEcap-开源GIF 屏幕录制工具 开源GIF 屏幕录制工具 下载可以访问:https://www.cockos.com/licecap/ 点击Record,开始录制 点击Stop,停止录制 点击Record,进入该页面 display in animation(在动画中显示) …

240627_昇思学习打卡-Day9-ResNet50图像分类

240627_昇思学习打卡-Day9-ResNet50图像分类 文章目录 240627_昇思学习打卡-Day9-ResNet50图像分类前言残差网络Residual Block代码实现Bottleneck Block代码实现 BN层(Batch Normalization)构建ResNet50网络数据集准备与加载模型训练与评估可视化模型预…

高德.js2.0绘制点聚合,并点击点出现自定义样式弹窗

我这里依旧使用AMapLoader插件 代码如下 // 初始化高德地图initMap() {AMapLoader.load({key: "fb35c92d4019cfafeca876fd5514bb47", //key值是key值 和安全密钥不同version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15plugins…

免费恢复微信好友的聊天记录(已删除的好友不能恢复)

非常简单,适用于未删除的微信好友的聊天记录恢复,支持导出 1、下载楼月微信聊天记录导出恢复助手 - 导出手机微信聊天记录 2、官方原文教程链接:官方原文教程链接https://www.louyue.com/weixin.htm

华为升腾显卡选型备忘

目录 1. 开发套件 2. 加速模块 3. 加速卡 4. 训练卡 官方地址:https://www.hiascend.com/ 备注: (1)V后缀的都是Video视频解析卡,本质是推理卡; (2)I后缀的都是推理卡&#…

如何通过小猪APP分发轻松实现应用内测分发

搞应用开发的朋友们,都知道内测分发这个环节有多重要。没有内测,一款应用基本上是不可能上线的。毕竟,谁也不想自己的产品在上线的那一刻就被用户吐槽得体无完肤。内测分发的好坏,直接影响到应用的质量和用户的第一印象。如何才能…

postGreSQL关系数据库介绍

什么是postGreSQL关系数据库? PostgreSQL 是一个强大的、开源的对象关系型数据库管理系统(ORDBMS)。它基于POSTQUEL查询语言的继承,提供了对SQL标准的广泛支持,并扩展了许多高级功能,如事务处理、多版本并…

使用Python实现深度学习模型通常涉及以下几个步骤

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把手教你开发炫酷的vbs脚本制作(完善中……) 4、牛逼哄哄的 IDEA编程利器技巧(编写中……) 5、面经吐血整理的 面试技…

光电液位传感器工作时容易受哪些因素影响?

光电式水位传感器的检测液位时是必须要接触液体才能进行检测的。当液体覆盖光电式水位传感器的探头时,传感器内的发光二极管发射出去的光线会折射在液体中,而光敏接收器只能接收到少量光电或者接收不到光线。反之正常接收光线则是无水状态。 光电式水位…

想买骨传导耳机怕踩雷?全方位的选购攻略分享给你!

作为一个爱好运动的人来说,现在天气越来越暖和了,很多人选择外出徒步、越野或者骑行。在运动过程中都会佩戴一些入耳式耳机,但是运动一段时间发现入耳式耳机带久了耳朵会很不舒服,而且出汗了的话对于一些不防水的入耳式耳机的话&a…

swiper轮播 loop:true失效解决

数据是写死的时候,能够loop:true是有效的;数据是动态获取的loop:true就会失效。 方法一:在接收到数据后,使用 setTimeout(() > {this.getSwiper(); //生成swiper方法}, 0); 下面是我项目具体使用的参考例子: 方法二&#xff…

详细解释Spring事务的传播机制

详细解释Spring事务的传播机制 Spring框架中,事务传播机制是指在一个事务方法调用另一个事务方法时,Spring如何管理这些方法之间的事务边界。Spring提供了七种事务传播行为,以满足不同的业务需求。下面将详细解释每种传播行为及其适用场景&a…

IDEA 安装与激活详细教程最新(附最新激活码)2099年亲测有效!

我们先从 IDEA 官网下载 IDEA 2024.1 版本的安装包,下载链接如下: https://www.jetbrains.com/idea/download/ 点击下载(下载Ultimate版),静心等待其下载完毕即可。 激活方式: 正版专属激活码领取

vcruntime140_1.dll是什么东东?vcruntime140_1.dll缺失的8个解决方法

当电脑出现找不到vcruntime140_1.dll,或vcruntime140_1.dll丢失无法打开软件怎么办?小编今天在本文详细为大家介绍解决方法与介绍vcruntime140_1.dll究竟是什么等vcruntime140_1.dll的问题。 一、vcruntime140_1.dll文件是什么 文件概述定义与功能 vcruntime140_…

观测云「可观测性解决方案」荣耀登入华为云官网

继成功上架华为云云商店联营商品后,「观测未来可观测性解决方案」已进一步正式登陆华为云官网,标志着双方合作的深化与拓展。这一全新上架的解决方案是观测云技术实力的集大成之作,为企业提供了一个全面升级的数字化监控观测服务。 观测云&am…

模拟局部下雨的天气思路Mars3d实现参考

目前mars3d里只有下雨滤镜那种,不能表现局部 曲线救国思路参考: 1、根据局部矢量范围求一个外接矩形bbox,根据bbox用turf按照比例尺生成网格(比如50x50公里一个网格) 2、所有的网格再按照矢量范围裁剪一下&#xff0…

「51媒体」湖北地区媒体邀约

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体宣传加速季,100万补贴享不停,一手媒体资源,全国100城线下落地执行。详情请联系胡老师。 湖北地区拥有网络媒体、电视媒体、报纸杂志、视频媒体等多…

python AI全栈工程师

python AI全栈工程师 前端:Streamlit Streamlit是一个开源的Python库,专为数据科学家和机器学习工程师设计,用于快速构建交互式用户界面。Streamlit功能强大、易于使用,特别适合数据科学家和机器学习工程师快速构建和部署交互式数…