使用哪个 pcl 过滤器对点云进行下采样

Which pcl filter to use to downsample a point cloud

我正在从自动驾驶机器人上的激光雷达获取点云,但要处理的数据太多了。

我已经实现了直通过滤器。

我确实得到了一个很好的结果,我在问自己是否还有其他过滤器或方法可以深入研究。

当然,我不是在寻找任何具体的东西,而是在寻找方向或建议,因为我对 pcl 库还很陌生,而且它看起来非常庞大。

这是我的过滤器:

    pcl::PointCloud<PointXYZIR>::Ptr cloudInput;
    cloudInput.reset(new pcl::PointCloud<PointXYZIR> (cloud_in));

    pcl::PointCloud<PointXYZIR>::Ptr cloudFiltered;
    cloudFiltered.reset(new pcl::PointCloud<PointXYZIR>);

    // Create the filtering object: downsample the dataset using a leaf size
    pcl::VoxelGrid<PointXYZIR> avg;
    avg.setInputCloud(cloudInput);
    avg.setLeafSize(0.25f, 0.25f, 0.25f);
    avg.filter(*cloudFiltered);

    //Filter object
    pcl::PassThrough<PointXYZIR> filter;
    filter.setInputCloud(cloudFiltered);

    filter.setFilterFieldName("x");
    filter.setFilterLimits(-100, 100);
    filter.filter(*cloudFiltered);

    filter.setFilterFieldName("y");
    filter.setFilterLimits(-100, 100);
    filter.filter(*cloudFiltered);

    cloud_out = *cloudFiltered;

下采样的体素网格应该在减少点数的同时保持很好的云分布。您可以设置每个轴中的体素有多小,以便根据需要保持尽可能多或尽可能少的分辨率。每个体素将删除其中的所有点,并用从删除的点中取平均的单个点替换它们。 http://pointclouds.org/documentation/tutorials/voxel_grid.php#voxelgrid

其实我确实找到了解决办法,但是没有通用的解决办法。就我而言,我认为这个问题非常具体到您将获得哪个点云以及您想用它做什么。

passtrought 过滤器是一种非常有效的降采样方式,而且不会冒丢失有趣数据的太大风险。

http://pointclouds.org/documentation/tutorials/passthrough.php

然后我测试了 StatisticalOutlierRemoval,它很有效但与我的情况无关。

http://pointclouds.org/documentation/tutorials/statistical_outlier.php

现在,我使用 leafsize 函数对点云进行下采样,然后创建一个 kdtree 以按半径过滤点。 这与 passstrought 过滤器的计算量大致相同,但在我的项目中这样做更有意义。

 // Create the filtering object: downsample the dataset using a leaf size
    pcl::VoxelGrid<PointXYZIR> avg;
    avg.setInputCloud(cloudInput);
    avg.setLeafSize(0.25f, 0.25f, 0.25f);
    avg.filter(*cloudFiltered);

    //searchPoint
    PointXYZIR searchPoint = cloudFiltered->at(0) ;

    //result from radiusSearch()
    std::vector<int> pointIdxRadiusSearch;
    std::vector<float> pointRadiusSquaredDistance;

    //kdTree
    pcl::KdTreeFLANN<PointXYZIR> kdtree;
    kdtree.setInputCloud (cloudFiltered);
    kdtree.setSortedResults(true);

    if ( kdtree.radiusSearch (searchPoint, 100, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
    {
        //delete every point in target
        for (size_t j = 0; j < pointIdxRadiusSearch.size (); ++j)
        {
            //is this the way to erase correctly???
            cloud_out.push_back(cloudFiltered->points[pointIdxRadiusSearch[j]]);
        }
    }