PCL点云滤波代码

发布时间 2023-11-16 15:59:32作者: 量子与太极

PCL点云滤波代码实例

1.直通滤波:

PassThrough           
直接指定保留哪个轴上的范围内的点
#include <pcl/filters/passthrough.h>
如果使用线结构光扫描的方式采集点云,必然物体沿z向分布较广,但x,y向的分布处于有限范围内。
此时可使用直通滤波器,确定点云在x或y方向上的范围,可较快剪除离群点,达到第一步粗处理的目的。

 

 1 /* 创建点云对象 指针
 2 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
 3 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
 4 // 原点云获取后进行滤波
 5 pcl::PassThrough<pcl::PointXYZ> pass;// 创建滤波器对象
 6 pass.setInputCloud (cloud);//设置输入点云
 7 pass.setFilterFieldName ("z");//滤波字段名被设置为Z轴方向
 8 pass.setFilterLimits (0.0, 1.0);//可接受的范围为(0.0,1.0) 
 9 //pass.setFilterLimitsNegative (true);//设置保留范围内 还是 过滤掉范围内
10 pass.filter (*cloud_filtered); //执行滤波,保存过滤结果在cloud_filtered
11 */
12 #include <iostream>
13 #include <pcl/point_types.h>
14 #include <pcl/filters/passthrough.h>//直通滤波器 PassThrough 
15 #include <pcl/visualization/cloud_viewer.h>//点云可视化
16 // 别名
17 typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;
18 
19 int  main (int argc, char** argv)
20 {
21   // 定义 点云对象 指针
22    Cloud::Ptr cloud_ptr(new Cloud());
23    Cloud::Ptr cloud_filtered_ptr(new Cloud());
24   //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
25   //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_ptr (new pcl::PointCloud<pcl::PointXYZ>);
26 
27   // 产生点云数据 
28   cloud_ptr->width  = 10;
29   cloud_ptr->height = 1;
30   cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);
31   for (size_t i = 0; i < cloud_ptr->points.size (); ++i)
32   {
33     cloud_ptr->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
34     cloud_ptr->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
35     cloud_ptr->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
36   }
37 
38   std::cerr << "Cloud before filtering滤波前: " << std::endl;
39   for (size_t i = 0; i < cloud_ptr->points.size (); ++i)
40     std::cerr << "    " << cloud_ptr->points[i].x << " " 
41                         << cloud_ptr->points[i].y << " " 
42                         << cloud_ptr->points[i].z << std::endl;
43 
44   // 创建滤波器对象 Create the filtering object
45   pcl::PassThrough<pcl::PointXYZ> pass;
46   pass.setInputCloud (cloud_ptr);//设置输入点云
47   pass.setFilterFieldName ("z");// 定义轴
48   pass.setFilterLimits (0.0, 1.0);// 范围
49  // pass.setKeepOrganized(true); // 保持 有序点云结构===============
50   pass.setFilterLimitsNegative (false);//标志为false时保留范围内的点
51   pass.filter (*cloud_filtered_ptr);
52 
53   // 输出滤波后的点云
54   std::cerr << "Cloud after filtering滤波后: " << std::endl;
55   for (size_t i = 0; i < cloud_filtered_ptr->points.size (); ++i)
56     std::cerr << "    " << cloud_filtered_ptr->points[i].x << " " 
57                         << cloud_filtered_ptr->points[i].y << " " 
58                         << cloud_filtered_ptr->points[i].z << std::endl;
59   // 程序可视化
60  
61   pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
62   viewer.showCloud(cloud_filtered_ptr);
63   while (!viewer.wasStopped())
64     {
65         // Do nothing but wait.
66     }
67 
68   return (0);
69 }

 

2.体素滤波器:

VoxelGrid

体素格 (正方体立体空间内 保留一个点(重心点))在网格内减少点数量保证重心位置不变 PCLPointCloud2() 下采样

#include <pcl/filters/voxel_grid.h>

 

注意此点云类型为 pcl::PCLPointCloud2 类型 blob 格子类型
#include <pcl/filters/voxel_grid.h>

 

// 转换为模板点云 pcl::PointCloud<pcl::PointXYZ>
pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);

 

如果使用高分辨率相机等设备对点云进行采集,往往点云会较为密集。
过多的点云数量会对后续分割工作带来困难。
体素格滤波器可以达到向下采样同时不破坏点云本身几何结构的功能。
点云几何结构 不仅是宏观的几何外形,也包括其微观的排列方式,
比如横向相似的尺寸,纵向相同的距离。
随机下采样虽然效率比体素滤波器高,但会破坏点云微观结构.

 

使用体素化网格方法实现下采样,即减少点的数量 减少点云数据,
并同时保存点云的形状特征,在提高配准,曲面重建,形状识别等算法速度中非常实用,
PCL是实现的VoxelGrid类通过输入的点云数据创建一个三维体素栅格,
容纳后每个体素内用体素中所有点的重心来*似显示体素中其他点,
这样该体素内所有点都用一个重心点最终表示,对于所有体素处理后得到的过滤后的点云,
这种方法比用体素中心(注意中心和重心)逼*的方法更慢,但是对于采样点对应曲面的表示更为准确。

 

#include <iostream>
#include <pcl/point_types.h>
//#include <pcl/filters/passthrough.h>
#include <pcl/filters/voxel_grid.h>//体素格滤波器VoxelGrid
#include <pcl/io/pcd_io.h>//点云文件pcd 读写
#include <pcl/visualization/cloud_viewer.h>//点云可视化

using namespace std;
// 别名
typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;

int
main(int argc, char** argv)
{
    // 定义 点云对象 指针
    pcl::PCLPointCloud2::Ptr cloud2_ptr(new pcl::PCLPointCloud2());
    pcl::PCLPointCloud2::Ptr cloud2_filtered_ptr(new pcl::PCLPointCloud2());
    Cloud::Ptr cloud_filtered_ptr(new Cloud);
    // 读取点云文件 填充点云对象
    pcl::PCDReader reader;
    reader.read("../table_scene_lms400.pcd", *cloud2_ptr);
    if (cloud2_ptr == NULL) { cout << "pcd file read err" << endl; return -1; }
    cout << "PointCLoud before filtering 滤波前数量: " << cloud2_ptr->width * cloud2_ptr->height
        << " data points ( " << pcl::getFieldsList(*cloud2_ptr) << "." << endl;

    // 创建滤波器对象 Create the filtering object
    pcl::VoxelGrid<pcl::PCLPointCloud2> vg;
    // pcl::ApproximateVoxelGrid<pcl::PointXYZ> avg;
    vg.setInputCloud(cloud2_ptr);//设置输入点云
    vg.setLeafSize(0.01f, 0.01f, 0.01f);// 体素块大小 1cm
    vg.filter(*cloud2_filtered_ptr);

    // 输出滤波后的点云信息
    cout << "PointCLoud before filtering 滤波后数量: " << cloud2_filtered_ptr->width * cloud2_filtered_ptr->height
        << " data points ( " << pcl::getFieldsList(*cloud2_filtered_ptr) << "." << endl;
    // 写入内存
    pcl::PCDWriter writer;
    writer.write("table_scene_lms400_downsampled.pcd", *cloud2_filtered_ptr,
        Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);

    // 调用系统可视化命令行显示
    //system("pcl_viewer table_scene_lms400_inliers.pcd");

    // 转换为模板点云 pcl::PointCloud<pcl::PointXYZ>
    pcl::fromPCLPointCloud2(*cloud2_filtered_ptr, *cloud_filtered_ptr);

    // 程序可视化
    pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
    viewer.showCloud(cloud_filtered_ptr);
    while (!viewer.wasStopped())
    {
        // Do nothing but wait.
    }

    return (0);
}

3.均匀采样:

UnifromSapling

均匀采样:半径求体内 保留一个点(重心点)

均匀采样:这个类基本上是相同的,但它输出的点云索引是选择的关键点,是在计算描述子的常见方式。

原理同体素格 (正方体立体空间内 保留一个点(重心点))
而 均匀采样:半径求体内 保留一个点(重心点)

 

 1 #include <iostream>
 2 #include <pcl/point_types.h>
 3 //#include <pcl/filters/passthrough.h>
 4 //#include <pcl/filters/voxel_grid.h>//体素格滤波器VoxelGrid
 5 #include <pcl/filters/uniform_sampling.h>//均匀采样
 6 #include <pcl/io/pcd_io.h>//点云文件pcd 读写
 7 #include <pcl/visualization/cloud_viewer.h>//点云可视化
 8 //#include <pcl_conversions/pcl_conversions.h>//点云类型转换
 9 
10 using namespace std;
11 // 别名
12 typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;
13 
14 int
15  main (int argc, char** argv)
16 {
17   // 定义 点云对象 指针
18   //pcl::PCLPointCloud2::Ptr cloud2_ptr(new pcl::PCLPointCloud2());
19   //pcl::PCLPointCloud2::Ptr cloud2_filtered_ptr(new pcl::PCLPointCloud2());
20   Cloud::Ptr cloud_ptr(new Cloud);
21   Cloud::Ptr cloud_filtered_ptr(new Cloud);
22   // 读取点云文件 填充点云对象
23   pcl::PCDReader reader;
24   reader.read( "../table_scene_lms400.pcd", *cloud_ptr);
25   if(cloud_ptr==NULL) { cout << "pcd file read err" << endl; return -1;}
26   cout << "PointCLoud before filtering 滤波前数量: " << cloud_ptr->width * cloud_ptr->height
27        << " data points ( " << pcl::getFieldsList (*cloud_ptr) << "." << endl;
28 
29   // 创建滤波器对象 Create the filtering object
30     pcl::UniformSampling<pcl::PointXYZ> filter;// 均匀采样
31     filter.setInputCloud(cloud_ptr);//输入点云
32     filter.setRadiusSearch(0.01f);//设置半径
33     //pcl::PointCloud<int> keypointIndices;// 索引
34     filter.filter(*cloud_filtered_ptr);
35     //pcl::copyPointCloud(*cloud_ptr, keypointIndices.points, *cloud_filtered_ptr);
36   // 输出滤波后的点云信息
37   cout << "PointCLoud before filtering 滤波后数量: " << cloud_filtered_ptr->width * cloud_filtered_ptr->height
38        << " data points ( " << pcl::getFieldsList (*cloud_filtered_ptr) << "." << endl;
39   // 写入内存
40   //pcl::PCDWriter writer;
41   //writer.write("table_scene_lms400_UniformSampled.pcd",*cloud_filtered_ptr,
42   //             Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);
43 
44   // 调用系统可视化命令行显示
45   //system("pcl_viewer table_scene_lms400_inliers.pcd");
46 
47   // 转换为模板点云 pcl::PointCloud<pcl::PointXYZ>
48  // pcl::fromPCLPointCloud2 (*cloud2_filtered_ptr, *cloud_filtered_ptr);
49 
50   // 程序可视化
51   pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
52   viewer.showCloud(cloud_filtered_ptr);
53   while (!viewer.wasStopped())
54     {
55         // Do nothing but wait.
56     }
57 
58   return (0);
59 }

4.统计滤波器:

StatisticalOutlierRemoval  统计滤波器用于去除明显离群点

#include <pcl/filters/statistical_outlier_removal.h>

统计滤波器用于去除明显离群点(离群点往往由测量噪声引入)。其特征是在空间中分布稀疏,可以理解为:每个点都表达一定信息量,某个区域点越密集则可能信息量越大。噪声信息属于无用信息,信息量较小。所以离群点表达的信息可以忽略不计。考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。计算每个点到其最*的k(设定)个点*均距离。则点云中所有点的距离应构成高斯分布。给定均值与方差,可剔除n个西格玛之外的点激光扫描通常会产生密度不均匀的点云数据集,另外测量中的误差也会产生稀疏的离群点,此时,估计局部点云特征(例如采样点处法向量或曲率变化率)时运算复杂,这会导致错误的数值,反过来就会导致点云配准等后期的处理失败。

解决办法:对每个点的邻域进行一个统计分析,并修剪掉一些不符合标准的点。具体方法为在输入数据中对点到临*点的距离分布的计算,对每一个点,计算它到所有临*点的*均距离(假设得到的结果是一个高斯分布,其形状是由均值和标准差决定),那么*均距离在标准范围之外的点,可以被定义为离群点并从数据中去除。

 

#include <iostream>
#include <pcl/point_types.h>
//#include <pcl/filters/passthrough.h>
//#include <pcl/filters/voxel_grid.h>//体素格滤波器VoxelGrid
#include <pcl/filters/statistical_outlier_removal.h>//统计滤波器 
#include <pcl/io/pcd_io.h>//点云文件pcd 读写
#include <pcl/visualization/cloud_viewer.h>//点云可视化

using namespace std;
// 别名
typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;

int
main(int argc, char** argv)
{
    // 定义 点云对象 指针
    Cloud::Ptr cloud_ptr(new Cloud);
    Cloud::Ptr cloud_filtered_ptr(new Cloud);
    //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
    //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_ptr (new pcl::PointCloud<pcl::PointXYZ>);

    // 读取点云文件 填充点云对象
    pcl::PCDReader reader;
    reader.read("../table_scene_lms400.pcd", *cloud_ptr);
    if (cloud_ptr == NULL) { cout << "pcd file read err" << endl; return -1; }
    cout << "PointCLoud before filtering 滤波前数量: " << cloud_ptr->width * cloud_ptr->height
        << " data points ( " << pcl::getFieldsList(*cloud_ptr) << "." << endl;

    // 创建滤波器,对每个点分析的临*点的个数设置为50 ,并将标准差的倍数设置为1  这意味着如果一
    // 个点的距离超出了*均距离一个标准差以上,则该点被标记为离群点,并将它移除,存储起来
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sta;//创建滤波器对象
    sta.setInputCloud(cloud_ptr);            //设置待滤波的点云
    sta.setMeanK(50);                         //设置在进行统计时考虑查询点临*点数
    sta.setStddevMulThresh(1.0);                   //设置判断是否为离群点的阀值
    sta.filter(*cloud_filtered_ptr);             //存储内点

    // 输出滤波后的点云信息
    std::cerr << "Cloud after filtering: " << std::endl;
    std::cerr << *cloud_filtered_ptr << std::endl;

    // 写入内存  保存内点
    pcl::PCDWriter writer;
    writer.write("table_scene_lms400_inliers.pcd", *cloud_filtered_ptr, false);
    // 保存外点 被滤出的点
    sta.setNegative(true);
    sta.filter(*cloud_filtered_ptr);
    writer.write<pcl::PointXYZ>("table_scene_lms400_outliers.pcd", *cloud_filtered_ptr, false);

    // 调用系统可视化命令行显示
    //system("pcl_viewer table_scene_lms400_inliers.pcd");

    // 程序可视化
    pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
    viewer.showCloud(cloud_filtered_ptr);
    while (!viewer.wasStopped())
    {
        // Do nothing but wait.
    }

    return (0);
}

 

5.半径滤波器:

RadiusOutlinerRemoval   球半径滤波器

#include <pcl/filters/radius_outlier_removal.h>

球半径滤波器与统计滤波器相比更加简单粗暴。以某点为中心 画一个球计算落在该球内的点的数量,当数量大于给定值时,

则保留该点,数量小于给定值则剔除该点。此算法运行速度快,依序迭代留下的点一定是最密集的,但是球的半径和球内点的数目都需要人工指定。RadiusOutlinerRemoval比较适合去除单个的离群点 ConditionalRemoval 比较灵活,可以根据用户设置的条件灵活过滤。 

 

#include <iostream>
#include <pcl/point_types.h>
//#include <pcl/filters/passthrough.h>
//#include <pcl/ModelCoefficients.h>     //模型系数头文件
//#include <pcl/filters/project_inliers.h> //投影滤波类头文件
#include <pcl/io/pcd_io.h>               //点云文件pcd 读写
#include <pcl/filters/radius_outlier_removal.h>// 球半径滤波器
#include <pcl/visualization/cloud_viewer.h>//点云可视化

// 别名
typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;
using namespace std;
int main (int argc, char** argv)
{
  // 定义 点云对象 指针
   Cloud::Ptr cloud_ptr(new Cloud());
   Cloud::Ptr cloud_filtered_ptr(new Cloud());

  // 产生点云数据 
  cloud_ptr->width  = 5;
  cloud_ptr->height = 1;
  cloud_ptr->points.resize (cloud_ptr->width * cloud_ptr->height);
  for (size_t i = 0; i < cloud_ptr->points.size (); ++i)
  {
    cloud_ptr->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud_ptr->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud_ptr->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
  }

  std::cerr << "Cloud before filtering半径滤波前: " << std::endl;
  for (size_t i = 0; i < cloud_ptr->points.size (); ++i)
    std::cerr << "    " << cloud_ptr->points[i].x << " " 
                        << cloud_ptr->points[i].y << " " 
                        << cloud_ptr->points[i].z << std::endl;

  // 可使用 strcmp获取指定命令行参数 if (strcmp(argv[1], "-r") == 0)
  // 创建滤波器 
  pcl::RadiusOutlierRemoval<pcl::PointXYZ> Radius;
  // 建立滤波器
  Radius.setInputCloud(cloud_ptr);
  Radius.setRadiusSearch(1.2);//半径为 0.8m
  Radius.setMinNeighborsInRadius (2);//半径内最少需要 2个点
  // 执行滤波
  Radius.filter (*cloud_filtered_ptr);

  // 输出滤波后的点云
  std::cerr << "Cloud after filtering半径滤波后: " << std::endl;
  for (size_t i = 0; i < cloud_filtered_ptr->points.size (); ++i)
    std::cerr << "    " << cloud_filtered_ptr->points[i].x << " " 
                        << cloud_filtered_ptr->points[i].y << " " 
                        << cloud_filtered_ptr->points[i].z << std::endl;
  // 程序可视化
  pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
  viewer.showCloud(cloud_filtered_ptr);
  while (!viewer.wasStopped())
    {
        // Do nothing but wait.
    }

  return (0);
}

 

6.条件滤波器:ConditionalRemoval

可以一次删除满足对输入的点云设定的一个或多个条件指标的所有的数据点

删除点云中不符合用户指定的一个或者多个条件的数据点不在条件范围内的点 被替换为 nan

pcl::removeNaNFromPointCloud()去除Nan点
#include <pcl/filters/conditional_removal.h>

 

 1 #include <iostream>
 2 #include <pcl/point_types.h>
 3 //#include <pcl/filters/passthrough.h>
 4 //#include <pcl/ModelCoefficients.h>       //模型系数头文件
 5 //#include <pcl/filters/project_inliers.h> //投影滤波类头文件
 6 #include <pcl/io/pcd_io.h>                 //点云文件pcd 读写
 7 //#include <pcl/filters/radius_outlier_removal.h>// 球半径滤波器
 8 #include <pcl/filters/conditional_removal.h>     //条件滤波器
 9 
10 //#include <pcl/filters/filter.h>
11 
12 #include <pcl/visualization/cloud_viewer.h>//点云可视化
13 
14 // 别名
15 typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;
16 using namespace std;
17 int main(int argc, char** argv)
18 {
19     // 定义 点云对象 指针
20     Cloud::Ptr cloud_ptr(new Cloud());
21     Cloud::Ptr cloud_filtered_ptr(new Cloud());
22 
23     // 产生点云数据 
24     cloud_ptr->width = 5;
25     cloud_ptr->height = 1;
26     cloud_ptr->points.resize(cloud_ptr->width * cloud_ptr->height);
27     for (size_t i = 0; i < cloud_ptr->points.size(); ++i)
28     {
29         cloud_ptr->points[i].x = 1 * rand() / (RAND_MAX + 1.0f);
30         cloud_ptr->points[i].y = 1 * rand() / (RAND_MAX + 1.0f);
31         cloud_ptr->points[i].z = 1 * rand() / (RAND_MAX + 1.0f);
32     }
33 
34     cout << "Cloud before filtering半径滤波前: " << endl;
35     for (size_t i = 0; i < cloud_ptr->points.size(); ++i)
36         cout << cloud_ptr->points[i].x << "," << cloud_ptr->points[i].y << "," << cloud_ptr->points[i].z << endl;
37 
38 
39     // 可使用 strcmp获取指定命令行参数 if (strcmp(argv[1], "-r") == 0)
40     //创建条件定义对象
41     pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond_cptr(new pcl::ConditionAnd<pcl::PointXYZ>());
42     //为条件定义对象添加比较算子
43     range_cond_cptr->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
44         pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
45     //添加在Z字段上大于(pcl::ComparisonOps::GT great Then)0的比较算子
46 
47     range_cond_cptr->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new
48         pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
49     //添加在Z字段上小于(pcl::ComparisonOps::LT Lower Then)0.8的比较算子
50 
51     // 创建滤波器并用条件定义对象初始化
52     pcl::ConditionalRemoval<pcl::PointXYZ> conditrem;//创建条件滤波器
53     conditrem.setCondition(range_cond_cptr);        //并用条件定义对象初始化            
54     conditrem.setInputCloud(cloud_ptr);             //输入点云
55     conditrem.setKeepOrganized(true);                //设置保持点云的结构
56     // 执行滤波
57     conditrem.filter(*cloud_filtered_ptr);           //大于0.0小于0.8这两个条件用于建立滤波器
58     // 不在条件范围内的点 被替换为 nan
59 
60     // 输出滤波后的点云
61     std::cout << "Cloud after filtering半径滤波后: " << std::endl;
62     for (size_t i = 0; i < cloud_filtered_ptr->points.size(); ++i)
63     {
64         std::cout << "    " << cloud_filtered_ptr->points[i].x << " "
65             << cloud_filtered_ptr->points[i].y << " "
66             << cloud_filtered_ptr->points[i].z << std::endl;
67     }
68 
69     // 去除 nan点
70     vector<int> mapping;
71     pcl::removeNaNFromPointCloud(*cloud_filtered_ptr, *cloud_filtered_ptr, mapping);
72     // 输出去除nan后的点云
73     std::cout << "Cloud after delet nan point去除nan点 : " << std::endl;
74     for (size_t i = 0; i < cloud_filtered_ptr->points.size(); ++i)
75     {
76         std::cout << "    " << cloud_filtered_ptr->points[i].x << " "
77             << cloud_filtered_ptr->points[i].y << " "
78             << cloud_filtered_ptr->points[i].z << std::endl;
79 
80     }
81     // 程序可视化
82     pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
83     viewer.showCloud(cloud_filtered_ptr);
84     while (!viewer.wasStopped())
85     {
86         // Do nothing but wait.
87     }
88 
89     return (0);
90 }

 

7.索引滤波器:

extractIndices 根据点云索引提取对应的点云

 

 1 #include <iostream>
 2 
 3 // PCL
 4 #include <pcl/point_types.h>
 5 #include <pcl/filters/extract_indices.h>
 6 
 7 int main(int, char**)
 8 {
 9     typedef pcl::PointXYZ PointType;
10     typedef pcl::PointCloud<PointType> CloudType;
11     CloudType::Ptr cloud(new CloudType);
12     cloud->is_dense = false;
13     // 生成点云 
14     PointType p;
15     for (unsigned int i = 0; i < 5; ++i)
16     {
17         p.x = p.y = p.z = static_cast<float> (i);
18         cloud->push_back(p);
19     }
20 
21     std::cout << "Cloud has " << cloud->points.size() << " points." << std::endl;
22 
23     pcl::PointIndices indices;// 取得需要的索引
24     indices.indices.push_back(0);
25     indices.indices.push_back(2);
26 
27     pcl::ExtractIndices<PointType> extract_indices;//索引提取器
28     extract_indices.setIndices(boost::make_shared<const pcl::PointIndices>(indices));//设置索引
29     extract_indices.setInputCloud(cloud);//设置输入点云
30     pcl::PointCloud<pcl::PointXYZ>::Ptr output(new pcl::PointCloud<pcl::PointXYZ>);
31     extract_indices.filter(*output);//提取对于索引的点云
32 
33   // 外点 绿色
34     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_other(new pcl::PointCloud<pcl::PointXYZ>);
35     // *cloud_other = *cloud - *output;
36       // 移去*面局内点,提取剩余点云
37     extract_indices.setNegative(true);
38     extract_indices.filter(*cloud_other);
39     std::cout << "Output has " << output->points.size() << " points." << std::endl;
40     std::cout << output->points[0].x << "," << output->points[0].y << "," << output->points[0].z << std::endl;
41     std::cout << output->points[1].x << "," << output->points[1].y << "," << output->points[1].z << std::endl;
42     return (0);
43 }

 

#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>//提取索引

#include <pcl/visualization/cloud_viewer.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>);

    // 读取PCD文件
    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);    // 设置采样体素大小 1cm*1cm*1cm
    sor.filter(*cloud_filtered_blob);        // 保存

    // 转换为模板点云 PCLPointCloud2 ---> pcl::PointXYZ
    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;               //创建分割对象  PCL采样一致性算法分割
    seg.setOptimizeCoefficients(true);                    //设置对估计模型参数进行优化处理

    seg.setModelType(pcl::SACMODEL_PLANE);                //设置分割模型类别  *面
    seg.setMethodType(pcl::SAC_RANSAC);                   //设置用哪个随机参数估计方法
    seg.setMaxIterations(1000);                           //设置最大迭代次数
    seg.setDistanceThreshold(0.01);                       //判断是否为模型内点的距离阀值

    // 设置ExtractIndices的实际参数
    pcl::ExtractIndices<pcl::PointXYZ> extract;            //创建点云提取对象

    int i = 0, nr_points = (int)cloud_filtered->points.size();
    // While 30% of the original cloud is still there
    while (cloud_filtered->points.size() > 0.3 * nr_points)
    {
        // 为了处理点云包含的多个模型,在一个循环中执行该过程并在每次模型被提取后,保存剩余的点进行迭代
        seg.setInputCloud(cloud_filtered);
        seg.segment(*inliers, *coefficients);
        if (inliers->indices.size() == 0)
        {
            std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;
            break;
        }

        // 有索引提取相应的点  Extract the inliers
        extract.setInputCloud(cloud_filtered);
        extract.setIndices(inliers);
        extract.setNegative(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);

        // Create the filtering object
        extract.setNegative(true);
        extract.filter(*cloud_f);
        cloud_filtered.swap(cloud_f);
        i++;
    }

    //pcl:: PointCloud < pcl:: PointXYZ > ::Ptr cloud_load(new pcl:: PointCloud<pcl::PointXYZ>);
    //pcl::io::loadPCDFile("./table_scene_lms400_plane_1.pcd", *cloud_load);
    //pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
    //viewer.showCloud(cloud_load);

    //pcl::PointCloud < pcl::PointXYZ > ::Ptr cloud_load1(new pcl::PointCloud<pcl::PointXYZ>);
    //pcl::io::loadPCDFile("../table_scene_lms400.pcd", *cloud_load1);
    //pcl::visualization::CloudViewer viewer1("pcd viewer1");// 显示窗口的名字
    //viewer1.showCloud(cloud_load1);


    //while (!viewer1.wasStopped())
    //{
    //    // Do nothing but wait.
    //}

    return (0);
}

   

 

 

8.投影滤波器:

 

ProjectInliers

输出投影后的点的坐标,使用参数化模型投影点云如何将点投影到一个参数化模型上(*面或者球体等),

参数化模型通过一组参数来设定,对于*面来说使用其等式形式。在PCL中有特定存储常见模型系数的数据结构。

投影滤波类就是输入点云和投影模型,输出为投影到模型上之后的点云。

 

 1 #include <iostream>
 2 #include <pcl/point_types.h>
 3 //#include <pcl/filters/passthrough.h>
 4 #include <pcl/ModelCoefficients.h>     //模型系数头文件
 5 #include <pcl/filters/project_inliers.h> //投影滤波类头文件
 6 #include <pcl/io/pcd_io.h>               //点云文件pcd 读写
 7 #include <pcl/visualization/cloud_viewer.h>//点云可视化
 8 
 9 // 别名
10 typedef pcl::PointCloud<pcl::PointXYZ>  Cloud;
11 using namespace std;
12 int main(int argc, char** argv)
13 {
14     // 定义 点云对象 指针
15     Cloud::Ptr cloud_ptr(new Cloud());
16     Cloud::Ptr cloud_filtered_ptr(new Cloud());
17     //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
18     //pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_ptr (new pcl::PointCloud<pcl::PointXYZ>);
19 
20     // 产生点云数据 
21     cloud_ptr->width = 5;
22     cloud_ptr->height = 1;
23     cloud_ptr->points.resize(cloud_ptr->width * cloud_ptr->height);
24     for (size_t i = 0; i < cloud_ptr->points.size(); ++i)
25     {
26         cloud_ptr->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
27         cloud_ptr->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
28         cloud_ptr->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
29     }
30 
31     std::cerr << "Cloud before filtering投影滤波前: " << std::endl;
32     for (size_t i = 0; i < cloud_ptr->points.size(); ++i)
33         std::cerr << "    " << cloud_ptr->points[i].x << " "
34         << cloud_ptr->points[i].y << " "
35         << cloud_ptr->points[i].z << std::endl;
36 
37     // 填充ModelCoefficients的值,使用ax+by+cz+d=0*面模型,其中 a=b=d=0,c=1 也就是X——Y*面
38     //定义模型系数对象,并填充对应的数据 创建投影滤波模型重会设置模型类型 pcl::SACMODEL_PLANE
39     pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
40     coefficients->values.resize(4);
41     coefficients->values[0] = coefficients->values[1] = 0;
42     coefficients->values[2] = 1.0;
43     coefficients->values[3] = 0;
44 
45     // 创建投影滤波模型ProjectInliers对象,使用ModelCoefficients作为投影对象的模型参数
46     pcl::ProjectInliers<pcl::PointXYZ> proj;    //创建投影滤波对象
47     proj.setModelType(pcl::SACMODEL_PLANE);    //设置对象对应的投影模型  *面模型
48     proj.setInputCloud(cloud_ptr);        //设置输入点云
49     proj.setModelCoefficients(coefficients);    //设置模型对应的系数
50     proj.filter(*cloud_filtered_ptr);        //投影结果存储
51 
52     // 输出滤波后的点云
53     std::cerr << "Cloud after filtering投影滤波后: " << std::endl;
54     for (size_t i = 0; i < cloud_filtered_ptr->points.size(); ++i)
55         std::cerr << "    " << cloud_filtered_ptr->points[i].x << " "
56         << cloud_filtered_ptr->points[i].y << " "
57         << cloud_filtered_ptr->points[i].z << std::endl;
58     // 程序可视化
59     pcl::visualization::CloudViewer viewer("pcd viewer");// 显示窗口的名字
60     viewer.showCloud(cloud_filtered_ptr);
61     while (!viewer.wasStopped())
62     {
63         // Do nothing but wait.
64     }
65 
66     return (0);
67 }

 

 

 

9.模型滤波器:

ModelOutlierRemoval   根据模型设置条件进行滤波

 1 #include <iostream>
 2 #include <pcl/point_types.h>
 3 #include <pcl/filters/model_outlier_removal.h>
 4 #include <pcl/visualization/cloud_viewer.h>//点云可视化
 5 
 6 int main()
 7 {
 8     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
 9     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_sphere_filtered(new pcl::PointCloud<pcl::PointXYZ>);
10 
11     // 1. Generate cloud data
12     int noise_size = 5;
13     int sphere_data_size = 10;
14     cloud->width = noise_size + sphere_data_size;
15     cloud->height = 1;
16     cloud->points.resize(cloud->width * cloud->height);
17     // 1.1 Add noise
18     for (size_t i = 0; i < noise_size; ++i)
19     {
20         cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
21         cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
22         cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
23     }
24     // 1.2 Add sphere:
25     double rand_x1 = 1;
26     double rand_x2 = 1;
27     for (size_t i = noise_size; i < noise_size + sphere_data_size; ++i)
28     {
29         // See: http://mathworld.wolfram.com/SpherePointPicking.html
30         while (pow(rand_x1, 2) + pow(rand_x2, 2) >= 1)
31         {
32             rand_x1 = (rand() % 100) / (50.0f) - 1;
33             rand_x2 = (rand() % 100) / (50.0f) - 1;
34         }
35         double pre_calc = sqrt(1 - pow(rand_x1, 2) - pow(rand_x2, 2));
36         cloud->points[i].x = 2 * rand_x1 * pre_calc;
37         cloud->points[i].y = 2 * rand_x2 * pre_calc;
38         cloud->points[i].z = 1 - 2 * (pow(rand_x1, 2) + pow(rand_x2, 2));
39         rand_x1 = 1;
40         rand_x2 = 1;
41     }
42 
43     std::cerr << "Cloud before filtering: " << std::endl;
44     for (size_t i = 0; i < cloud->points.size(); ++i)
45         std::cout << "    " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;
46 
47     // 2. filter sphere:
48     // 2.1 generate model:
49     // modelparameter for this sphere:
50     // position.x: 0, position.y: 0, position.z:0, radius: 1
51     pcl::ModelCoefficients sphere_coeff;
52     sphere_coeff.values.resize(4);
53     sphere_coeff.values[0] = 0;
54     sphere_coeff.values[1] = 0;
55     sphere_coeff.values[2] = 0;
56     sphere_coeff.values[3] = 1;
57 
58     pcl::ModelOutlierRemoval<pcl::PointXYZ> sphere_filter;
59     sphere_filter.setModelCoefficients(sphere_coeff);
60     sphere_filter.setThreshold(0.05);
61     sphere_filter.setModelType(pcl::SACMODEL_SPHERE);
62     sphere_filter.setInputCloud(cloud);
63     sphere_filter.filter(*cloud_sphere_filtered);
64 
65     std::cerr << "Sphere after filtering: " << std::endl;
66     for (size_t i = 0; i < cloud_sphere_filtered->points.size(); ++i)
67         std::cout << "    " << cloud_sphere_filtered->points[i].x << " " << cloud_sphere_filtered->points[i].y << " " << cloud_sphere_filtered->points[i].z
68         << std::endl;
69 
70     //pcl::PointCloud < pcl::PointXYZ > ::Ptr cloud_load1(new pcl::PointCloud<pcl::PointXYZ>);
71     //pcl::io::loadPCDFile("../table_scene_lms400.pcd", *cloud_load1);
72     pcl::visualization::CloudViewer viewer1("pcd viewer1");// 显示窗口的名字
73     viewer1.showCloud(cloud);
74     
75     
76     while (!viewer1.wasStopped())
77     {
78         // Do nothing but wait.
79     }
80 
81     return (0);
82 }