Downsampling point clouds with PCL

PCL (Point Cloud Library) offers two ways that I know of to downsample a point cloud to a more manageable size.

The first uses pcl::VoxelGrid, and the second uses pcl::octree::OctreePointCloudVoxelCentroid.

They are both simple to use:


using Point = pcl::PointXYZ;
using Cloud = pcl::PointCloud<Point>;

float leaf = 1.f;
pcl::VoxelGrid<Point> vg;
vg.setLeafSize(leaf, leaf, leaf);
Cloud::Ptr output(new Cloud);

Here we create the filtering object, give it an input cloud to work on, give it the only parameter it requires, `leaf` being the voxel dimension, and filter it to a new output cloud.

The size of the resultant output cloud is dependent on the leaf size.


float leaf = 1.f;
pcl::octree::OctreePointCloudVoxelCentroid octree(leaf);
pcl::octree::OctreePointCloud::AlignedPointTVector centroids;

Cloud::Ptr output(new Cloud);
output->points.assign(centroids.begin(), centroids.end());
output->width = uint32_t(centroids.size());
output->height = 1;
output->is_dense = true;

Here we create an octree initialised with it’s voxel dimension, give it an input cloud to work with, and get back a vector of the centroids of all possible voxels. This vector can then be used to construct a new cloud.


In both cases the size of the output cloud is unknown beforehand. It’s dependent on the choice made for the voxel leaf dimension. Only after downsampling can you query the cloud for it’s size.

An iterative method is needed if you want to end up with a given size: You can perform one of the downsampling methods, and based on the resultant output size, adjust leaf up or down and do it again. Stop iterating when the output cloud size converges to within a tolerance of a required size or percentage of the input.

I do this for both methods in my hobby project of pcl-tools.