点云滤波方法

什么是点云滤波?

点云滤波作为常见的点云处理算法,一般是点云处理的第一步,对后续处理有很重要作用。滤波
有很多方面也有很多种功能,比如去除噪声点、离群点、点云平滑以及空洞、数据压缩等。

为什么要点云滤波?

原始点云数据往往包含大量散列点、孤立点,在获取点云数据时 ,由于设备精度,操作者经验环
境因素带来的影响,以及电磁波的衍射性,被测物体表面性质变化和数据拼接配准操作过程的影
响,点云数据中讲不可避免的出现一些噪声,而且采样的分辨率也不同。

直通滤波器

直通滤波器就是根据点云的属性在点的属性上设置范围,对点进行滤波,保留范围内的或保留范围外的

(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_filtered

体素滤波器(下采样)

体素滤波器可以达到向下采样同时不破坏点云本身几何结构的功能,但是会移动点的位置。此外体素滤波器可以去除一定程度的噪音点及离群点。主要功能是用来进行降采样。
(1)它的原理是根据输入的点云,首先计算一个能够刚好包裹住该点云的立方体,然后根据设定的分辨率,将该大立方体分割成不同的小立方体。对于每一个小立方体内的点,计算他们的质心,并用该质心的坐标来近似该立方体内的若干点。
(2)ApproximateVoxelGrid的不同在于这种方法是利用每一个小立方体的中心来近似该立方体内的若干点。相比于VoxelGrid,计算速度稍快,但也损失了原始点云局部形态的精细度。

#include <pcl/filters/voxel_grid.h>
// 第一种(推荐):VoxelGrid
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;//在给定的点云上组装一个3D网格,进行降采样和过滤
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); // 执行滤波

半径滤波(去噪)

半径滤波器以某点为中心画一个圆计算落在该圆中点的数量,当数量大于给定值时,则保留该点,数量小于给定值则剔除该点。径内必须要有两个邻居点,此点才会保存主要还是用于去除离群点,在一定程度上可以用来筛选边缘点。

14
公众号:3D视觉工坊半径滤波(去噪)
半径滤波器以某点为中心画一个圆计算落在该圆中点的数量,当数量大于给定值时,则保留该
点,数量小于给定值则剔除该点。
#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); //在半径为0.8 在此半
径内必须要有两个邻居点,此点才会保存

投影滤波

将点投影到一个参数化模型上,这个参数化模型可以是平面、圆球、圆柱、锥形等进行投影滤波。
把三维点云投影到二维图像上,然后用图像处理的方法进行处理。

// 填充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::PointX
YZRGB>::BORDERS_POLICY_IGNORE);
convolution.setDistanceThreshold (static_cast<float> (0.1));
convolution.setInputCloud (inputCloud);
convolution.setKernel (gaussian_kernel);
convolution.convolve(*cloud);

双边滤波(平滑)

双边滤波是一种非线性滤波器,它可以达到保持边缘、降噪平滑的效果。一定程度上拟补了高斯滤波的缺点。双边滤波对高斯噪声效果比较好。

pcl::FastBilateralFilter<pcl::PointXYZ> fbf;

一篇值得看的参考文献和在线双边滤波,有源码

IPOL Journal · The Bilateral Filter for Point Clouds

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值