PCL滤波—使用索引滤波器过滤地面

PCL滤波—从一个点云中提取一个子集——ExtractIndices滤波器——索引滤波器
索引滤波的官方教程添加链接描述
使用该方法结合降采样和统计滤波可以很好的完成地面分离。
此处是索引滤波头文件

#include 

此处是重点,距离阈值的参数影响计算速度和地面分割精度,不同模型的参数不一样,一般是0.01-0.2之间取值

    seg.setMaxIterations(100);               //设置最大迭代次数
    seg.setDistanceThreshold(0.15);           //设置判断是否为模型内点的距离阈值

此处是判断保留内点还是反向选取,false是保留内点,true是反选

        extract.setIndices(inliers);
        extract.setNegative(false);
        extract.filter(*cloud_p);

这里加了一个循环结构,当还有60%原始点云数据时退出循环

    while (cloud_filtered->points.size() > 0.6 * nr_points)

以下是原代码和最终效果,保留了汽车分割掉了地面。
本文参考了添加链接描述
PCL滤波—使用索引滤波器过滤地面_第1张图片
PCL滤波—使用索引滤波器过滤地面_第2张图片

//索引滤波
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 

int
main(int argc, char** argv)
{
    //sensor_msgs::PointCloud2::Ptr cloud_blob (new sensor_msgs::PointCloud2), cloud_filtered_blob (new sensor_msgs::PointCloud2);
    pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);
    pcl::PCLPointCloud2::Ptr 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::PLYReader reader;
    reader.read("C:\\Users\\fhlhc\\Desktop\\car_left.ply", *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.06f, 0.06f, 0.06f);        //设置采样的体素大小
    sor.filter(*cloud_filtered_blob);            //执行采样保存数据cloud_filtered_blob

        统计滤波器,删除离群点
    pcl::StatisticalOutlierRemoval<pcl::PCLPointCloud2> Static;   //创建滤波器对象
    Static.setInputCloud(cloud_filtered_blob);                           //设置待滤波的点云
    Static.setMeanK(50);                               //设置在进行统计时考虑查询点临近点数
    Static.setStddevMulThresh(0.5);                      //设置判断是否为离群点的阀值
    Static.filter(*cloud_filtered_blob);                    //存储

    // 转化为模板点云
    //pcl::fromROSMsg(*cloud_filtered_blob, *cloud_filtered);
    pcl::fromPCLPointCloud2(*cloud_filtered_blob, *cloud_filtered);
    std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;

    // 将下采样后的数据存入磁盘
    pcl::PLYWriter writer;
  //writer.write("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.setOptimizeCoefficients(true);        //设置对估计的模型参数进行优化处理
    //必选
    seg.setModelType(pcl::SACMODEL_PLANE);    //设置分割模型类别
    seg.setMethodType(pcl::SAC_RANSAC);       //设置用哪个随机参数估计方法
    seg.setMaxIterations(100);               //设置最大迭代次数
    seg.setDistanceThreshold(0.15);           //设置判断是否为模型内点的距离阈值

    // 创建滤波器对象
    pcl::ExtractIndices<pcl::PointXYZ> extract;
    int i = 0, nr_points = (int)cloud_filtered->points.size();

    //为了处理点云中包含多个模型,在一个循环中执行该过程,
    //并在每次模型被提取后,我们保存剩余的点,进行迭代;
    //模型内点通过分割过程获取;
    //当还有60%原始点云数据时退出循环
    while (cloud_filtered->points.size() > 0.6 * 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.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(ss.str(), *cloud_p, false);

         // 创建滤波器对象
        extract.setNegative(true);
        extract.filter(*cloud_f);
        cloud_filtered.swap(cloud_f);
        i++;
    }
    cout << "迭代次数:"<<i << endl;
    pcl::visualization::CloudViewer viewer("Cloud Viewer");     //创建viewer对象
    viewer.showCloud(cloud_f);
    // viewer.runOnVisualizationThreadOnce(viewerOneOff);
    while (!viewer.wasStopped())
    {
        //在此处可以添加其他处理

    }
    return (0);
}

你可能感兴趣的:(PCL,滤波,点云)