转载自:https://blog.csdn.net/weixin_46098577/article/details/114385690
PCL中点云滤波模块提供了很多灵活实用的滤波处理算法,例如:直通滤波、统计滤波、双边滤波、高斯滤波、基于随机采样一致性滤波等。同时,PCL中总结了几种需要进行点云滤波处理的情况,如下:
点云数据密度不规则需要平滑
因遮挡等问题噪声的离群点需要去除
数据冗余需要下采样
噪声数据需要去除
对应的方法如下:
按具体给定的规则过滤点
通过滤波算法修改点的部分属性
点云数据下采样
下面对PCL各种滤波方法做一些归纳总结,方便日后使用。
一、直通滤波
针对点云某一维度,去掉指定范围内(或外)的点。
流程:读入点云→创建滤波器对象→设置滤波字段范围→执行滤波→保存滤波结果
#include <pcl/filters/passthrough.h>
二、VoxelGrid体素滤波器
对点云数据创建一个三维体素栅格(微小的空间三维立方体的集合),用每个体素重心近似代替体素中的其他点。这种方法比用体素中心来逼近的方法更慢,但它对于采样点对应曲面的表示更为准确。
流程:读入点云→创建滤波器对象→设置体素大小→执行滤波→保存滤波点云
#include <pcl/filters/voxel_grid.h
滤波前后对比
三、UniformSampling均匀采样
对点云数据创建一个三维体素栅格,然后,在每个体素保留一个最接近体素中心的点,代替体素中所有点。
流程:读入点云→创建滤波器对象→设置滤波球体半径→执行滤波→保存滤波点云
#include <pcl/keypoints/uniform_sampling.h>
滤波前后对比
四、StatisticalOutlierRemoval统计滤波器
对每一点的邻域进行统计分析,基于点到所有邻近点的距离分布特征,过滤掉一些不满足要求的离群点。该算法对整个输入进行两次迭代:在第一次迭代中,它将计算每个点到最近k个近邻点的平均距离,得到的结果符合高斯分布。接下来,计算所有这些距离的平均值 μ 和标准差 σ 以确定距离阈值 thresh_d ,且 thresh_d = μ ± k·σ。 k为标准差乘数。在下一次迭代中,如果这些点的平均邻域距离分别低于或高于该阈值,则这些点将被分类为内点或离群点。
流程:读入点云→创建滤波器对象→设置离群点阈值→执行统计滤波→保存滤波点云
#include <pcl/filters/statistical_outlier_removal.h>
滤波前后对比
五、RadiusOutlierRemoval半径滤波器
对整个输入迭代一次,对于每个点进行半径R邻域搜索,如果邻域点的个数低于某一阈值,则该点将被视为噪声点并被移除。
流程:读入点云→创建半径滤波器对象→设置离群点阈值→执行下采样→保存采样结果
#include <pcl/filters/radius_outlier_removal.h>
滤波前后对比
六、ConditionRemoval条件滤波器
筛选满足特定条件的点云数据。有两种类型的条件:
ConditionAnd: 所有条件都要满足
ConditionOr: 满足一个条件即可
可以设置一个或多个条件对象,并为条件对象添加比较算子。条件比较算子包含三项:
(1)名称:对应于点云XYZ字段名称、RGB颜色空间、HSI颜色空间中的颜色分量等。
(2) 比较运算符:GT、GE、LT、LE、EQ
运算符 含义
GT greater than 大于
GE greater than or equal 大于等于
LT less than 小于
LE less than or equal 小于等于
EQ equal 等于
比较运算符源码
switch (this->op_) { case pcl::ComparisonOps::GT : return (compare_result > 0); case pcl::ComparisonOps::GE : return (compare_result >= 0); case pcl::ComparisonOps::LT : return (compare_result < 0); case pcl::ComparisonOps::LE : return (compare_result <= 0); case pcl::ComparisonOps::EQ : return (compare_result == 0); default: PCL_WARN ("[pcl::FieldComparison::evaluate] unrecognized op_!\n"); return (false); }
值:即要比较的名称的数值
流程:读入点云→创建条件对象→添加比较算子→创建条件限定下的滤波器对象→执行滤波→保存滤波结果
#include <pcl/filters/conditional_removal.h>
滤波前后对比
setKeepOrganized(true) 解释:
保持点云结构,即有序点云经过滤波后,仍能够保持有序性。
setKeepOrganized默认false,即直接将滤除的点删除,从而可能改变点云的组织结构。is_dense: 1
若设置为true,再通过setuserFilterValue设置一个指定的值,被滤除的点将会被该值代替;不进行setuserFilterValue设置,则默认用nan填充被滤除的点。is_dense: 0;
七、ExtractIndices索引提取
从原始点云中提取一组索引对应的点云子集,前提是要获取点云索引集合。
流程:读入点云→平面分割获取索引集合→创建点云索引提取对象→执行索引提取→保存提取点云
#include <pcl/filters/extract_indices.h>
滤波前后对比
八、投影滤波器
将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波。
参数化模型投影点云,以平面投影为例:读入点云→创建参数化模型→设置模型系数→执行投影滤波→保存投影点云
#include <pcl/filters/project_inliers.h>
投影前后对比
九、ModelOutlierRemoval模型滤波器
根据点到模型的距离,设置距离阈值过滤非模型点
流程:读入点云→设置模型系数→创建模型滤波器对象→执行模型滤波→保存滤波结果
滤波前后对比
十、空间裁剪滤波
10.1 CropHull滤波器
获取点云在 3D 封闭曲面上或 2D 封闭多边形内或外部的点。
流程:读入点云→设置封闭范围顶点→创建凸包对象→执行CropHull滤波→保存滤波点云
需要注意的是 ,setDimension()和CH.setDim()的维度应保持一致
当维度设置为2时,封闭区域为2D封闭多边形,只有X和Y两个维度。因此,该封闭多边形在三维空间中表示为垂直于XOY面的竖直曲面。得到的是曲面内部或外部的点云。
当维度设置为3时,封闭区域为3D封闭曲面,仅得到位于该封闭曲面上的点。
十一 、BilateralFilter 双边滤波器
class pcl::BilateralFilter< PointT > 类BilateralFilter是对双边滤波算法在点云上的实现,该类的实现利用的并非XYZ字段的数据进行,而是利用强度数据进行双边滤波算法的实现,所以在使用该类时点云的类型必须有强度字段,否则无法进行双边滤波处理(所以在用这个函数的时候是需要注意自己输入点云的数据格式的,需要包含点云的强度信息)
#include <pcl/filters/bilateral.h>
注:只是代码跑通,并不适用于1.pcd文件(1.pcd文件只有XYZ字段,没有强度字段)