PCL-- removal outliers(四种滤波方法)

本文档介绍了如何使用PCL库进行点云数据的预处理,包括统计外点移除、半径外点移除和条件移除。统计外点移除通过设定均值K和标准差阈值来去除异常点;半径外点移除根据邻域内点的数量来判断并移除外点;条件移除则依据特定条件(如点坐标范围)筛选点云。这些方法有助于提高点云数据的质量和后续处理的准确性。
摘要由CSDN通过智能技术生成

1. StatisticalOutlierRemoval Filter

对点云中的每个点进行统计分析

//微微修改一下官方文档的code,大体如下

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.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>);
//load pcd file from the path
//需要你在命令行输入文件所在路径,如 ../data/table.pcd
  pcl::PCDReader reader;
  reader.read<pcl::PointXYZ> (argv[1], *cloud);

  std::cout<<"original cloud data: "<<cloud->points.size()<<"points"<<std::endl;
  std::cerr << "Cloud before filtering: " << std::endl;
  //std::cerr << *cloud << std::endl;

  // Create the filtering object
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;

  // 设置输入
  sor.setInputCloud (cloud);
  // 设置用于平均距离估计的 KD-tree最近邻搜索点的个数.
  sor.setMeanK (50);
  // 高斯分布标准差的倍数, 也就是 u+1*sigma,u+2*sigma,u+3*sigma 中的 倍数1、2、3
  sor.setStddevMulThresh (1.0);
  // 滤波后输出
  sor.filter (*cloud_filtered);


  std::cerr << "Cloud after filtering: " << std::endl;
  std::cerr << *cloud_filtered << std::endl;
  //save the inliers into ASCII PCD file
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("lms400_inliers.pcd", *cloud_filtered, false);
  //save the filtered result into ASCII pcd file    保存过滤后的结果
  sor.setNegative (true);
  sor.filter (*cloud_filtered);
  writer.write<pcl::PointXYZ> ("lms400_outliers.pcd", *cloud_filtered, false);
  
  return (0);
}

2. RadiusOutlier removal / 3. Conditional removal

半径移除外点算法,就是设定一个搜索半径,判断目标点在设定半径范围内的相邻点数目,如下所示。

如果设定半径后,设定阀值范围为 1,那么只有黄色目标点被删除,如果设定阀值范围是 2,那么黄色和绿色范围点都会被删除

#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>);

  // Fill in the cloud data
  cloud->width  = 5;
  cloud->height = 1;
  cloud->resize (cloud->width * cloud->height);

  for (auto& point: *cloud)
  {
    point.x = 1024 * rand () / (RAND_MAX + 1.0f);
    point.y = 1024 * rand () / (RAND_MAX + 1.0f);
    point.z = 1024 * rand () / (RAND_MAX + 1.0f);
  }
  

  // RadiusOutlier-Removal
  if (strcmp(argv[1], "-r") == 0)
  {
    pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
    // build the filter
    outrem.setInputCloud(cloud);
    outrem.setRadiusSearch(0.8);
    outrem.setMinNeighborsInRadius (1);
    outrem.setKeepOrganized(true);
    // apply filter
    outrem.filter (*cloud_filtered);
  }

  // Conditional-Removal
  else if (strcmp(argv[1], "-c") == 0)
  {
    // build the condition
    // 构建一个 ‘与’ 操作的环境,只有当目标点满足所有条件才被认为是 inlier
    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.5)));
    range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new
      pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 1)));
    //上面这两个条件规定了 z 坐标的范围,0.5 < z < 1;


    // build the filter
    pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
    condrem.setCondition (range_cond);
    condrem.setInputCloud (cloud);
    condrem.setKeepOrganized(true);
    // apply filter
    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 (const auto& point: *cloud)
    std::cerr << "    " << point.x << " "
                        << point.y << " "
                        << point.z << std::endl;
  // display pointcloud after filtering
  std::cerr << "Cloud after filtering: " << std::endl;
  for (const auto& point: *cloud_filtered)
    std::cerr << "    " << point.x << " "
                        << point.y << " "
                        << point.z << std::endl;
  return (0);
}

 3. Conditional removal

涉及到的几个关键函数和类:

1. void pcl::ConditionBase< PointT >:: addComparison (ComparisonBaseConstPtr comparison)        增加一个新的比较对象

Parameters

comparisonthe comparison operator to add

References pcl::ComparisonBase< PointT >::capable_.

2. pcl::FieldComparison< PointT >::FieldComparison ( std::string field_name,ComparisonOps::CompareOp op,double compare_val )        规定具体条件

Parameters

field_name: the name of the field that contains the data we want to compare

op: the operator to use when making the comparison

compare_val: the constant value to compare the field value too

References pcl::ComparisonBase< PointT >::capable_, pcl::ComparisonBase< PointT >::field_name_, pcl::getFields(), pcl::ComparisonBase< PointT >::op_, and pcl::FieldComparison< PointT >::point_data_.

3. pcl::ComparisonOps::GT/LT {LT, GT, LE, GE, EQ}

Parameters

LT:less than 小于 

GT:greater than 大于

LE:less than or equal to 小于等于

GE:greater than or equal to 大于等于

EQ:equal to 等于

4. pcl::ConditionAnd

‘ 与 ’ 比较,必须满足所有条件才被认为是  inliers

   pcl::ConditionOr

‘ 或 ’ 比较, 满足所有条件中的一个就可以认为是 inliers

4. passthrough

直通滤波( passthrough filter)操作相对粗暴,针对你定义的点的类型,对 X、Y、Z、R、G、B…等等各纬度进行内外点的界定

#include <iostream>
#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>);

  // Fill in the cloud data
  cloud->width  = 5;
  cloud->height = 1;
  cloud->points.resize (cloud->width * cloud->height);

  for (auto& point: *cloud)
  {
    point.x = 1024 * rand () / (RAND_MAX + 1.0f);
    point.y = 1024 * rand () / (RAND_MAX + 1.0f);
    point.z = 1024 * rand () / (RAND_MAX + 1.0f);
  }

  std::cerr << "Cloud before filtering: " << std::endl;
  for (const auto& point: *cloud)
    std::cerr << "    " << point.x << " "
                        << point.y << " "
                        << point.z << std::endl;

  // Create the filtering object
  pcl::PassThrough<pcl::PointXYZ> pass;
  pass.setInputCloud (cloud);

  //规定了 x 的取值范围
  pass.setFilterFieldName ("x");
  pass.setFilterLimits (0.0, 1.0);

  //规定了 z 的取值范围
  pass.setFilterFieldName ("z");
  pass.setFilterLimits (0.0, 1.0);

  //这里也可以对颜色(RGB)进行滤波

  //pass.setFilterLimitsNegative (true);
  pass.filter (*cloud_filtered);

  std::cerr << "Cloud after filtering: " << std::endl;
  for (const auto& point: *cloud_filtered)
    std::cerr << "    " << point.x << " "
                        << point.y << " "
                        << point.z << std::endl;

  return (0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值