在PCL中使用直通滤波器对点云进行滤波处理

      在激光点云的采集过程中,因为设备和环境因素的影响,会出现一些噪点信息,例如点云数据中存在不合常理的坐标值;同时由于采集设备的有效距离的影响,对于距离较远的目标其反射的激光点云数据呈现过度离散的状态,不具备识别的可能,因此本文从目标对象本身的三维空间大小出发,通过统计方法对激光点云数据做一些过滤处理操作,过滤噪点和距离过远的点。

PCL官网代码是对随机产生的5个数据按设置参数进行滤波,代码如下:

#include <iostream>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int
 main (int argc, char** argv)
{ srand(time(0));
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  //填入点云数据
  cloud->width  = 5;//设置点云宽度
  cloud->height = 1;//设置点云高度,无序点云默认为1
  cloud->points.resize (cloud->width * cloud->height);
  for (size_t i = 0; i < cloud->points.size (); ++i)//为点云填充数据
  {
    cloud->points[i].x = rand () / (RAND_MAX + 1.0f)-0.5;
    cloud->points[i].y = rand () / (RAND_MAX + 1.0f)-0.5;
    cloud->points[i].z = rand () / (RAND_MAX + 1.0f)-0.5;
  }
  std::cout << "Cloud before filtering: " << std::endl;
  for (size_t i = 0; i < cloud->points.size (); ++i)
    std::cout << "    " << cloud->points[i].x << " " 
                        << cloud->points[i].y << " " 
                        << cloud->points[i].z << std::endl;
  // 创建滤波器对象
  pcl::PassThrough<pcl::PointXYZ> pass;//设置滤波器对象
  pass.setInputCloud (cloud);//设置输入点云
  pass.setFilterFieldName ("z");//设置过滤时所需要点云类型的z字段
  pass.setFilterLimits (-2.5, 1.0);//设置在过滤字段上的范围
  //pass.setFilterLimitsNegative (true);//设置保留范围内的or过滤掉范围内的
  pass.filter (*cloud_filtered);//执行滤波,保存过滤结果在cloud_filtered


  std::cout<< "Cloud after filtering: " << std::endl;
  for (size_t i = 0; i < cloud_filtered->points.size (); ++i)
    std::cout << "    " << cloud_filtered->points[i].x << " " 
                        << cloud_filtered->points[i].y << " " 
                        << cloud_filtered->points[i].z << std::endl;
  system("pause");
  return (0);

}

运行结果:

在PCL中使用直通滤波器对点云进行滤波处理

结果显示:随机产生点云数据,点云中Z坐标在(0,1)范围外的点将被过滤。

在此,本文将修改编译源代码,添加table_scene文件,进行直通滤波器对象滤波并可视化。

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>
int
main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
  // 填入点云数据
  pcl::PCDReader reader;
  // 把路径改为自己存放文件的路径
  reader.read<pcl::PointXYZ> ("E:/PCLcode/PCLtest/table_scene_lms400.pcd", *cloud);
  std::cerr << "Cloud before filtering: " << std::endl;
  std::cerr << *cloud << std::endl;
  // 创建直通滤波器对象
  pcl::PassThrough<pcl::PointXYZ> pass;//设置滤波器对象
  pass.setInputCloud (cloud);//设置输入点云
  pass.setFilterFieldName ("z");//设置过滤时所需要点云类型的z字段
  pass.setFilterLimits (-1.6, 0.0);//设置在过滤字段上的范围
  //pass.setFilterLimitsNegative (true);//设置保留范围内的or过滤掉范围内的
  pass.filter (*cloud_filtered);//执行滤波,保存过滤结果在cloud_filtered
  std::cout<< "Cloud after filtering: " << std::endl;
  std::cerr << *cloud_filtered << std::endl;
  //剩下的数据(内部点)将被存入磁盘
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("table_scene_lms400(滤波).pcd", *cloud_filtered, false);
  pass.setNegative (true);
  pass.filter (*cloud_filtered);
  writer.write<pcl::PointXYZ> ("table_scene_lms400(滤除点).pcd", *cloud_filtered, false);//将数据写回到磁盘
  system("pause");
  return (0);

}

执行上述代码:

在PCL中使用直通滤波器对点云进行滤波处理

滤波前点云有450400,直通滤波后,点云在(-1.6,0.0)以外的点被过滤(范围的选择与采集设备的位置紧密相关,应该弄清楚场景与采集设备之间的几何关系),剩余点云数量389481个。

接下来,利用cloud_viewer类对table_scene_lms400(滤波).pcd,table_scene_lms400(滤除点).pcd进行可视化。

在PCL中使用直通滤波器对点云进行滤波处理

在PCL中使用直通滤波器对点云进行滤波处理