PCL滤波介绍(1)
在获取点云数据时 ,由于设备精度,操作者经验环境因素带来的影响,以及电磁波的衍射特性,被测物体表面性质变化和数据拼接配准操作过程的影响,点云数据中讲不可避免的出现一些噪声。在点云处理流程中滤波处理作为预处理的第一步,对后续的影响比较大,只有在滤波预处理中将噪声点 ,离群点,孔洞,数据压缩等按照后续处理定制,才能够更好的进行配准,特征提取,曲面重建,可视化等后续应用处理,PCL中点云滤波模块提供了很多灵活实用的滤波处理算法,例如:双边滤波,高斯滤波,条件滤波,直通滤波,基于随机采样一致性滤波,
PCL中点云滤波的方案
PCL中总结了几种需要进行点云滤波处理情况,这几种情况分别如下:
(1) 点云数据密度不规则需要平滑
(2) 因为遮挡等问题造成离群点需要去除
(3) 大量数据需要下采样
(4) 噪声数据需要去除
对应的方案如下:
(1)按照给定的规则限制过滤去除点
(2) 通过常用滤波算法修改点的部分属性
(3)对数据进行下采样
双边滤波算法是通过取临近采样点和加权平均来修正当前采样点的位置,从而达到滤波效果,同时也会有选择剔除与当前采样点“差异”太大的相邻采样点,从而保持原特征的目的
|
Classes |
|
|
pcl::ApproximateVoxelGrid< PointT > 类ApproximateVoxelGrid根据给定的点云形成三维体素栅格,并利用所有体素的中心点近似体素 |
|
|
中包含的点集,这样完成下采样得到滤波结果,该类比较合适对海量点云数据在处理前进行压缩,提高算法效率 |
|
|
class |
pcl::BilateralFilter< PointT > 类BilateralFilter是对双边滤波算法在点云上的实现,该类的实现利用的并非XYZ字段的数据进行,而是利用 |
|
强度数据进行双边滤波算法的实现,所以在使用该类时点云的类型必须有强度字段,否则无法进行双边滤波处理, |
|
|
class |
pcl::BoxClipper3D< PointT >实现用一个原点为中心,XYZ各个方向尺寸为2 经过用户指定的仿射变换的立方体进行空间裁剪,通过设置一个仿射变换矩阵先对立方体进行变换处理,之后输出仿射变换后落在该立方体内的点集 |
|
class |
pcl::Clipper3D< PointT >是3D空间裁剪对象的基类 |
|
class |
pcl::ConditionalRemoval< PointT >实现过滤满足一定的条件的点云数据,非常灵活,可以设置滤波条件 |
|
class |
pcl::filters::Convolution< PointIn, PointOut > 实现卷积滤波处理 |
|
class |
pcl::filters::ConvolvingKernel< PointInT, PointOutT > 是所有卷积核的基类 |
|
class |
pcl::filters::GaussianKernel< PointInT, PointOutT > 是基于高斯核的卷积滤波实现 高斯滤波相当于一个具有平滑性能的低通滤波器 |
|
class |
pcl::filters::GaussianKernelRGB< PointInT, PointOutT > 是附加RGB通道基于高斯核的卷积滤波实现,不仅考虑空间XYZ而且考虑RGB |
|
class |
pcl::CropBox< PointT > 过滤掉在用户给定立方体内的点云数据 |
|
class |
pcl::CropHull< PointT > 过滤在给定三维封闭曲面或二维封闭多边形内部或外部的点云数据 |
|
class |
pcl::ExtractIndices< PointT > 从一个点云中提取索引 |
|
class |
pcl::Filter< PointT > 是滤波模块最重要的类 其他所有的滤波模块的类都从它继承。 |
|
。。。。。。。。。。(还有很多) |
|
应用实例
(1)在PCL 中使用直通滤波器对点云进行滤波处理
代码解析如下
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h> int
main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>); //生成并填充点云
cloud->width = ;
cloud->height = ;
cloud->points.resize (cloud->width * cloud->height); for (size_t i = ; i < cloud->points.size (); ++i) //填充数据
{
cloud->points[i].x = * rand () / (RAND_MAX + 1.0f);
cloud->points[i].y = * rand () / (RAND_MAX + 1.0f);
cloud->points[i].z = * rand () / (RAND_MAX + 1.0f);
} std::cerr << "Cloud before filtering: " << std::endl; //打印
for (size_t i = ; i < cloud->points.size (); ++i)
std::cerr << " " << cloud->points[i].x << " "
<< cloud->points[i].y << " "
<< cloud->points[i].z << std::endl;
/************************************************************************************
创建直通滤波器的对象,设立参数,滤波字段名被设置为Z轴方向,可接受的范围为(0.0,1.0)
即将点云中所有点的Z轴坐标不在该范围内的点过滤掉或保留,这里是过滤掉,由函数setFilterLimitsNegative设定
***********************************************************************************/
// 设置滤波器对象
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud); //设置输入点云
pass.setFilterFieldName ("z"); //设置过滤时所需要点云类型的Z字段
pass.setFilterLimits (0.0, 1.0); //设置在过滤字段的范围
//pass.setFilterLimitsNegative (true); //设置保留范围内还是过滤掉范围内
pass.filter (*cloud_filtered); //执行滤波,保存过滤结果在cloud_filtered std::cerr << "Cloud after filtering: " << std::endl; //打印
for (size_t i = ; i < cloud_filtered->points.size (); ++i)
std::cerr << " " << cloud_filtered->points[i].x << " "
<< cloud_filtered->points[i].y << " "
<< cloud_filtered->points[i].z << std::endl; return ();
}
由于随机生成的点云,所以每次运行结果不一样,但是都会将点云中Z坐标在(0,1)范围外的点过滤掉

(2)使用VoxelGrid滤波器对点云进行下采样
使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,并同时保存点云的形状特征,在提高配准,曲面重建,形状识别等算法速度中非常实用,PCL是实现的VoxelGrid类通过输入的点云数据创建一个三维体素栅格,容纳后每个体素内用体素中所有点的重心来近似显示体素中其他点,这样该体素内所有点都用一个重心点最终表示,对于所有体素处理后得到的过滤后的点云,这种方法比用体素中心逼近的方法更慢,但是对于采样点对应曲面的表示更为准确。
代码解释
voxel_grid.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h> int
main (int argc, char** argv)
{ pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2 ());
pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ()); //点云对象的读取
pcl::PCDReader reader; reader.read ("table_400.pcd", *cloud); //读取点云到cloud中 std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
<< " data points (" << pcl::getFieldsList (*cloud) << ")."; /******************************************************************************
创建一个叶大小为1cm的pcl::VoxelGrid滤波器,
**********************************************************************************/
pcl::VoxelGrid<pcl::PCLPointCloud2> sor; //创建滤波对象
sor.setInputCloud (cloud); //设置需要过滤的点云给滤波对象
sor.setLeafSize (0.01f, 0.01f, 0.01f); //设置滤波时创建的体素体积为1cm的立方体
sor.filter (*cloud_filtered); //执行滤波处理,存储输出 std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
<< " data points (" << pcl::getFieldsList (*cloud_filtered) << ")."; pcl::PCDWriter writer;
writer.write ("table_scene_lms400_downsampled.pcd", *cloud_filtered,
Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false); return ();
}
从输出的结果可以看出,过滤后的数据量大大减小了。打印结果如下

显示的结果图可以看出对比

原始点云与滤波后的点云可视化结果,明显的可以看出来,点的密度大小与整齐程度不同,虽然处理后的数据量大大减小,但是很明显所含有的形状特征和空间结构信息与原始点云差不多。
微信公众号号可扫描二维码一起共同学习交流

未完待续***************************88
PCL滤波介绍(1)的更多相关文章
- PCL滤波介绍(3)
(1)从一个点云中提取索引 如何使用一个,基于某一分割算法提取点云中的一个子集. 代码解析 #include <iostream> #include <pcl/ModelCoeffi ...
- PCL滤波介绍(2)
(1)使用statisticalOutlierRemoval滤波器移除离群点 使用统计分析技术,从一个点云数据中集中移除测量噪声点(也就是离群点)比如:激光扫描通常会产生密度不均匀的点云数据集,另外测 ...
- 图像处理之均值滤波介绍及C算法实现
1 均值滤波介绍 滤波是滤波是将信号中特定波段频率滤除的操作,是从含有干扰的接收信号中提取有用信号的一种技术. 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临 ...
- 图像处理之中值滤波介绍及C实现
1 中值滤波概述 中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号平滑处理技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值. 中值滤波的基本原理是把数字图像或数字序 ...
- PCL—低层次视觉—点云滤波(初步处理)
点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之前必须要进行的预处理.其作用类似于信号处理中的滤波,但实现手段却和信号处理不一样.我认为原因有以下几个方面: ...
- PCL—点云滤波(初步处理)
博客转载自:http://www.cnblogs.com/ironstark/p/4991232.html 点云滤波的概念 点云滤波是点云处理的基本步骤,也是进行 high level 三维图像处理之 ...
- PCL学习笔记(一)
由于项目需要,开始学习一下HP公司的PCL打印语言,发现这方面的中文资料非常少,我做下记录也为后人提供便利. 关于PCL的介绍可以参考wiki百科 http://zh.wikipedia.org/zh ...
- PCL基础3.2-如何编写新的PCL类
1.文件名为mainBilateralFilter.cpp的文件内容如下 #include <pcl/point_types.h> #include <pcl/io/pcd_io.h ...
- opencv-11-中值滤波及自适应中值滤波
开始之前 在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行 ...
随机推荐
- unity, Gizmos.DrawMesh一个坑
错误写法(画不出来): void OnDrawGizmos(){ Mesh mesh=new Mesh(); mesh.vertices=... mesh.triangles=... //mesh.R ...
- unity, particle system Emit from Edge
- shell 计算时间差
#!/bin/bash #date_5='awk 'BEGIN{print strftime("%H:%M",(systime()-300))}'' #ps -ef | grep ...
- Java常考面试题(四)
序言 双十一那天去我女朋友那了,11.11到11.13 漏了两天的内容,今天中午刚回来的,赶紧补一下前两天漏下的博文,我相信,坚持下来,会有成长的,等到出去实习那一天,肯定会很有帮助,会感谢现在自己的 ...
- Introducing Project Kinect for Azure
https://www.linkedin.com/pulse/introducing-project-kinect-azure-alex-kipman/ Hello everyone! Microso ...
- JavaScript 模块化简述
JavaScript 模块化简述 前言 关于模块化,最直接的表现就是我们写的 require 和 import 关键字,如果查阅相关资料,就一定会遇到 CommonJS .CMD AMD 这些名词,以 ...
- Python模块学习——tempfile
主要有以下几个函数: tempfile.TemporaryFile 如何你的应用程序需要一个临时文件来存储数据,但不需要同其他程序共享,那么用TemporaryFile函数创建临时文件是最好的选择.其 ...
- Docker 入门 --- 命令总结
Docker命令总结 前言 命令来自于官网的get-started教程,放在这里自用 part-1 ## List Docker CLI commands docker docker containe ...
- Windows / VS下不同类型变量转换
[时间:2016-07] [状态:Open] [关键词:windows,vs,mfc,类型转换] 在实际编码中经常遇到不同类型及编码方式的字符串.变量之间的转换,比如Unicode->char. ...
- java中Class.getResource用法(用于配置文件的读取)
https://www.cnblogs.com/keyi/p/6282838.html ******************************************** 用JAVA获取文件,听 ...