当前位置:   article > 正文

学习点云和pcl算法初步②_点云平滑

点云平滑

**

点云初步学习②

主要工具:visual studio 2019 和cloudcompare(自行编译)
  • 1

1.点云预处理(滤波):①点云去噪②点云的简化

原因: (1) 点云数据密度不规则需要平滑
      (2) 因为遮挡等问题造成离群点需要去除
      (3) 大量数据需要下采样
      (4) 噪声数据需要去除
  • 1
  • 2
  • 3
  • 4

①点云去噪:去除离群点和点云的平滑处理

去除离群点:①半径滤波②统计滤波
点云的平滑处理:①双边滤波 ②导向滤波
  • 1
  • 2

1. 直通滤波器(PassThrough 滤波) pcl::PassThroughpcl::PointXYZ pass

最简单的一种滤波器,它的作用是过滤掉在指定维度方向上取值不在给定值域内的点。直通滤波器的实现原理如下:首先,指定一个维度以及该维度下的值域,其次,遍历点云中的每个点,判断该点在指定维度上的取值是否在值域内,删除取值不在值域内的点,最后,遍历结束,留下的点即构成滤波后的点云。直通滤波器简单高效,适用于消除背景等操作。

#include <pcl/filters/passthrough.h>
  如果使用线结构光扫描的方式采集点云,必然物体沿z向分布较广,
  但x,y向的分布处于有限范围内。
  此时可使用直通滤波器,确定点云在x或y方向上的范围,
  可较快剪除离群点,达到第一步粗处理的目的。

  // 创建点云对象 指针
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  // 原点云获取后进行滤波
  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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.体素滤波器(下采样)
使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,并同时保存点云的形状特征,在提高配准,曲面重建,形状识别等算法速度中非常实用。

1.VoxelGrid原理是根据输入的点云,首先计算一个能够刚好包裹住点云的立方体,然后根据设定的分辨率,
将该大立方体分割成不同的小立方体,对于每个小立方体的点,计算他们的质心(重心),并用质心的坐标来近似该立方体内的若干点。

#include <pcl/filters/voxel_grid.h>
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud(cloud);
sor.setLeafSize(0.01f,0.01f,0.01f);//设置格子大小
sor.filter(*cloud_filtered)//保留滤波后的点
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.ApproximateVoxelGrid(近似体素)的不同在于利用每个小立方体的中心来近似表示该立方体的若干点,相比于VoxelGrid,
计算速度快,但损失了一部分点云局部形态的精细度。
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);//保留滤波后的点
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.均匀采样滤波器(下采样)

这个类基本上是相同的,但它输出的点云索引是选择的关键点,是在计算描述子的常见方式。均匀采样滤波器不改变点的位置,下采样后,点云分布基本均匀,
  原理同体素格 (正方体立体空间内 保留一个点(重心点))
  而 均匀采样:半径球体内 保留一个点(重心点)
  #include <pcl/filters/uniform_sampling.h>//均匀采样
  ----------------------------------------------------------
   // 创建滤波器对象 Create the filtering object
      pcl::UniformSampling<pcl::PointXYZ> filter;// 均匀采样
      filter.setInputCloud(cloud_ptr);//输入点云
      filter.setRadiusSearch(0.01f);//设置半径
      //pcl::PointCloud<int> keypointIndices;// 索引
      filter.filter(*cloud_filtered_ptr);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

4.增采样 setUpsamplingMethod

  增采样是一种表面重建方法,当你有比你想象的要少的点云数据时,
  增采样可以帮你恢复原有的表面(S),通过内插你目前拥有的点云数据,
  这是一个复杂的猜想假设的过程。所以构建的结果不会百分之一百准确,
  但有时它是一种可选择的方案。
  所以,在你的点云云进行下采样时,一定要保存一份原始数据!
  #include <pcl/surface/mls.h>
  ------------
  // 滤波对象
      pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointXYZ> filter;
      filter.setInputCloud(cloud);
      //建立搜索对象
      pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree;
      filter.setSearchMethod(kdtree);
      //设置搜索邻域的半径为3cm
      filter.setSearchRadius(0.03);
      // Upsampling 采样的方法有 DISTINCT_CLOUD, RANDOM_UNIFORM_DENSITY
      filter.setUpsamplingMethod(pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointXYZ>::SAMPLE_LOCAL_PLANE);
      // 采样的半径是
      filter.setUpsamplingRadius(0.03);
      // 采样步数的大小
      filter.setUpsamplingStepSize(0.02);

      filter.process(*filteredCloud);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

5.统计滤波器 statisticalOutlierRemoval
统计滤波器的主要思想是假设点云中所有的点与其最近的k个邻居点的平均距离满足高斯分布,那么,根据均值和方差可确定一个距离阈值,当某个点与其最近k个点的平均距离大于这个阈值时,判定该点为离群点并去除。

统计滤波器的实现原理如下:首先,遍历点云,计算每个点与其最近的k个邻居点之间的平均距离;其次,计算所有平均距离的均值μ与标准差σ,则距离阈值dmax可表示为dmax=μ+α×σ,α是一个常数,可称为比例系数,它取决于邻居点的数目;最后,再次遍历点云,剔除与k个邻居点的平均距离大于dmax的点。
请添加图片描述

// 创建点云对象 指针
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  // 源点云读取 获取 后
  // 创建滤波器,对每个点分析的临近点的个数设置为50 ,并将标准差的倍数设置为1  这意味着如果一
  //个点的距离超出了平均距离一个标准差以上,则该点被标记为离群点,并将它移除,存储起来
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;//创建滤波器对象
  sor.setInputCloud (cloud);                        //设置待滤波的点云
  sor.setMeanK (50);                                //设置在进行统计时考虑查询点临近点数
  sor.setStddevMulThresh (1.0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/267967
推荐阅读