Downsampling 3D Point Clouds with a Voxelized Grid

This tutorial covers the process of downsampling / reducing the number of points in a 3D point cloud through a voxelized grid approach.

Note

This tutorial is applicable for execution both within inside and outside a Docker* image. It assumes that the pcl-oneapi-tutorials Deb package is installed, and the user has copied the tutorial directory from /opt/intel/pcl/oneapi/tutorials/ to a user-writable directory.

  1. Prepare the environment:

    cd <path-to-oneapi-tutorials>/voxel_grid
    
    Copy to clipboard
  2. oneapi_voxel_grid.cpp should be in the directory with following content:

     1#include <pcl/oneapi/filters/voxel_grid.h>
     2#include <pcl/io/pcd_io.h>
     3#include <pcl/point_types.h>
     4#include <pcl/point_cloud.h>
     5
     6
     7int main (int argc, char** argv)
     8{
     9  std::cout << "Running on device: " << dpct::get_default_queue().get_device().get_info<sycl::info::device::name>() << "\n";
    10
    11  // Read Point Cloud
    12  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_( new pcl::PointCloud<pcl::PointXYZ>() );
    13  int result = pcl::io::loadPCDFile("table_scene_lms400.pcd", *cloud_);
    14  if (result != 0)
    15  {
    16    pcl::console::print_info ("Load pcd file failed.\n");
    17    return result;
    18  }
    19
    20  // Prepare Point Cloud Memory (output)
    21  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_( new pcl::PointCloud<pcl::PointXYZ>() );
    22
    23  // GPU calculate
    24  pcl::oneapi::VoxelGrid<pcl::PointXYZ> vg_oneapi;
    25  vg_oneapi.setInputCloud(cloud_);
    26  float leafsize= 0.005f;
    27  vg_oneapi.setLeafSize (leafsize, leafsize, leafsize);
    28  vg_oneapi.filter(*cloud_filtered_);
    29
    30  // print log
    31  std::cout << "[oneapi voxel grid] PointCloud before filtering: " << cloud_->size() << std::endl;
    32  std::cout << "[oneapi voxel grid] PointCloud after filtering: " << cloud_filtered_->size() << std::endl;
    33}
    
    Copy to clipboard
  3. Source the Intel® oneAPI Base Toolkit environment:

    source /opt/intel/oneapi/setvars.sh
    
    Copy to clipboard
  4. (Optional) Setup proxy setting to download test data:

    export http_proxy="http://<http_proxy>:port"
    export https_proxy="http://<https_proxy>:port"
    
    Copy to clipboard
  5. Build the code:

    mkdir build && cd build
    cmake ../
    make -j
    
    Copy to clipboard
  6. Run the binary:

    ./oneapi_voxel_grid
    
    Copy to clipboard
  7. Expected results example:

    [oneapi voxel grid] PointCloud before filtering: 460400
    [oneapi voxel grid] PointCloud after filtering: 141525
    
    Copy to clipboard

Code Explanation

Now, let’s explain the code in detail.

First, load the example PCD into a PointCloud<PointXYZ>.

  // Read Point Cloud
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_( new pcl::PointCloud<pcl::PointXYZ>() );
  int result = pcl::io::loadPCDFile("table_scene_lms400.pcd", *cloud_);
  if (result != 0)
  {
    pcl::console::print_info ("Load pcd file failed.\n");
    return result;
  }
Copy to clipboard

Then prepare output buffer for filtered result.

  // Prepare Point Cloud Memory (output)
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered_( new pcl::PointCloud<pcl::PointXYZ>() );
Copy to clipboard

Next, starts to compute the result.

  // GPU calculate
  pcl::oneapi::VoxelGrid<pcl::PointXYZ> vg_oneapi;
  vg_oneapi.setInputCloud(cloud_);
  float leafsize= 0.005f;
  vg_oneapi.setLeafSize (leafsize, leafsize, leafsize);
  vg_oneapi.filter(*cloud_filtered_);
Copy to clipboard

Result(output log).

  // print log
  std::cout << "[oneapi voxel grid] PointCloud before filtering: " << cloud_->size() << std::endl;
  std::cout << "[oneapi voxel grid] PointCloud after filtering: " << cloud_filtered_->size() << std::endl;
Copy to clipboard