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 = 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);																				//设置输入点云
		outrem.setRadiusSearch(0.8);																				//搜索半径设置为0.8,在该范围内搜索邻近点
		outrem.setMinNeighborsInRadius(1);																			//设置查询点的邻近点点数小于1的就删除
		outrem.filter(*cloud_filtered);																				//执行条件滤波
	}
	else if (strcmp(argv[1], "-c") == 0)
	{
		pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());					//创建条件限定下的滤波器
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
		//添加z字段上大于0的比较算子GT
		range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
		//添加z字段上小于0.8的比较算子LT
		pcl::ConditionalRemoval<pcl::PointXYZ>condrem;
		condrem.setCondition(range_cond);
		condrem.setInputCloud(cloud);																				//设置输入点云
		condrem.setKeepOrganized(true);																				//设置保持点云的结构,为true时被提出的点为NAN
		condrem.filter(*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);

三、编译结果

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值