0.引言

\qquad

PCL的体素滤波器如果对超大容量点云进行降采样,要求降采样后的格点数目必须在整型的范围,不然就会报[pcl::VoxelGrid::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow的错误。本文使用PCL中OcTree结构实现大容量点云的分块存储和分块体素降采样,以达到近似的全局体素降采样效果。
StackOverFlow 参考链接🔗

1.普通体素降采样

\qquad

PCL普通的体素降采样只需要调用VoxelGrid库即可,这里给出了一个示例函数。只需要设置体素大小cell_x, cell_y, cell_z即可,其要求降采样后格点不能超过整型的最大值。对于激光雷达扫描的点云,一般原点云数超过10万就不能在再采用这个方法了。

#include <pcl/filters/extract_indices.h>  
#include <pcl/filters/filter.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/point_types.h>
typedef pcl::PointXYZI PointType;

pcl::PointCloud<PointType>::Ptr FILTREexample(pcl::PointCloud<PointType>::Ptr pointcloud, pcl::IndicesPtr indices, float cell_x, float cell_y, float cell_z) {
    pcl::PointCloud<PointType>::Ptr filtered_pointcloud(new pcl::PointCloud<PointType>);
    pcl::VoxelGrid<PointType> sor;
    sor.setInputCloud(pointcloud);
    sor.setLeafSize(cell_x, cell_y, cell_z);
    sor.filter(*filtered_pointcloud); // No problem :)
    return filtered_pointcloud;
}

2.OcTree体素降采样

\qquad

PCL库中并没有给出直接的实例教程,所以本文在这里简要说明以下,VoxelGrid体素滤波器有一个函数sor.setIndices(indices);,其中indices就是大体素点云拆分成一个个小点云团的分区序号数组,这个数组的构建通过OcrTree的近邻搜索加以构建,具体如下:

pcl::PointCloud<PointType>::Ptr subFilter(pcl::PointCloud<PointType>::Ptr pointcloud, pcl::IndicesPtr indices, float cell_x, float cell_y, float cell_z) {
    pcl::PointCloud<PointType>::Ptr filtered_pointcloud(new pcl::PointCloud<PointType>);
    pcl::VoxelGrid<PointType> sor;
    sor.setInputCloud(pointcloud);
    sor.setIndices(indices);
    sor.setLeafSize(cell_x, cell_y, cell_z);
    sor.filter(*filtered_pointcloud); // No problem :)
    return filtered_pointcloud;
}

pcl::PointCloud<PointType>::Ptr OctFilter(pcl::PointCloud<PointType>::Ptr cloudIn, float cell_x, float cell_y, float cell_z) {    
    pcl::octree::OctreePointCloudSearch<PointType> octree(128);  // // Octree resolution - side length of octree voxels
    octree.setInputCloud(cloudIn);
    octree.addPointsFromInputCloud();
    pcl::octree::OctreePointCloud<PointType>::LeafNodeIterator it;
    pcl::octree::OctreePointCloud<PointType>::LeafNodeIterator it_end = octree.leaf_depth_end();
    pcl::PointCloud<PointType>::Ptr filtered_cloud(new pcl::PointCloud<PointType>);    
    for (it = octree.leaf_depth_begin(); it != it_end; ++it)
    {

        pcl::IndicesPtr indexVector(new std::vector<int>);
        pcl::octree::OctreeContainerPointIndices& container = it.getLeafContainer();

        container.getPointIndices(*indexVector);
        *filtered_cloud += *subFilter(cloudIn, indexVector, cell_x,cell_y,cell_z);
    }
    return filtered_cloud;
}

其中128是Octree的分辨率,一般较大的点云需要设的大一些,如果设的过小,还是有可能在调用子函数subFilter产生相同的[pcl::VoxelGrid::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow错误。一个简单的用法如下:

pcl::PointCloud<PointType>::Ptr laserCloudIn(new pcl::PointCloud<PointType>);
// TODO: Load PointCloud into laserCloudIN
pcl::PointCloud<PointType>::Ptr laserCloudOut(new pcl::PointCloud<PointType>);
*laserCloudOut = *OctFilter(laserCloudIn, 0.05f, 0.05f, 0.05f);  // set your voxel size

版权声明:本文为weixin_44044411原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_44044411/article/details/128423091