PCL入门之过滤器模块Filtering

0. 引言

本文主要记录PCL点云库的过滤器模块Filtering的几个例子。

├── data
│   └── table_scene_lms400.pcd
├── ExtractIndices
│   ├── CMakeLists.txt
│   └── extract_indices.cpp
├── PassThrough
│   ├── CMakeLists.txt
│   └── passthrough.cpp
├── ProjectInliers
│   ├── CMakeLists.txt
│   └── project_inliers.cpp
├── RemoveOutliers
│   ├── CMakeLists.txt
│   └── remove_outliers.cpp
├── StatisticalRemoval
│   ├── CMakeLists.txt
│   └── statistical_removal.cpp
└── VoxelGrid
    ├── CMakeLists.txt
    └── voxel_grid.cpp

1. 使用 PassThrough 过滤器过滤点云

这一小节主要目的是:如何沿指定维度执行简单的过滤,即截断给定用户范围内部或外部的值。

1.1 实现代码

工程文件夹名为PassThrough

passthrough.cpp代码如下:


#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>

int main(){
    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 (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;
    
    }

    // 创建过滤器对象
    pcl::PassThrough<pcl::PointXYZ> pass;
    pass.setInputCloud(cloud);
    pass.setFilterFieldName("z");
    pass.setFilterLimits(0.0, 1.0);

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

1.2 CMakeLists.txt文件

CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(PassThrough)

find_package(PCL 1.8.1 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (PassThrough passthrough.cpp)
target_link_libraries (PassThrough ${PCL_LIBRARIES})

1.3 运行结果

编译执行结果如下:

Cloud before filtering: 
      0.352222 -0.151883 -0.106395
      -0.397406 -0.473106 0.292602
      -0.731898 0.667105 0.441304
      -0.734766 0.854581 -0.0361733
      -0.4607 -0.277468 -0.916762
Cloud after filtering: 
      -0.397406 -0.473106 0.292602
      -0.731898 0.667105 0.441304

2. 使用 VoxelGrid 过滤器对点云进行下采样

2.1 实现代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>

int main(){
    pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2());
    pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2());

    pcl::PCDReader reader;
    reader.read("../../data/table_scene_lms400.pcd", *cloud);

    std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
              << " data points(" << pcl::getFieldsList(*cloud) << ")." << std::endl;

    pcl::VoxelGrid<pcl::PCLPointCloud2> 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) << ")." << std::endl;

    pcl::PCDWriter writer;
    writer.write ("../../data/table_scene_lms400_downsampled.pcd", *cloud_filtered,
            Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);

    return (0);
}

2.2 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(VoxelGrid)

find_package(PCL 1.8 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})

add_executable(VoxelGrid voxel_grid.cpp)
target_link_libraries(VoxelGrid ${PCL_LIBRARIES})

2.3 运行结果

3. 使用 StatisticalOutlierRemoval 过滤器删除异常值

3.1 实现代码

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>

int main(){
    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<pcl::PointXYZ> ("../../data/table_scene_lms400.pcd", *cloud);

    std::cerr << "Cloud before filtering: " << std::endl;
    std::cerr << *cloud << std::endl;

    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud);
    sor.setMeanK(50);
    sor.setStddevMulThresh(1.0);
    sor.filter(*cloud_filtered);

    std::cerr << "Cloud after filtering: " << std::endl;
    std::cerr << *cloud_filtered << std::endl;

    pcl::PCDWriter writer;
    writer.write<pcl::PointXYZ> ("../../data/table_scene_lms400_inliers.pcd", *cloud_filtered, false);

    sor.setNegative(true);
    sor.filter(*cloud_filtered);
    writer.write<pcl::PointXYZ> ("../../data/table_scene_lms400_outliers.pcd", *cloud_filtered, false);

    return (0);
}

3.2 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(StatisticalRemoval)

find_package(PCL 1.8 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})

add_executable(StatisticalRemoval statistical_removal.cpp)
target_link_libraries(StatisticalRemoval ${PCL_LIBRARIES})

3.3 运行结果

4. 使用参数模型投影点

4.1 实现代码

#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/project_inliers.h>

int main(){
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projectd (new pcl::PointCloud<pcl::PointXYZ>);

    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 projection: " << std::endl;
    for (const auto& point: *cloud){
        std::cerr << "      " << point.x << " "
                              << point.y << " "
                              << point.z << std::endl;
    }

    pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = coefficients->values[1] = 0;
    coefficients->values[2] = 1.0;
    coefficients->values[3] = 0;

    pcl::ProjectInliers<pcl::PointXYZ> proj;
    proj.setModelType (pcl::SACMODEL_PLANE);
    proj.setInputCloud (cloud);
    proj.setModelCoefficients (coefficients);
    proj.filter (*cloud_projectd);

    std::cerr << "Cloud after projection: " << std::endl;
    for (const auto& point: *cloud_projectd){
        std::cerr << "      " << point.x << " "
                              << point.y << " "
                              << point.z << std::endl;        
    }
    return (0);
}

4.2 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(ProjectInliers)

find_package(PCL 1.8 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})

add_executable(ProjectInliers project_inliers.cpp)
target_link_libraries(ProjectInliers ${PCL_LIBRARIES})

4.3 运行结果

5. 从点云中提取索引

5.1 实现代码


#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(){
    pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filterd_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 ("../../data/table_scene_lms400.pcd", *cloud_blob);

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

    pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
    sor.setInputCloud (cloud_blob);
    sor.setLeafSize (0.01f, 0.01f, 0.01f);
    sor.filter (*cloud_filterd_blob);

    pcl::fromPCLPointCloud2 (*cloud_filterd_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;
    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();
    while (cloud_filtered->size() == 0){
        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.setInputCloud (cloud_filtered);
        extract.setIndices (inliers);
        extract.setNegative (false);
        extract.filter (*cloud_p);
        std::cerr << "PointCloud reqresenting 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);
}

5.2 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(ExtractIndices)

find_package(PCL 1.8 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINTIONS})

add_executable(ExtractIndices extract_indices.cpp)
target_link_libraries(ExtractIndices ${PCL_LIBRARIES})

5.3 运行结果

6. 使用条件或半径异常值删除来删除异常值

6.1 实现代码


#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>

int main(){
    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->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);

    }

    if (strcmp(argc[1], "-r") == 0){
        pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
        outrem.setInputCloud(cloud);
        outrem.setRadiusSearch(0.8);
        outrem.setMinNeighborsInRadius (2);
        outrem.setKeepOrganized(true);

        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.8)));

        pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
        condrem.setCondition (range_cond);
        codnrem.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 (const auto& point: *cloud){
        std::cerr << "      " << point.x << " "
                              << point.y << " "
                              << point.z << std::endl;
    }
    return (0);
}

6.2 CMakeLists.txt文件

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(RemoveOutliers)

find_package(PCL 1.8 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories((${PCL_LIBRARY_DIRS}))
add_definitions(${PCL_DEFINITIONS})

add_executable(RemoveOutliers remove_outliers.cpp)
target_link_libraries(RemoveOutliers ${PCL_LIBRARY_DIRS})

6.3 运行结果



Reference:




须知少时凌云志,曾许人间第一流。



⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZPILOTE

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

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

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

打赏作者

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

抵扣说明:

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

余额充值