PCl 滤波汇总
1、直通滤波 passThrough
原理:对指定的某一维度进行滤波,去掉用户指定字段或范围内Or外的点云数据。
头文件为:
#include<pcl/filters/passthrough.h>
滤波代码实例:
// Create the filtering object
pcl::PassThrough<pcl::PointXYZ> pass; // 声明直通滤波
pass.setInputCloud(cloud); // 传入点云数据
pass.setFilterFieldName("z"); // 设置操作的坐标轴
pass.setFilterLimits(0.0, 3.0); // 设置坐标范围
pass.setFilterLimitsNegative(true); // 保留数据函数
pass.filter(*cloud_filtered); // 进行滤波输出
*需要注意的是,单个直通滤波器仅仅可以过滤一个坐标轴方向上的点云;*
如下解释:
pass.setFilterFieldName(“z”); // 设置操作的坐标轴
pass.setFilterLimits(0.0, 3.0); // 设置坐标范围
表示只操作Z轴点云数据,对0~3范围内的点云进行保存或者舍弃
pass.setFilterLimitsNegative(true); // 保留数据函数
false表示保存范围内的点云数据,true则相反
使用步骤:
1、创建待处理点云对象,以及存储点云处理完成后的点云对象。
2、设置点云的容量:宽+高+长×宽;
3、设置点云内所有点的xyz坐标;
4、创建PassThroughFilter对象,并设置其滤波参数。
5、将待处理点云对象作为filter的输入进行滤波;
6、得到结果:在filter对象设置的x,y,z的范围之内的点将被保留,范围之外的点将被舍弃,实现直通滤波的功能
2、体素滤波器 voxelGrid
原理:[下采样]减少点云数据集中点云的数量。对点云数据创建一个三维体素栅格(微小的空间三维立方体的集合),用每个体素重心近似代替体素中的其他点。这种方法比用体素中心来逼近的方法更慢,但它对于采样点对应曲面的表示更为准确。
头文件为:
#include <pcl/filters/voxel_grid.h>
滤波代码示例:
cout << "->正在体素下采样..." << endl;
pcl::VoxelGrid<pcl::PointXYZ> vg; //创建滤波器对象
vg.setInputCloud(cloud); //设置待滤波点云
vg.setLeafSize(0.05f, 0.05f, 0.05f); //设置体素大小
vg.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
使用步骤:
读入点云→创建滤波器对象→设置体素大小→执行滤波→保存滤波点云
3、均匀采样 uniformSampling
原理:对点云数据创建一个三维体素栅格,然后,在每个体素保留一个最接近体素中心的点,代替体素中所有点。
头文件为:
#include <pcl/keypoints/uniform_sampling.h>
滤波代码实例:
cout << "->正在均匀采样..." << endl;
pcl::UniformSampling<pcl::PointXYZ> us; //创建滤波器对象
us.setInputCloud(cloud); //设置待滤波点云
us.setRadiusSearch(0.05f); //设置滤波球体半径
us.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
使用步骤:
读入点云→创建滤波器对象→设置滤波球体半径→执行滤波→保存滤波点云
4、统计滤波器 statisticalOutlierRemoval
原理:对每一点的邻域进行统计分析,基于点到所有邻近点的距离分布特征,过滤掉一些不满足要求的离群点。该算法对整个输入进行两次迭代:在第一次迭代中,它将计算每个点到最近k个近邻点的平均距离,得到的结果符合高斯分布。接下来,计算所有这些距离的平均值 μ 和标准差 σ 以确定距离阈值 thresh_d ,且 thresh_d = μ ± k·σ。 k为标准差乘数。在下一次迭代中,如果这些点的平均邻域距离分别低于或高于该阈值,则这些点将被分类为内点或离群点。
头文件为:
#include <pcl/filters/statistical_outlier_removal.h>
滤波代码实例:
cout << "->正在进行统计滤波..." << endl;
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; //创建滤波器对象
sor.setInputCloud(cloud); //设置待滤波点云
sor.setMeanK(50); //设置查询点近邻点的个数
sor.setStddevMulThresh(1.0); //设置标准差乘数,来计算是否为离群点的阈值
//sor.setNegative(true); //默认false,保存内点;true,保存滤掉的离群点
sor.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
使用步骤:
读入点云→创建滤波器对象→设置离群点阈值→执行统计滤波→保存滤波点云
5、半径滤波器 RadiusOutlierRemoval
原理:对整个输入迭代一次,对于每个点进行半径R邻域搜索,如果邻域点的个数低于某一阈值,则该点将被视为噪声点并被移除。
头文件为:
#include <pcl/filters/radius_outlier_removal.h>
滤波代码示例:
cout << "->正在进行半径滤波..." << endl;
pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror; //创建滤波器对象
ror.setInputCloud(cloud); //设置待滤波点云
ror.setRadiusSearch(0.02); //设置查询点的半径范围
ror.setMinNeighborsInRadius(5); //设置判断是否为离群点的阈值,即半径内至少包括的点数
//ror.setNegative(true); //默认false,保存内点;true,保存滤掉的外点
ror.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
使用步骤:
读入点云→创建半径滤波器对象→设置离群点阈值→执行下采样→保存采样结果
6、条件滤波器 conditionRemoval
筛选满足特定条件的点云数据。有两种类型的条件:
[1]ConditionAnd: 所有条件都要满足
[2]ConditionOr: 满足一个条件即可
可以设置一个或多个条件对象,并为条件对象添加比较算子。条件比较算子包含三项:
[1]名称:对应于点云XYZ字段名称、RGB颜色空间、HSI颜色空间中的颜色分量等。
[2]比较运算符:GT、GE、LT、LE、EQ
[3]值:即要比较的名称的数值
比较运算符罗列:
运算符 | 含义 |
---|---|
GT | greater than 大于 |
GE | greater than or equal 大于等于 |
LT | less than 小于 |
LE | less than or equal 小于等于 |
EQ | equal 等于 |
头文件为:
#include <pcl/filters/conditional_removal.h>
滤波代码为:
cout << "->正在进行条件滤波..." << endl;
/*创建条件限定下的滤波器*/
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond
//为条件定义对象添加比较算子
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -0.1)));//添加在x字段上大于 -0.1 的比较算子
range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 1.0)));//添加在x字段上小于 1.0 的比较算子
pcl::ConditionalRemoval<pcl::PointXYZ> cr; //创建滤波器对象
cr.setCondition(range_cond); //用条件定义对象初始化
cr.setInputCloud(cloud); //设置待滤波点云
//cr.setKeepOrganized(true); //设置保持点云的结构
//cr.setUserFilterValue(5); //将过滤掉的点用(5,5,5)代替
cr.filter(*cloud_filtered); //执行滤波,保存滤波结果于cloud_filtered
setKeepOrganized(true) 解释:
保持点云结构,即有序点云经过滤波后,仍能够保持有序性。*
*setKeepOrganized默认false,即直接将滤除的点删除,从而可能改变点云的组织结构。is_dense: 1
若设置为true,再通过setuserFilterValue设置一个指定的值,被滤除的点将会被该值代替;不进行setuserFilterValue设置,则默认用nan填充被滤除的点。is_dense: 0;
使用步骤:
读入点云→创建条件对象→添加比较算子→创建条件限定下的滤波器对象→执行滤波→保存滤波结果
7、索引提取 extractIndices
原理:从原始点云中提取一组索引对应的点云子集,前提是要获取点云索引集合。
头文件为:
#include <pcl/filters/extract_indices.h>
滤波代码实例:
cout << "->正在进行点云平面子集提取..." << endl;
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients()); //创建分割时所需要的模型系数对象coefficients
pcl::PointIndices::Ptr inliers(new pcl::PointIndices()); //创建存储内点的点索引集合对象inliers
pcl::SACSegmentation<pcl::PointXYZ> seg; //创建分割对象
seg.setOptimizeCoefficients(true); //可选,对估计的模型参数进行优化处理
seg.setModelType(pcl::SACMODEL_PLANE); //设置分割模型类别
seg.setMethodType(pcl::SAC_RANSAC); //设置随即参数估计方法
seg.setMaxIterations(1000); //设置最大迭代次数
seg.setDistanceThreshold(0.01); //设置判断是否为模型内点的距离阈值
/*平面点云提取*/
///从点云中分割最大平面组成部分
seg.setInputCloud(cloud);//设置输入点云,待分割
seg.segment(*inliers, *coefficients);//引发分割实现:存储分割结果到点集合inliers;存储平面模型系数coefficients
pcl::ExtractIndices<pcl::PointXYZ> extract; //创建点云提取对象
extract.setInputCloud(cloud); //设置输入点云
extract.setIndices(inliers); //设置分割后的内点inliers为需要提取的点集
extract.setNegative(false); //设置提取内点而非外点,默认false
extract.filter(*cloud_filtered); //提取点集并存储到 cloud_filtered
使用步骤:
读入点云→平面分割获取索引集合→创建点云索引提取对象→执行索引提取→保存提取点云
8、投影滤波器 projectInliers
原理:将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波。
头文件为:
#include <pcl/filters/project_inliers.h>
滤波代码实例:
cout << "->正在平面模型投影..." << endl;
//创建 Ax+By+Cz=0 平面
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
coefficients->values.resize(4); //设置模型系数的大小
coefficients->values[0] = 1.0; //x系数
coefficients->values[1] = 1.0; //y系数
coefficients->values[2] = 1.0; //z系数
coefficients->values[3] = 0.0; //常数项
//投影滤波
pcl::ProjectInliers<pcl::PointXYZ> proj;//创建投影滤波器对象
proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型
proj.setInputCloud(cloud); //设置输入点云
proj.setModelCoefficients(coefficients);//设置模型对应的系数
proj.filter(*cloud_projected); //执行投影滤波,存储结果于cloud_projected
投影模型:
- 平面模型:SACMODEL_PLANE
- 线模型:SACMODEL_LINE
- 平面上的二维圆:SACMODEL_CIRCLE2D
- 平面上的三维圆:SACMODEL_CIRCLE3D
- 球体模型:SACMODEL_SPHERE
- 圆柱模型:SACMODEL_CYLINDER
- 圆锥模型:SACMODEL_CONE
- 圆环模型:SACMODEL_TORUS
- 平行于给定轴的一种线模型:SACMODEL_PARALLEL_LINE
- 垂直于指定轴的平面模型:SACMODEL_PERPENDICULAR_PLANE
- 三维棒分割模型:SACMODEL_STICK
使用步骤:
读入点云→创建参数化模型→设置模型系数→执行投影滤波→保存投影点云
9、模型滤波器 modelOutlierRemoval
原理:根据点到模型的距离,设置距离阈值过滤非模型点。
头文件为:
#include <pcl/filters/model_outlier_removal.h>
滤波代码实例:
cout << "->正在模型滤波..." << endl;
//设置模型系数
pcl::ModelCoefficients model_coeff;
model_coeff.values.resize(4);
model_coeff.values[0] = 1.0;
model_coeff.values[1] = 1.0;
model_coeff.values[2] = 1.0;
model_coeff.values[3] = 0.0;
///模型滤波
pcl::ModelOutlierRemoval<pcl::PointXYZ> filter; //创建模型滤波器对象
filter.setModelCoefficients(model_coeff); //为模型对象添加模型系数
filter.setThreshold(0.1); //设置判断是否为模型内点的阈值
filter.setModelType(pcl::SACMODEL_PLANE); //设置模型类别
filter.setInputCloud(cloud); //输入待滤波点云
filter.setNegative(false); //默认false,提取模型内点;true,提取模型外点
filter.filter(*cloud_filtered); //执行模型滤波,保存滤波结果于cloud_filtered
使用步骤:
读入点云→设置模型系数→创建模型滤波器对象→执行模型滤波→保存滤波结果
10、双边滤波 BilateralFilter
原理:class pcl::BilateralFilter< PointT > 类BilateralFilter是对双边滤波算法在点云上的实现,该类的实现利用的并非XYZ字段的数据进行,而是利用强度数据进行双边滤波算法的实现,所以在使用该类时点云的类型必须有强度字段,否则无法进行双边滤波处理(所以在用这个函数的时候是需要注意自己输入点云的数据格式的,需要包含点云的强度信息)。
头文件为:
#include <pcl/filters/bilateral.h>
滤波代码实例:
pcl::search::KdTree<pcl::PointXYZI>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZI>);
pcl::BilateralFilter<pcl::PointXYZI> bf;
bf.setInputCloud(cloud);
bf.setSearchMethod(tree);
bf.setHalfSize(0.1); // 设置高斯双边滤波窗口的一半大小,即搜索半径。
bf.setStdDev(0.03); // 设置标准差参数
bf.filter(*outcloud);