PCL学习笔记(十八)-- ConditionalRemoval和RadiusOutliersRemoval滤波器移除离群点

一、简介

  RadiusOutlierRemoval滤波处理会滤除那些一定范围内没有足够多近邻的点;

  ConditionalRemoval滤波器用于删除不符合用户要求的一个或多个数据点。

二、代码分析

  1)首先,程序会确保用户输入正确的命令行参数,并随机生成一个点云数据:

  if (argc != 2)
  {
    std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
    exit(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;
  cloud->points.resize(cloud->width*cloud->height);
  //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)
  {
	  cloud->points[i].x = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
	  cloud->points[i].y = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
	  cloud->points[i].z = 1 * rand() / (RAND_MAX + 1.0f) - 0.5;
  }

  2)创建RadiusOutlierRemoval滤波器对象,设置其参数并将其应用到我们输入的点云数据,将搜索半径设为0.8,在此半径内的点必须要有一个近邻,才会保留这个点:

  if (strcmp(argv[1], "-r") == 0){
	  pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// 创建滤波器    
	  outrem.setInputCloud(cloud);              //设置输入点云
	  //搜索半径设为0.8,在此半径内点必须要有至少1个邻居时,此点才会被保留
	  outrem.setRadiusSearch(0.8);              //设置在0.8半径的范围内找邻近点
	  outrem.setMinNeighborsInRadius(1);        //设置查询点的邻近点集数小于1的删除
	  outrem.filter(*cloud_filtered);           //执行条件滤波,存储结果到cloud_filtered
  }

  3)创建 ConditionalRemoval滤波器,在z字段上大于0小于0.8的点云将被保留,其他点云数据将被删去:

  else if (strcmp(argv[1], "-c") == 0){
	  //创建条件限定下的滤波器
	  pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());            //创建条件定义对象
	  //为条件定义对象添加比较算子: 使用大于0.0和小于0.8这两个条件用于建立滤波器。
	  range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new 
		  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
	  //添加在z字段上大于0的比较算子  
	  range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new 
		  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
	  //添加在z字段上小于0.8的比较算子
	  //创建滤波器并用条件定义对象初始化
	  pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
	  condrem.setCondition(range_cond);
	  condrem.setInputCloud(cloud);           //设置输入点云
	  condrem.setKeepOrganized(true);         //设置保持点云的结构:为true时被剔除的点为NAN
	  condrem.filter(*cloud_filtered);        //执行条件滤波,存储结果到cloud_filtered
  }

  4)显示滤波后的点云:

  std::cerr << "Cloud before filtering: " << std::endl;
  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::cerr << "Cloud after filtering: " << std::endl;
  for (size_t i = 0; i < cloud_filtered->points.size (); ++i)
    std::cerr << "    " << cloud_filtered->points[i].x << " "
                        << cloud_filtered->points[i].y << " "
                        << cloud_filtered->points[i].z << std::endl;

  5)整体代码:

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>
int
 main (int argc, char** argv)
{
  if (argc != 2)
  {
    std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
    exit(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;
  cloud->points.resize(cloud->width*cloud->height);
  //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)
  {
	  cloud->points[i].x = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
	  cloud->points[i].y = 2 * rand() / (RAND_MAX + 1.0f) - 0.5;
	  cloud->points[i].z = 1 * rand() / (RAND_MAX + 1.0f) - 0.5;
  }
 
  if (strcmp(argv[1], "-r") == 0){
	  pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// 创建滤波器    
	  outrem.setInputCloud(cloud);              //设置输入点云
	  //搜索半径设为0.8,在此半径内点必须要有至少1个邻居时,此点才会被保留
	  outrem.setRadiusSearch(0.8);              //设置在0.8半径的范围内找邻近点
	  outrem.setMinNeighborsInRadius(1);        //设置查询点的邻近点集数小于1的删除
	  outrem.filter(*cloud_filtered);           //执行条件滤波,存储结果到cloud_filtered
  }
  else if (strcmp(argv[1], "-c") == 0){
	  //创建条件限定下的滤波器
	  pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());            //创建条件定义对象
	  //为条件定义对象添加比较算子: 使用大于0.0和小于0.8这两个条件用于建立滤波器。
	  range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new 
		  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
	  //添加在z字段上大于0的比较算子  
	  range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new 
		  pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
	  //添加在z字段上小于0.8的比较算子
	  //创建滤波器并用条件定义对象初始化
	  pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
	  condrem.setCondition(range_cond);
	  condrem.setInputCloud(cloud);           //设置输入点云
	  condrem.setKeepOrganized(true);         //设置保持点云的结构:为true时被剔除的点为NAN
	  condrem.filter(*cloud_filtered);        //执行条件滤波,存储结果到cloud_filtered
  }
  else{
    std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
    exit(0);
  }
  
  std::cerr << "Cloud before filtering: " << std::endl;
  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::cerr << "Cloud after filtering: " << std::endl;
  for (size_t i = 0; i < cloud_filtered->points.size (); ++i)
    std::cerr << "    " << cloud_filtered->points[i].x << " "
                        << cloud_filtered->points[i].y << " "
                        << cloud_filtered->points[i].z << std::endl;
  return (0);
}

  6)容易遇到的问题:

	  pcl::ConditionalRemoval<pcl::PointXYZ> condrem(range_cond);

  使用上述代码时容易报错:找不到匹配的构造函数!改成以下代码即可解决:

	  pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
	  condrem.setCondition(range_cond);

三、编译结果

PCL学习笔记(十八)-- ConditionalRemoval和RadiusOutliersRemoval滤波器移除离群点

上一篇:Matlab智能算法-基于非线性动态自适应惯性权重粒子群算法(IPSO)


下一篇:【优化求解】基于三重动态调整的花授粉算法matlab源码