PCL学习记录——点云滤波

一、点云格式

问题出现于示例代码的voxel_grid和extract_indices中。
从GitHub下载的部分代码不能编译通过,对pcl点云格式pcl::PCLPointCloud2::Ptr进行学习和理解。源代码是sensor_msgs::PointCloud2,显然是运行于ROS里的。另外,涉及到点云数据格式的转换。

体素滤波可运行代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
int main (int argc, char** argv)
{
  //sensor_msgs::PointCloud2::Ptr cloud (new sensor_msgs::PointCloud2 ());
  //sensor_msgs::PointCloud2::Ptr cloud_filtered (new sensor_msgs::PointCloud2 ());
  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 ("../table_scene_lms400.pcd", *cloud); 
  std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height 
       << " data points (" << pcl::getFieldsList (*cloud) << ").";
  // 创建滤波器对象
  //pcl::VoxelGrid<sensor_msgs::PointCloud2> sor;
  pcl::VoxelGrid<pcl::PointXYZ> sor;
  sor.setInputCloud (cloud);
  sor.setLeafSize (0.01f, 0.01f, 0.01f);
  sor.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height 
       << " data points (" << pcl::getFieldsList (*cloud_filtered) << ").";
  pcl::PCDWriter writer;
  //writer.write ("2f.pcd", *cloud_filtered, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);
  writer.write ("2f.pcd", *cloud_filtered, false);
  return (0);
}

索引滤波可运行代码

#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/extract_indices.h>

int main (int argc, char** argv)
{
  pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);

  // 填入点云数据
  pcl::PCDReader reader;
  reader.read ("../table_scene_lms400.pcd", *cloud_blob);

  std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;

  //创建滤波器对象:使用叶大小为1cm的下采样
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
  sor.setInputCloud (cloud_blob);
  sor.setLeafSize (0.01f, 0.01f, 0.01f);
  sor.filter (*cloud_filtered_blob);

  // 转化为模板点云
  pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);

  std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;

  // 将下采样后的数据存入磁盘
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("../table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
  
  pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
  pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
  
  // 创建分割对象
  pcl::SACSegmentation<pcl::PointXYZ> seg;//创建分割对象
  // Optional
  seg.setOptimizeCoefficients (true);//设置对估计模型参数进行优化处理
  // Mandatory
  seg.setModelType (pcl::SACMODEL_PLANE);//设置分割模型类别
  seg.setMethodType (pcl::SAC_RANSAC);//设置用哪个随机参数估计方法
  seg.setMaxIterations (1000);//设置最大迭代次数
  seg.setDistanceThreshold (0.01);//判断是否为模型内点的距离阀值

  // 创建滤波器对象
  pcl::ExtractIndices<pcl::PointXYZ> extract;

  int i = 0, nr_points = (int) cloud_filtered->size ();
  //当还有30%原始点云数据时
  while (cloud_filtered->size () > 0.3 * nr_points)
  {
    // 从余下的点云中分割最大平面组成部分
    seg.setInputCloud (cloud_filtered);
    seg.segment (*inliers, *coefficients);	//inliers为分割后的索引
    std::cout<<"THIS SEG POINTS: "<<inliers->indices.size()<<std::endl;
    if (inliers->indices.size () == 0)
    {
      std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
      break;
    }

    // 分离内层
    extract.setInputCloud (cloud_filtered);
    extract.setIndices (inliers);	//提取的点云索引inliers中的点
    extract.setNegative (false);	//提取范围内的点,所以为false
    extract.filter (*cloud_p);
    std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;

    std::stringstream ss;
    ss << "../table_scene_lms400_plane_" << i << ".pcd";
    writer.write<pcl::PointXYZ> (ss.str (), *cloud_p, false);

    // 创建滤波器对象
    extract.setNegative (true);	//提取范围外的点
    extract.filter (*cloud_f);
    cloud_filtered.swap (cloud_f);	//交换,所以第二次的点云会与第一次不会有交集
    i++;
  }

  return (0);
}

参考链接

pcl::PCLPointCloud2::Ptr 和 pcl::PointCloud<pcl::PointXYZ>数据结构区别:
见参考链接: PCL中点云数据格式之间的转化

二、半径滤波

这个示例的运行方式不一样,如果只在终端输入./remove_outliers ,会提示:please specify command line arg ‘-r’ or ‘-c’
正确输入指令为:

./remove_outliers -r

可以调整代码outrem.setRadiusSearch(10)括号中的值,观察滤波差异。

#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);
  }
  
  if (strcmp(argv[1], "-r") == 0){
    pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
    // 创建滤波器
    outrem.setInputCloud(cloud);
    outrem.setRadiusSearch(10);
    outrem.setMinNeighborsInRadius (2);
    // 应用滤波器
    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)));
    range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (new
      pcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.01)));
    
    // 创建滤波器
    //pcl::ConditionalRemoval<pcl::PointXYZ> condrem (range_cond);
    pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
    condrem.setCondition(range_cond);
    condrem.setInputCloud (cloud);
    condrem.setKeepOrganized(true);
    // 应用滤波器
    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);
}

报错代码:

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

解决方法:
替换成以下两行,应该是函数定义更新了。

pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
condrem.setCondition(range_cond);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可见一班

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值