·而在PCL中总结了几种需要进行点云滤波处理的情况,这几种情况分别是:
(1)点云数据密度不规则需要平滑。
(2)因为遮挡等问题造成离群点需要去除。
(3)大量数据需要进行“下采样”(Downsample)。
(4)噪声数据需要去除。
·对应的解决方法是:
(1)按具体给定的规则限制过滤去除点。
(2)通过常用滤波算法修改点的部分属性。
(3)对数据进行下采样。
有很多方面也有很多种功能,比如去除噪声点、离群点、点云平滑以及空洞、数据压缩等
原始点云数据往往包含大量散列点、孤立点,在获取点云数据时 ,由于设备精度,操作者经验环
境因素带来的影响,以及电磁波的衍射性,被测物体表面性质变化和数据拼接配准操作过程的影
响,点云数据中讲不可避免的出现一些噪声,而且采样的分辨率也不同。
在点云处理流程中滤波处理作为预处理的第一步,对后续的影响比较大,只有在滤波预处理中将 噪声点,离群点,孔洞,数据压缩等按照后续处理定制,才能够更好的进行配准,特征提取,曲面重建,可视化等后续应用处理。其类似于信号处理中的滤波。
直通滤波器
直通滤波器就是根据点云的属性在点的属性上设置范围,对点进行滤波,保留范围内的或保留范围外的。
指定一个维度以及该维度下的值域
遍历点云中的每个点,判断该点在指定维度上的取值是否在值域内,删除取值不在值域内的点
遍历结束,留下的点即构成滤波后的点云。
#include <pcl/filters/passthrough.h>
// 原点云获取后进行滤波
pcl::PassThrough<pcl::PointXYZ> pass;// 创建滤波器对象
pass.setInputCloud (cloud);//设置输入点云
pass.setFilterFieldName ("z");//滤波字段名被设置为Z轴方向
pass.setFilterLimits (0.0, 1.0);//可接受的范围为(0.0,1.0)
//pass.setFilterLimitsNegative (true);//设置保留范围内 还是 过滤掉范围内
pass.filter (*cloud_filtered); //执行滤波,保存过滤结果在cloud_filter
体素滤波器(下采样)
体素滤波器可以达到向下采样同时不破坏点云本身几何结构的功能,但是会移动点的位置。 此外体素滤波器可以去除一定程度的噪音点及离群点。主要功能是用来进行降采样。
它的原理是根据输入的点云,首先计算一个能够刚好包裹住该点云的立方体,然后根据设定的分辨率,将该大立方体分割成不同的小立方体。对于每一个小立方体内的点,计算他们的质心,并用该质心的坐标来近似该立方体内的若干点。
ApproximateVoxelGrid的不同在于这种方法是利用每一个小立方体的中心来近似该立方体内的若干点。相比于 VoxelGrid,计算速度稍快,但也损失了原始点云局部形态的精细度
#include <pcl/filters/voxel_grid.h>
// VoxelGrid
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloud);
sor.setLeafSize (0.01f, 0.01f, 0.01f);
sor.filter (*cloud_filtered);
// Approximate 体素格滤波器
pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
approximate_voxel_filter.setLeafSize (0.2, 0.2, 0.2);
approximate_voxel_filter.setInputCloud (input_cloud);
approximate_voxel_filter.filter (*filtered_cloud)
均匀采样滤波器(下采样)
均匀采样滤波基本上等同于体素滤波器,但是其不改变点的位置。下采样后,其点云分布基本均匀,但是其点云的准确度要好于体素滤波,因为没有移动点的位置。
均匀采样算法:
均匀采样通过构建指定半径的球体对点云进行下采样滤波,将每一个球内距离球体中心最近的点作为下采样之后的点输出。
体素滤波是建立立方体,均匀采样是建立一个球。
#include <pcl/keypoints/uniform_sampling.h>
// Uniform sampling object.
pcl::UniformSampling<pcl::PointXYZ> filter;
filter.setInputCloud(cloud);
filter.setRadiusSearch(0.01f);
// We need an additional object to store the indices of surviving points.
pcl::PointCloud<int> keypointIndices;
filter.compute(keypointIndices);
统计滤波器(去噪)
统计滤波器主要用于去除明显离群点。 离群点特征在空间中分布稀疏。定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。根据给定均值与方差,可剔除方差之外的点。
#include <pcl/filters/statistical_outlier_removal.h>
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud (cloud);
sor.setMeanK (50); //设置考虑查询点临近点数
sor.setStddevMulThresh (1.0);//设置判断是否为离群点的阀值
sor.filter (*cloud_filtered);
// 然后,使用同样的参数再次调用该滤波器,但是利用函数setNegative设置使输出取外点,以获取离群点数据(也就是原本滤除掉的点)。
sor.setNegative (true);
sor.filter (*cloud_filtered);
条件滤波
条件滤波器通过设定滤波条件进行滤波,删除不符合用户指定的一个或者多个条件。直通滤波器是一种较简单的条件滤波器。
#include <pcl/filters/conditional_removal.h>
pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond (new pcl::ConditionAnd<pcl::PointXYZ>()); //创建条件定义对象
//添加在Z字段上大于0的比较算子
range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::GT, 0.0)));
//添加在Z字段上小于0.8的比较算子
range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8)));
// 创建滤波器并用条件定义对象初始化
pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud);
condrem.setKeepOrganized(true); //设置保持点云的结构
condrem.filter (*cloud_filtered); // 执行滤波
半径滤波(去噪)
半径滤波器以某点为中心画一个圆计算落在该圆中点的数量,当数量大于给定值时,则保留该 点,数量小于给定值则剔除该点。
主要还是用于去除离群点,在一定程度上可以用来筛选边缘点。
#include <pcl/filters/radius_outlier_removal.h>
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8);//设置半径为0.8的范围内找临近点
outrem.setMinNeighborsInRadius (2);//设置查询点的邻域点集数小于2的删除
outrem.filter (*cloud_filtered); //
投影滤波
将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波。 把三维点云投影到二维图像上,然后用图像处理的方法进行处理。
// 填充ModelCoefficients的值,使用ax+by+cz+d=0平面模型,其中 a=b=d=0,c=1 也就是X——Y平面
//定义模型系数对象,并填充对应的数据
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
coefficients->values.resize(4);
coefficients->values[0] = coefficients->values[1] = 0;
coefficients->values[2] = 1.0;
coefficients->values[3] = 0;
// 创建ProjectInliers对象,使用ModelCoefficients作为投影对象的模型参数
pcl::ProjectInliers<pcl::PointXYZ> proj; //创建投影滤波对象
proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型
proj.setInputCloud(cloud);//设置输入点云
proj.setModelCoefficients(coefficients);//设置模型对应的系数
proj.filter(*cloud_projected);//投影结果存储
模型滤波
根据点到模型的距离,设置距离阈值过滤非模型点, 基于模型的点分割操作,将模型外的点从点云中剔除。
//x^2 + y^2 + z^2 = 1
pcl::ModelCoefficients sphere_coeff;
sphere_coeff.values.resize (4);
sphere_coeff.values[0] = 0;
sphere_coeff.values[1] = 0;
sphere_coeff.values[2] = 0;
sphere_coeff.values[3] = 1;
pcl::ModelOutlierRemoval<pcl::PointXYZ> sphere_filter;
sphere_filter.setModelCoefficients (sphere_coeff);
sphere_filter.setThreshold (0.05);
sphere_filter.setModelType (pcl::SACMODEL_SPHERE);
sphere_filter.setInputCloud (cloud);
sphere_filter.filter (*cloud_sphere_filtered);
高斯滤波(去噪、平滑)
GaussianKernel是基于高斯核的卷积滤波实现,高斯过滤器相当于一个具有平滑性能的低通滤波器, 通过该类处理后的点云,相对比较平滑。
pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB> convolution;
Eigen::ArrayXf gaussian_kernel(5);
gaussian_kernel << 1.f/16, 1.f/4, 3.f/8, 1.f/4, 1.f/16;
convolution.setBordersPolicy(pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_IGNORE);
convolution.setDistanceThreshold (static_cast<float> (0.1));
convolution.setInputCloud (inputCloud);
convolution.setKernel (gaussian_kernel);
convolution.convolve(*cloud);
双边滤波(平滑)
双边滤波是一种非线性滤波器,它可以达到保持边缘、降噪平滑的效果。一定程度上拟补了高斯滤波的缺点。 双边滤波对高斯噪声效果比较好。
PCL中filters模块
pcl::PassThroughtpcl::PointXYZ pass; 直通滤波器
pcl::VoxelGrid< pcl::PointXYZ > vox;体素滤波器
pcl::StatisticalOutlierRemovalpcl::PointXYZ sor;统计滤波器
pcl::RadiusOutlierRemovalpcl::PointXYZ rador;半径滤波器
pcl::UniformSamplinqpcl::PointXYz unisam;均匀采样
pcl::ConditionalRemovalpcl::PointXYZ condr;条件滤波器
pcl::ProjectInlierspcl::PointXYZ proj;投影滤波器
pcl::ModelOutlierRemovalpcl::PointXYZ modr;模型滤波器
pcl::BilateralFilterpcl::PointXYZ bf:双边滤波
pcl::filters::GaussianKernal<PointInT,PointOutT>高斯滤
pcl::ExtractIndicespcl::PointxYz extr;索引提取
空间裁剪滤波
pcl::Clipper3Dpcl::PointXYZ
pcl::BoxCliper3Dpcl::PointXYZ
pcl::CropBoxpcl::PointXYZ
pcl::CropHullpcl::PointXYZ