【C++】PCL对大容量点云进行体素降采样

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::PointCloud<PointType>::Ptr filtered_cloud(new pcl::PointCloud<PointType>);    
    for (auto it = octree.leaf_depth_begin(); it != octree.leaf_depth_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
PCL(Point Cloud Library)是一个开源的点云处理库,提供了丰富的点云处理算法和工具。点云降采样点云处理中的一项重要任务,它可以减少点云数据的数量,从而降低计算和存储的成本,并且可以去除一些噪声点。 在PCL中,点云降采样可以通过使用VoxelGrid滤波器来实现。VoxelGrid滤波器将点云划分为一个个体素(或称为体素格子),然后对每个体素内的点进行采样,只保留一个代表性的点作为该体素的代表点。这样就可以将原始的稠密点云转换为稀疏的点云,从而实现降采样的效果。 以下是使用PCL进行点云降采样的步骤: 1. 创建一个VoxelGrid滤波器对象。 2. 设置滤波器的输入点云数据。 3. 设置滤波器的体素大小,即决定了降采样后的点云密度。 4. 调用滤波器的filter()函数进行降采样操作。 5. 获取滤波器的输出点云数据。 下面是一个示例代码片段,展示了如何使用PCL进行点云降采样: ```cpp #include <pcl/point_cloud.h> #include <pcl/filters/voxel_grid.h> int main() { // 创建点云对象 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 读取点云数据 // 创建VoxelGrid滤波器对象 pcl::VoxelGrid<pcl::PointXYZ> voxelGrid; // 设置输入点云数据 voxelGrid.setInputCloud(cloud); // 设置体素大小 voxelGrid.setLeafSize(0.01f, 0.01f, 0.01f); // 体素大小为1cm // 执行降采样操作 pcl::PointCloud<pcl::PointXYZ>::Ptr filteredCloud(new pcl::PointCloud<pcl::PointXYZ>); voxelGrid.filter(*filteredCloud); // 获取降采样后的点云数据 return 0; } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

非线性光学元件

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

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

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

打赏作者

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

抵扣说明:

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

余额充值