io获取 pcl_点云数据可视化之PCL滤波学习
PCL滤波概述
在获取点云数据时 ,由于设备精度,操作者经验环境因素带来的影响,以及电磁波的衍射特性,被测物体表面性质变化和数据拼接配准操作过程的影响,点云数据中将不可避免的出现一些噪声。在点云处理流程中滤波处理作为预处理的第一步,对后续的影响比较大,只有在滤波预处理中将噪声点 ,离群点,孔洞,数据压缩等按照后续处理定制,才能够更好的进行配准,特征提取,曲面重建,可视化等后续应用处理,PCL中点云滤波模块提供了很多灵活实用的滤波处理算法,例如:PassThrough直通滤波、VoxelGrid过滤、StatisticalOutlierRemoval过滤、点云投影、提取索引等;下面将对几种常见滤波进行介绍。
PCL中点云滤波的方案
PCL中总结了几种需要进行点云滤波处理情况,这几种情况分别如下:
(1) 点云数据密度不规则需要平滑
(2) 因为遮挡等问题造成离群点需要去除
(3) 大量数据需要下采样
(4) 噪声数据需要去除
对应的方案如下:
(1)按照给定的规则限制过滤去除点
(2) 通过常用滤波算法修改点的部分属性
(3)对数据进行下采样
常见滤波概述
直通滤波:快速过滤掉用户自定义区间范围内的点云,效果最为明显并且也最容易理解。
体素滤波:在分割、配准前,如果点云数量太多会影响后续时间。此时,需要对点云进行下采样处理,体素滤波为采用体素网格方法采样,减少点云数量。
统计滤波:统计滤波往往去除离群点,利用统计分析技术删除噪声异常值等。
投影点云:将点投影到一个参数化模型上(平面或者球体等)。
提取索引:基于某一分割算法提取点云中的子集。
几种常见滤波使用实例
对于下面各种滤波的使用并没有只用文字来阐述,而是主要在代码的注释中,我认为这样会便于理解。
- 直通滤波
直通滤波通俗来讲就是设置一个范围,经该范围内或者该范围外的点云数据剔除,是一种简单暴力但效果明显的方式。
代码:
#include #include #include #include #include int main (int argc, char** argv){ //点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud(new pcl::PointCloud<:pointxyz>); //处理后点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud_handle(new pcl::PointCloud<:pointxyz>); //处理后点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud_handle2(new pcl::PointCloud<:pointxyz>); //从点云文件中读取点云数据 pcl::io::loadPCDFile("d:/2.pcd", *cloud); //目的:通过直通滤波器将某个方向范围的点云数据过滤掉 // 设置滤波器对象 pcl::PassThrough<:pointxyz> pass; //z坐标轴 pass.setInputCloud (cloud); //设置输入点云 pass.setFilterFieldName ("x"); //设置过滤的坐标轴方向 pass.setFilterLimits (-90, 90); //设置在过滤掉的坐标范围 pass.setFilterLimitsNegative (false); //设置过滤范围内还是范围外,当为false为范围外 pass.filter (*cloud_handle); //过滤器过滤,过滤后点云数据保存在cloud_handle中 // 设置滤波器对象 pcl::PassThrough<:pointxyz> pass2; //z坐标轴 pass.setInputCloud (cloud_handle); //设置输入点云 pass.setFilterFieldName ("y"); //设置过滤的坐标轴方向 pass.setFilterLimits (-86, 50); //设置在过滤掉的坐标范围 pass.setFilterLimitsNegative (false); //设置过滤范围内还是范围外,当为false为范围外 pass.filter (*cloud_handle2); //过滤器过滤,过滤后点云数据保存在cloud_handle中 //处理后点云显示 pcl::visualization::CloudViewer viewer("PCL滤波"); viewer.showCloud(cloud_handle2); while (!viewer.wasStopped()){ } return (0);}
处理前:
处理后:
这种滤波处理方式效果很明显,但是它受限于采样设备的角度,如果角度不佳,仅仅对XYZ轴方向进行过滤就得不到理想的结果。
- 体素滤波
使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,并同时保存点云的形状特征,在提高后期点云处理速度方面将起到显著效果。PCL是实现的VoxelGrid类通过输入的点云数据创建一个三维体素栅格,容纳后每个体素内用体素中所有点的重心来近似显示体素中其他点,这样该体素内所有点都用一个重心点最终表示,对于所有体素处理后得到的过滤后的点云,这种方法比用体素中心逼近的方法更慢,但是对于采样点对应曲面的表示更为准确。
代码:
#include #include #include #include #include #include int main (int argc, char** argv){ //点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud(new pcl::PointCloud<:pointxyz>); //处理后点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud_handle(new pcl::PointCloud<:pointxyz>); //从点云文件中读取点云数据 pcl::io::loadPCDFile("d:/2.pcd", *cloud); pcl::VoxelGrid<:pointxyz> sor; //创建滤波对象 sor.setInputCloud (cloud); //设置需要过滤的点云给滤波对象 sor.setLeafSize (1, 1, 1); //设置滤波时创建的体素体积,单位m,因为保留点云大体形状的方式是保留每个体素的中心点,所以体素体积越大那么过滤掉的点云就越多 sor.filter (*cloud_handle); //执行滤波处理 //处理后点云显示 pcl::visualization::CloudViewer viewer("PCL滤波"); viewer.showCloud(cloud_handle); while (!viewer.wasStopped()){ } return (0);}
处理前:
处理后:
- 统计滤波
使用统计分析技术,从一个点云数据中集中移除测量噪声点(也就是离群点)比如:激光扫描通常会产生密度不均匀的点云数据集,另外测量中的误差也会产生稀疏的离群点,使效果不好,估计局部点云特征(例如采样点处法向量或曲率变化率)的运算复杂,这会导致错误的数值,反过来就会导致点云配准等后期的处理失败。
解决办法:每个点的邻域进行一个统计分析,并修剪掉一些不符合一定标准的点,稀疏离群点移除方法基于在输入数据中对点到临近点的距离分布的计算,对每一个点,计算它到它的所有临近点的平均距离,,假设得到的结果是一个高斯分布,其形状是由均值和标准差决定,平均距离在标准范围之外的点,可以被定义为离群点并可从数据中去除。
代码:
#include #include #include #include #include #include #include int main (int argc, char** argv){ //点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud(new pcl::PointCloud<:pointxyz>); //处理后点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud_handle(new pcl::PointCloud<:pointxyz>); //从点云文件中读取点云数据 pcl::io::loadPCDFile("d:/2.pcd", *cloud); pcl::StatisticalOutlierRemoval<:pointxyz> sta; //创建滤波器对象 sta.setInputCloud (cloud); //设置待滤波的点云 sta.setMeanK (1); //设置在进行统计时考虑查询点临近点数 sta.setStddevMulThresh (1.0); //设置判断是否为离群点的阀值,根据原理来说,阈值越小过滤掉的点就越多 sta.filter (*cloud_handle); //存储 //处理后点云显示 pcl::visualization::CloudViewer viewer("PCL滤波"); viewer.showCloud(cloud_handle); while (!viewer.wasStopped()){ } return (0);}
处理前:
处理后:
统计滤波我目前的理解是通过算法按照一定阈值将点云中的可能存在干扰的离散点过滤掉。
- 点云投影
点云投影主要是将三维结构投影到二维平面上。
#include #include #include #include #include #include #include #include #include int main (int argc, char** argv){ //点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud(new pcl::PointCloud<:pointxyz>); //处理后点云对象 pcl::PointCloud<:pointxyz>::Ptr cloud_handle(new pcl::PointCloud<:pointxyz>); //从点云文件中读取点云数据 pcl::io::loadPCDFile("d:/2.pcd", *cloud); //定义模型系数对象,并填充对应的数据,填充ModelCoefficients的值 //使用ax+by+cz+d=0平面模型,其中 a=b=d=0,c=1 也就是X——Z平面 pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ()); coefficients->values.resize (4); coefficients->values[0] = coefficients->values[1] = 1.0; coefficients->values[2] = 0; coefficients->values[3] = 0; pcl::ProjectInliers<:pointxyz> proj; //创建投影滤波对象 proj.setModelType (pcl::SACMODEL_PLANE); //设置对象对应的投影模型 proj.setInputCloud (cloud); //设置输入点云 proj.setModelCoefficients (coefficients); //设置模型对应的系数 proj.filter (*cloud_handle); //投影结果存储 //处理后点云显示 pcl::visualization::CloudViewer viewer("PCL滤波"); viewer.showCloud(cloud_handle); while (!viewer.wasStopped()){ } return (0);}
处理前:
处理后:
这里就变成了一个在x-z平面的二维投影。
- 提取索引
代码:
#include #include #include #include #include #include #include #include #include #include int main (int argc, char** argv){ pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);//声明滤波前后的点云 pcl::PointCloud<:pointxyz>::Ptr cloud_filtered (new pcl::PointCloud<:pointxyz>), cloud_p (new pcl::PointCloud<:pointxyz>), cloud_f (new pcl::PointCloud<:pointxyz>); // 读取PCD文件 pcl::PCDReader reader; reader.read ("d:/2.pcd", *cloud_blob); //统计滤波前的点云个数 //从输入的.PCD 文件载入数据后,创建一个VOxelGrid滤波器对数据进行下采样,在这里进行下采样是为了加速处理过程, //越少的点意味着分割循环中处理起来越快 // 创建体素栅格下采样: 下采样的大小为1cm pcl::VoxelGrid<:pclpointcloud2> sor; //体素栅格下采样对象 sor.setInputCloud (cloud_blob); //原始点云 sor.setLeafSize (1, 1, 1); // 设置采样体素大小 sor.filter (*cloud_filtered_blob); //保存 // 转换为模板点云 pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered); // 保存下采样后的点云 pcl::PCDWriter writer; writer.write<:pointxyz> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false); pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ()); pcl::PointIndices::Ptr inliers (new pcl::PointIndices ()); pcl::SACSegmentation<:pointxyz> seg; //创建分割对象 seg.setOptimizeCoefficients (true); //设置对估计模型参数进行优化处理 seg.setModelType (pcl::SACMODEL_PLANE); //设置分割模型类别 seg.setMethodType (pcl::SAC_RANSAC); //设置用哪个随机参数估计方法 seg.setMaxIterations (1000); //设置最大迭代次数 seg.setDistanceThreshold (0.01); //判断是否为模型内点的距离阀值 // 设置ExtractIndices的实际参数 pcl::ExtractIndices<:pointxyz> extract; //创建点云提取对象 int i = 0, nr_points = (int) cloud_filtered->points.size (); // While 30% of the original cloud is still there while (cloud_filtered->points.size () > 0.3 * nr_points) { // 为了处理点云包含的多个模型,在一个循环中执行该过程并在每次模型被提取后,保存剩余的点进行迭代 seg.setInputCloud (cloud_filtered); seg.segment (*inliers, *coefficients); if (inliers->indices.size () == 0) { break; } // Extract the inliers extract.setInputCloud (cloud_filtered); extract.setIndices (inliers); extract.setNegative (false); extract.filter (*cloud_p); std::stringstream ss; ss << "table_scene_lms400_plane_" << i << ".pcd"; writer.write<:pointxyz> (ss.str (), *cloud_p, false); // Create the filtering object extract.setNegative (true); extract.filter (*cloud_f); cloud_filtered.swap (cloud_f); i++; } //处理后点云显示 pcl::visualization::CloudViewer viewer("PCL滤波"); viewer.showCloud(cloud_f); while (!viewer.wasStopped()){ } return (0);}
处理前:
处理后:
io获取 pcl_点云数据可视化之PCL滤波学习相关推荐
- Python+vtk 实现激光点云数据可视化学习(2021.7.12)
Python+VTK实现激光点云数据可视化学习 2021.7.12 1.激光点云与VTK简介 2.配置Python环境(Conda+PyCharm+Python3.6+VTK) 3.点云数据(大约60 ...
- 袋鼠云数据可视化大屏技术揭秘|数据地图的类型
地图是按照一定的法则,有选择地以二维或多维形式与手段在平面或球面上表示地球(或其它星球)若干现象的图形或图像.在数据可视化中,地图也是一个重要的部分.本期给大家讲解一下在数据可视化中怎样去选择一个合适 ...
- 基于变电站3D点云数据的目标识别与检测学习总结(一)
最近开始学习有关三维点云的知识,由于工程项目原因,首先学习了一篇与变电站相关的文章–<基于三维点云的变电站设备分类识别研究–李玲侠>,该文采用三维激光扫描仪来获取点云数据. 文章摘要 1. ...
- 数据可视化记二基础学习(Highcharts、AntV、ECharts)
目录 一.Highcharts 1.1 Highcharts JS 1.2 Highstock JS 1.3 Highmaps JS 二.AntV 2.1 绘制流程 2.1.1 Antv G2 绘图流 ...
- 《数据可视化》之小白学习篇(一)
本博客记录这学期关于数据可视化的一些学习,由于我是一个菜鸟,编程能力很弱,希望看到的大佬不要笑话. 文章目录 前言 一.为什么要数据可视化? 二.数据可视化基础篇 1.Javascript实现直方图绘 ...
- 爬取一周天气获取24小时温度+数据可视化
以下代码是根据https://blog.csdn.net/weixin_45826022/article/details/109584915进行修改实现的(修改成一周温度爬取),具体的实现思路请参考上 ...
- 乐视体感astra pro深度摄像头在ros系统获取 深度图像 彩色图像 无色彩点云数据 彩色点云数据
1.astra pro深度摄像头介绍 2.astra pro驱动安装 3.astra pro获取深度图像 无色彩pointCloud2 4.astra pro获取彩色图像 带彩色的pointCl ...
- 国内小众国货宝藏数据可视化工具top5
都说第四次工业革命是数据化革命,确实,随着互联网的发展,数据革命已经在不知不觉中悄悄来到我们身边,现在这个时代谁能更快将数据掌握在自己手中谁就能更好的占领市场,谁能更好的玩转数据谁就能得到更好得发展, ...
- 第二章 python-pcl、open3d读取、显示pcd、bin等格式点云数据
第二章 python-pcl.open3d读取.显示pcd.bin格式点云数据 文章目录 第二章 python-pcl.open3d读取.显示pcd.bin格式点云数据 前言 环境 一.点云数据类型 ...
最新文章
- Rocksdb 的优秀代码(二)-- 工业级 打点系统 实现分享
- aws lambda_为什么我会自动删除所有旧的推文以及我用来执行此操作的AWS Lambda函数...
- 「北京」「10-30k」「华米科技(小米手环)」招前端工程师
- VB100八月测试:Vista成众安全厂商梦魇 国内仅可牛通过测试
- 详解 Windows下apache 实现 SSL
- 截断骨干用于检测,YOLO-ReT开源:边缘GPU设备上的高性能检测器
- Beyond Compare 4
- Silverlight 密码框 Focus
- ---perl 模块安装方法
- iOS数据库的使用(三):sqlite多线程
- 金蝶kis仓库管理系统演示_金蝶KIS操作流程
- 【Python密度泛函理论】
- HTML页面多语言切换
- Maven的jar包无法导入/彻底解决unable to find valid certification path to requested target
- 题解:2018校招真题(字节跳动:附加题)
- 开咖啡店会遇到的哪些问题?总结八大解决方法
- gb28181简单解包rtp ps流,推出rtmp(java版基于springboot):六、解包rtp ps流,推出rtmp
- 普华永道思略特:阿里巴巴研发投入领跑中国上市公司
- 孟岩《通证经济系统设计》三期8.18开课,四期正式接受报名!
- Mac使用hsdis查看java字节码的汇编命令
热门文章
- 目标检测coco数据集点滴介绍
- Redis高可用集群Redis Cluster搭建
- 如何自学php框架,如何学习php框架
- java 无法取消引用_Java的新手,并出现错误“无法取消引用int” - java
- CoordinatorLayout 和 AppBarLayout 实现的局部点击按钮实现折叠和展开
- getElementById 使用
- Android studio 编译器导入一个背景图片
- GridView使用的技巧
- activeMQ 本地测试
- 【PHP+JS】uploadify3.2 和 Ueditor 修改上传文件 大小!!