点云滤波与匹配进阶

0. 简介

之前作者专门为点云匹配写了几篇博客,但是我们发现最近几年有更多的新方法已经在不断地被使用。同时之前有些内容也没有很好的概括,所以这里我们将作为一篇进阶文章来介绍这些方法的使用。

1. 地面点去除

处了使用一些复杂的方法(FEC)或是一些简单的方法(根据高度来滤除)以外,还可以使用Ransac的方法完成平面拟合

#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/sac_segmentation.h>void RemovePointsUnderGround(const pcl::PointCloud<pcl::PointXYZI>& cloud_in,pcl::PointCloud<pcl::PointXYZI>& cloud_out)
{// 对输入点云进行降采样pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_downsampled(new pcl::PointCloud<pcl::PointXYZI>);pcl::VoxelGrid<pcl::PointXYZI> voxel_grid;voxel_grid.setInputCloud(cloud_in.makeShared());voxel_grid.setLeafSize(0.1f, 0.1f, 0.1f); // 设置体素格大小voxel_grid.filter(*cloud_downsampled);// 创建一个滤波器对象,用于提取地面平面pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZI>);pcl::PassThrough<pcl::PointXYZI> pass_through;pass_through.setInputCloud(cloud_downsampled);pass_through.setFilterFieldName("z"); // 对z轴进行滤波pass_through.setFilterLimits(-1.5, 0.5); // 设置滤波范围,过滤掉z轴在-1.5到0.5之间的点pass_through.filter(*cloud_filtered);// 创建一个分割对象,用于提取地面平面pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers(new pcl::PointIndices);pcl::SACSegmentation<pcl::PointXYZI> segmentation;segmentation.setInputCloud(cloud_filtered);segmentation.setModelType(pcl::SACMODEL_PLANE);segmentation.setMethodType(pcl::SAC_RANSAC);segmentation.setDistanceThreshold(0.1); // 设置距离阈值,点到平面的距离小于该阈值的点将被认为是地面点segmentation.segment(*inliers, *coefficients);// 创建一个提取对象,用于提取地面点pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_ground(new pcl::PointCloud<pcl::PointXYZI>);pcl::ExtractIndices<pcl::PointXYZI> extract;extract.setInputCloud(cloud_filtered);extract.setIndices(inliers);extract.setNegative(false); // 提取地面点,即保留inliers对应的点extract.filter(*cloud_ground);// 创建一个提取对象,用于提取非地面点pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_non_ground(new pcl::PointCloud<pcl::PointXYZI>);extract.setNegative(true); // 提取非地面点,即去除inliers对应的点extract.filter(*cloud_non_ground);// 将结果保存到输出点云中cloud_out = *cloud_non_ground;
}

2. PCA主成分判别

除了去除点云以外,还可以通过主成分判别来判断我们分割的是否是地面。其中eigenvectors()函数得到的矩阵中的三个列向量分别对应于数据的主成分轴。这些主成分轴是按照数据方差的降序排列的,即第一个列向量对应的是数据的第一主成分轴,第二个列向量对应的是数据的第二主成分轴,第三个列向量对应的是数据的第三主成分轴。对于PCA的特征值和特征向量可以从PCA | 特征值和特征向量-CSDN博客这里理解。

#include <iostream>
#include <vector>
#include <pcl/point_types.h>
#include <pcl/common/pca.h>bool EstimatePlane(const pcl::PointCloud<pcl::PointXYZI>& cloud)
{// 将输入点云数据转换为PCL点云格式for (const auto& point : cloud){pcl::PointXYZ pclPoint;pclPoint.x = point.x();pclPoint.y = point.y();pclPoint.z = point.z();cloud->push_back(pclPoint);}// 创建PCA对象pcl::PCA<pcl::PointXYZ> pca;pca.setInputCloud(cloud);// 计算主成分Eigen::Vector3f eigenValues = pca.getEigenValues();Eigen::Matrix3f eigenVectors = pca.getEigenVectors();// 获取地面法向量,因为最小的就是第三列,所以最后一列是地面(0,0,1),如果是墙面那就(x,1-x,0)Eigen::Vector3f groundNormal = eigenVectors.col(2);#eigen_vector.block<3, 1>(0, 2)//最小成分的主成分向量,对应的是地面的法线,因为地面XY都存在比较大的主成分// 如果是其他的比如灯杆这种,一般的就会是fabs(eigen_vector.block<3, 1>(0, 0).dot(Eigen::Vector3f::UnitZ()))的形式,也就是最大主成分,沿着最大主成分方向bool is_ground = (fabs(groundNormal.dot(Eigen::Vector3f::UnitZ())) > 0.98) &&(eigenValues(2) < 0.05 * 0.05);//最小得列和地面法线重合|a||b|cos,并且eigenValues重要程度满足要求,因为地面基本等于0,所以特征值也很小 https://blog.csdn.net/xinxiangwangzhi_/article/details/118228160// 如果是其他的比如灯杆这种,一般的就会是eigen_values(0) > 10 * eigen_values(1)return is_ground;
}

3. GICP配准

GICP配准这块在之前的博客经典论文阅读之-GICP(ICP大一统)中已经详细讲过了,下面就是一个示例代码

Eigen::Matrix4d gicp_trans(pcl::PointCloud<PointType>::Ptr source_cloud,pcl::PointCloud<PointType>::Ptr target_cloud) {CHECK(source_cloud);CHECK(target_cloud);pcl::GeneralizedIterativeClosestPoint<PointType, PointType> gicp;gicp.setInputSource(source_cloud);gicp.setInputTarget(target_cloud);gicp.setMaxCorrespondenceDistance(10.0);gicp.setMaximumIterations(100);gicp.setMaximumOptimizerIterations(100);gicp.setRANSACIterations(100);gicp.setRANSACOutlierRejectionThreshold(1.0);gicp.setTransformationEpsilon(0.01);gicp.setUseReciprocalCorespondences(false);LOG(INFO) << "MaxCorrespondenceDistance: " << gicp.getMaxCorrespondenceDistance();LOG(INFO) << "MaximumIterations: " << gicp.getMaximumIterations();LOG(INFO) << "MaximumOptimizerIterations: " << gicp.getMaximumOptimizerIterations();LOG(INFO) << "RANSACIterations: " << gicp.getRANSACIterations();LOG(INFO) << "RANSACOutlierRejectionThreshold: " << gicp.getRANSACOutlierRejectionThreshold();LOG(INFO) << "TransformationEpsilon: " << gicp.getTransformationEpsilon();LOG(INFO) << "MaxCorrespondenceDistance: " << gicp.getMaxCorrespondenceDistance();LOG(INFO) << "RANSACOutlierRejectionThreshold: " << gicp.getRANSACOutlierRejectionThreshold();LOG(INFO) << "UseReciprocalCorrespondences: " << gicp.getUseReciprocalCorrespondences();pcl::PointCloud<PointType>::Ptr aligned_source =boost::make_shared<pcl::PointCloud<PointType>>();gicp.align(*aligned_source);CHECK(aligned_source);LOG(INFO) << "Final transformation: " << std::endl << gicp.getFinalTransformation();if (gicp.hasConverged()) {LOG(INFO) << "GICP converged." << std::endl<< "The score is " << gicp.getFitnessScore();} else {LOG(INFO) << "GICP did not converge.";}LOG(INFO) << "Saving aligned source cloud to: " << params_.aligned_cloud_filename;pcl::io::savePCDFile(params_.aligned_cloud_filename, *aligned_source);return  gicp.getFinalTransformation();
}

点击 点云滤波与匹配进阶 - 古月居可查看全文

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

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

相关文章

Cute Background FX

Cute Background FX是环境背景粒子系统的集合。非常适合作为菜单的背景。 该包包括: -20个独特预制件+20个URP预制件 -5种独特的环境设计 -15种纹理 -2个自定义着色器+2个URP着色器 -共59项独特资产 -一个演示场景,您可以在其中概述所有内容。 所有纹理都是512x512分辨率的P…

基于SSM框架实现的在线心理评测与咨询系统(技术栈 spring+springmvc+mybatis+jsp+jquery+css)

一、项目简介 本项目是一套基于SSM框架实现的在线心理评测与咨询系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&am…

iOS 应用内网络请求设置代理

主要通过URLSessionConfiguration 的connectionProxyDictionary 属性 为了方便其他同学使用&#xff0c;我们可以通过界面来进行设定&#xff08;是否开启代理、服务端、端口&#xff09;&#xff0c;从而达到类似系统上的设定 具体链接参考&#xff1a;为 iOS 网络请求设置代理…

代码随想录算法训练营33期 第二十九天(补第二十八天)| 93.复原IP地址、78.子集、 90.子集II

93.复原IP地址 class Solution { public:vector<string> result;bool isValid(const string& s, int start, int end){if (start > end){return false;}if (s[start]0 && start ! end){return false;}int num 0;for (int istart; i<end; i){if (s[i]…

设计模式总结-桥接模式

桥接模式 模式动机模式定义模式结构模式分析桥接模式实例与解析实例一&#xff1a;模拟毛笔 模式优缺点 模式动机 设想如果要绘制矩形、圆形、椭圆、正方形&#xff0c;我们至少需要4个形状类&#xff0c;但是如果绘制的图形需要具有不同的颜色&#xff0c;如红色、绿色、蓝色…

linux内核网络源码分析--功能专用字段‘每日读书’

linux内核是模块化的&#xff0c;允许你选择要包含什么以及省略什么。因此&#xff0c;只有当内核编译位支持特定功能时候&#xff0c;如防火墙或者Qos&#xff0c;某些字段才会包含在sk_buff数据结构中。 unsigned long nfmark __u32 nfcache __u32 nfctinfo struct nf_conntr…

xss.pwnfunction-Ugandan Knuckles

这个是把<>过滤掉了所以只能用js的事件 ?weya"onfocus"alert(1337)" autofocus"

基于springboot的社区医疗服务系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

数据结构面试题报错调试方法记录

栈和队列报错调试 1.用栈实现队列 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 此题解题思路如下&#xff1a; 先将数据放在pushst栈里面&#xff0c;popst栈为空再把pushst栈里面的数据放进popst栈里面去&#xff0c;不为空则不执行。不为空时候直接拿取栈…

基于C语言实现 SQL数据库和链表的相互转换

使用的函数介绍 这里sqlite3_open、sqlite3_close就不介绍了 sqlite3_prepare_v2()&#xff1a; 函数原型&#xff1a;int sqlite3_prepare_v2(sqlite3* db, const char* zSql, int nByte, sqlite3_stmt** ppStmt, const char** pzTail);作用&#xff1a;准备 SQL 语句以供执…

WSL2迁移后默认登陆用户为root的解决方案

第一步&#xff0c;在wsl的root用户下面用vim打开/etc/wsl.conf文件 vim /etc/wsl.conf第二步&#xff0c;在文件中添加以下代码, 仅需把user_name替换成你原来wsl的用户名即可 [user] defaultuser_name如 [user] defaultpengyuyan重启wsl,在powershell下输入 wsl --shutdo…

【GDB】GDB解CORE文件

目录 一 GDB解析CORE文件(Linux) 二 GDB解析CORE文件(QNX) 在 Linux 系统中,当一个进程发生崩溃或异常时,它会生成一个所谓的 core dump 文件,其中包含了该进程的内存映像和一些调试信息。这个文件可以用于分析和解决崩溃问题,以便了解进程崩溃时的状态和原因

多模态text-image模型之ITM loss(blip)

主要代码&#xff1a; # forward the positve image-text pair # 正向传播正面的图像文本对 output_pos self.text_encoder.bert(encoder_embedstext_embeds, attention_masktext.attention_mask,encoder_hidden_statesimage_embeds,encoder_attention_maskimage_atts, …

【技术笔记】Ubuntu下VirtualBox不能识别USB解决办法(手把手解决)

环境说明 系统版本&#xff1a;Ubuntu 20.04 VirtualBox版本&#xff1a; 7.0.12 解决过程 扩展下载&#xff0c;进入VirtualBox 官方下载路径。选择本机安装版本&#xff0c;如下图所示&#xff0c;因笔者是7.0.x版本&#xff0c;因此点击第一条链接&#xff1b; 进入版本页…

机器学习(30)

文章目录 摘要一、文献阅读1. 题目2. abstract3. 网络架构3.1 Sequence Generative Adversarial Nets3.2 SeqGAN via Policy Gradient3.3 The Generative Model for Sequences3.4 The Discriminative Model for Sequences(CNN) 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过…

慢SQL问题排查

慢SQL问题排查是一个系统性的过程&#xff0c;它涉及到对数据库性能、查询优化以及系统资源的深入理解。 1. 收集慢查询日志 启用慢查询日志&#xff1a;大多数数据库系统&#xff08;如MySQL、PostgreSQL等&#xff09;都支持慢查询日志功能。启用该功能后&#xff0c;数据库…

关于npm和yarn的使用(自己的问题记录)

目录 一 npm 和 yarn 常用命令 二 package.json中 devDependencies 和 dependencies 的区别。 三 npm安装包时&#xff0c;加 --save和不加的区别 一 npm 和 yarn 常用命令 备注&#xff1a;以下命令以 axios 为例。 未完&#xff1a;待续。。。。 二 ​​​​​​​ …

【Vue3源码学习】— CH2.7 Computed: Vue 3 计算属性深入解析

Computed: Vue 3 计算属性深入解析 1.计算属性的基本用法2. ComputedRefImpl 类深入解析JavaScript 中的 getter 函数 3. 计算属性的创建&#xff1a;computed 方法解析3.1 源码解析3.2 使用示例 4. 计算属性的工作原理5. 手动实现简化的计算属性6. 结语 在 Vue 3 的响应式系统…

【教程】VOC数据集制作

语义分割任务中VOC数据集的制作&#xff0c;任务中只有一种标签&#xff1a;gas 文章目录 1、由黑白图像识别为txt标签2、txt转json3、数据集转VOC格式 1、由黑白图像识别为txt标签 由于使用CycleGAN网络进行风格迁移学习&#xff0c;生成了大量伪标签图像&#xff0c;因此需…

【递归与递推】数的计算|数的划分|耐摔指数

1.数的计算 - 蓝桥云课 (lanqiao.cn) 思路&#xff1a; 1.dfs的变量>每一次递归什么在变&#xff1f; &#xff08;1&#xff09;当前数的大小一直在变&#xff1a;sum &#xff08;2&#xff09;最高位的数&#xff1a;k 2.递归出口&#xff1a;最高位数字为1 3.注意&#…