* 为什么进行点云滤波处理: (1) 点云数据密度不规则需要平滑 (2) 因为遮挡等问题造成离群点需要去除 (3) 大量数据需要下采样 (4)
噪声数据需要去除
* 点云数据去噪滤波方法: 双边滤波、高斯滤波、分箱去噪、KD-Tree、直通滤波、随机采样一致性滤波等
* 方法定义以及适用性:
1.双边滤波:将距离和空间结构结合去噪,效果较好。只适用于有序点云


2.高斯滤波(标准差去噪):适用于呈正态分布的数据。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最近的k个点平均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除3∑之外的点。

3.分箱去噪:适用于呈偏态分布的数据。

4.dbscan:基于聚类原理去噪,复杂度较高。

5.KD-Tree(孤立森林):复杂度高。构建KD树,随机取点求平均距离d,删掉所有大于2d的点。适用于无序点云去噪。

6.条件滤波:条件滤波器通过设定滤波条件进行滤波,有点分段函数的味道,当点云在一定范围则留下,不在则舍弃。

7.直通滤波

8.随机采样一致性滤波

9.体素滤波:

体素的概念类似于像素,使用AABB包围盒将点云数据体素化,一般体素越密集的地方信息越多,噪音点及离群点可通过体素网格去除。另一方面如果使用高分辨率相机等设备对点云进行采集,往往点云会较为密集。过多的点云数量会对后续分割工作带来困难。体素滤波器可以达到向下采样同时不破坏点云本身几何结构的功能。

10.半径滤波:

半径滤波器与统计滤波器相比更加简单粗暴。以某点为中心画一个圆计算落在该圆中点的数量,当数量大于给定值时,则保留该点,数量小于给定值则剔除该点。此算法运行速度快,依序迭代留下的点一定是最密集的,但是圆的半径和圆内点的数目都需要人工指定。
原理以及核心代码:
直通滤波器:对于在空间分布有一定空间特征的点云数据,比如使用线结构光扫描的方式采集点云,沿z向分布较广,但x,y向的分布处于有限范围内。此时可使用直通滤波器,确定点云在x或y方向上的范围,可较快剪除离群点,达到第一步粗处理的目的。
// Create the filtering object pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud (cloud); pass.setFilterFieldName ("z"); pass.setFilterLimits
(0.0, 1.0); //pass.setFilterLimitsNegative (true); pass.filter
(*cloud_filtered); 体素滤波器: // Create the filtering object
pcl::VoxelGrid<pcl::PCLPointCloud2> sor; sor.setInputCloud (cloud);
sor.setLeafSize (0.01f, 0.01f, 0.01f); sor.filter (*cloud_filtered); 统计滤波器: //
Create the filtering object pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud (cloud); sor.setMeanK (50); sor.setStddevMulThresh (1.0);
sor.filter (*cloud_filtered); 半径滤波器: // build the filter
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem; outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8); outrem.setMinNeighborsInRadius (2); // apply
filter outrem.filter (*cloud_filtered);
一般来说,滤波对应的方案有如下几种:
(1)按照给定的规则限制过滤去除点 (2)通过常用滤波算法修改点的部分属性 (3)对数据进行下采样
查阅的相关资料:

PCL点云滤波去噪:

https://blog.csdn.net/qq_30815237/article/details/86294496
<https://blog.csdn.net/qq_30815237/article/details/86294496>

https://mp.weixin.qq.com/s/9pxff6LwcecDHsx4kI34sw
<https://mp.weixin.qq.com/s/9pxff6LwcecDHsx4kI34sw>

PCL中关于点云滤波的所有函数:

http://docs.pointclouds.org/trunk/group__filters.html
<http://docs.pointclouds.org/trunk/group__filters.html>

具体实现:
#include<iostream> #include<pcl/point_types.h>
#include<pcl/filters/passthrough.h> //直通滤波器头文件
#include<pcl/filters/voxel_grid.h> //体素滤波器头文件
#include<pcl/filters/statistical_outlier_removal.h> //统计滤波器头文件 #include
<pcl/filters/conditional_removal.h> //条件滤波器头文件 #include
<pcl/filters/radius_outlier_removal.h> //半径滤波器头文件 int main(int argc, char**
argv) { /*创建点云数据集。*/ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new
pcl::PointCloud<pcl::PointXYZ>); cloud->width = 500; cloud->height = 1;
cloud->points.resize(cloud->width*cloud->height); std::cout << "创建原始点云数据" <<
std::endl; for (size_t i = 0; i < cloud->points.size(); ++i) {
cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].y =
1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand() /
(RAND_MAX + 1.0f); } for (size_t i = 0; i < cloud->points.size(); i++) {
std::cerr << " " << cloud->points[i].x << " " << cloud->points[i].y << " " <<
cloud->points[i].z << std::endl; } std::cout << "原始点云数据点数:" <<
cloud->points.size() << std::endl << std::endl; /*方法一:直通滤波器对点云进行处理。*/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_after_PassThrough(new
pcl::PointCloud<pcl::PointXYZ>); pcl::PassThrough<pcl::PointXYZ> passthrough;
passthrough.setInputCloud(cloud);//输入点云
passthrough.setFilterFieldName("z");//对z轴进行操作 passthrough.setFilterLimits(0.0,
400.0);//设置直通滤波器操作范围
//passthrough.setFilterLimitsNegative(true);//true表示保留范围内,false表示保留范围外
passthrough.filter(*cloud_after_PassThrough);//执行滤波,过滤结果保存在
cloud_after_PassThrough std::cout << "直通滤波后点云数据点数:" <<
cloud_after_PassThrough->points.size() << std::endl; /*方法二:体素滤波器实现下采样*/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_after_voxelgrid(new
pcl::PointCloud<pcl::PointXYZ>);// pcl::VoxelGrid<pcl::PointXYZ> voxelgrid;
voxelgrid.setInputCloud(cloud);//输入点云数据 voxelgrid.setLeafSize(10.0f, 10.0f,
10.0f);//AABB长宽高 voxelgrid.filter(*cloud_after_voxelgrid); std::cout <<
"体素化网格方法后点云数据点数:" << cloud_after_voxelgrid->points.size() << std::endl;
/*方法三:统计滤波器滤波*/ pcl::PointCloud<pcl::PointXYZ>::Ptr
cloud_after_StatisticalRemoval(new pcl::PointCloud<pcl::PointXYZ>);//
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> Statistical;
Statistical.setInputCloud(cloud); Statistical.setMeanK(20);//取平均值的临近点数
Statistical.setStddevMulThresh(5);//临近点数数目少于多少时会被舍弃
Statistical.filter(*cloud_after_StatisticalRemoval); std::cout <<
"统计分析滤波后点云数据点数:" << cloud_after_StatisticalRemoval->points.size() << std::endl;
/*方法四:条件滤波器*/ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_after_Condition(new
pcl::PointCloud<pcl::PointXYZ>); pcl::ConditionAnd<pcl::PointXYZ>::Ptr
range_condition(new pcl::ConditionAnd<pcl::PointXYZ>());
range_condition->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
//GT表示大于等于
range_condition->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
//LT表示小于等于 pcl::ConditionalRemoval<pcl::PointXYZ> condition;
condition.setCondition(range_condition); condition.setInputCloud(cloud); //输入点云
condition.setKeepOrganized(true); condition.filter(*cloud_after_Condition);
std::cout << "条件滤波后点云数据点数:" << cloud_after_Condition->points.size() <<
std::endl; /*方法五:半径滤波器*/ pcl::PointCloud<pcl::PointXYZ>::Ptr
cloud_after_Radius(new pcl::PointCloud<pcl::PointXYZ>);
pcl::RadiusOutlierRemoval<pcl::PointXYZ> radiusoutlier; //创建滤波器
radiusoutlier.setInputCloud(cloud); //设置输入点云
radiusoutlier.setRadiusSearch(100); //设置半径为100的范围内找临近点
radiusoutlier.setMinNeighborsInRadius(2); //设置查询点的邻域点集数小于2的删除
radiusoutlier.filter(*cloud_after_Radius); std::cout << "半径滤波后点云数据点数:" <<
cloud_after_Radius->points.size() << std::endl; int a; std::cin >> a; return
(0); }
原博文:

https://blog.csdn.net/yanghan742915081/article/details/85092643
<https://blog.csdn.net/yanghan742915081/article/details/85092643>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信