文章目录
- 0.引言
- 1.普通体素降采样
- 2.OcTree体素降采样
0.引言
\qquadPCL的体素滤波器如果对超大容量点云进行降采样,要求降采样后的格点数目必须在整型的范围,不然就会报[pcl::VoxelGrid::applyFilter] Leaf size is too small for the input dataset. Integer indices would overflow
的错误。本文使用PCL中OcTree结构实现大容量点云的分块存储和分块体素降采样,以达到近似的全局体素降采样效果。
StackOverFlow 参考链接🔗
1.普通体素降采样
\qquadPCL普通的体素降采样只需要调用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体素降采样
\qquadPCL库中并没有给出直接的实例教程,所以本文在这里简要说明以下,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 voxelsoctree.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