Surface Reconstruction with oneAPI™ Moving Least Squares (MLS)

MLS creates a 3D surface from a point cloud through either down-sampling or up-sampling techniques. Intel® oneAPI Base Toolkit's MLS is based on the original MLS API. Differences between the two:

  • oneapi MLS calculates with 32-bit float instead of 64-bit double.

  • oneapi MLS’s surface is constructed as a set of indices grouped into multiple blocks. This consumes more system memory than the original version. Control the block size with setSearchBlockSize.

  • oneapi MLS improves the performance of all up-sampling methods.

  • The oneapi namespace must be appended to the original MovingLeastSquares class.

See resampling.rst for details.

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>/mls
    
    Copy to clipboard
  2. oneapi_mls.cpp should be in the directory with following content:

     1#include <pcl/oneapi/surface/mls.h>
     2#include <pcl/oneapi/search/kdtree.h>
     3#include <pcl/point_types.h>
     4#include <pcl/io/pcd_io.h>
     5
     6
     7using namespace pcl::oneapi;
     8
     9int main (int argc, char** argv)
    10{
    11  std::cout << "Running on device: " << dpct::get_default_queue().get_device().get_info<sycl::info::device::name>() << "\n";
    12
    13  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr( new pcl::PointCloud<pcl::PointXYZ>() );
    14
    15  // Load bun0.pcd
    16  pcl::io::loadPCDFile ("bun0.pcd", *cloud_ptr);
    17
    18  pcl::oneapi::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::oneapi::KdTreeFLANN<pcl::PointXYZ>);
    19
    20  // Output has the PointNormal type in order to store the normals calculated by MLS
    21  pcl::PointCloud<pcl::PointNormal> mls_points;
    22
    23  // Init object (second point type is for the normals, even if unused)
    24  pcl::oneapi::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;
    25
    26  mls.setComputeNormals (true);
    27
    28  // Set parameters
    29  mls.setInputCloud (cloud_ptr);
    30  mls.setPolynomialOrder (2);
    31  mls.setSearchMethod (tree);
    32  mls.setSearchRadius (0.03);
    33
    34  // Reconstruct
    35  mls.process (mls_points);
    36
    37  // Save output
    38  pcl::io::savePCDFile ("bun0-mls.pcd", mls_points);
    39}
    
    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_mls
    
    Copy to clipboard
  7. The reconstructed surface saves as bun0-mls.pcd. To view the smoothed surface

    pcl_viewer bun0-mls.pcd
    
    Copy to clipboard

Code Explanation

oneAPI™ MLS requires this header.

#include <pcl/oneapi/surface/mls.h>
#include <pcl/oneapi/search/kdtree.h>
Copy to clipboard

Load the test data into a PointCloud<PointXYZ> (these fields are mandatory; other fields are allowed and preserved).

  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr( new pcl::PointCloud<pcl::PointXYZ>() );

  // Load bun0.pcd
  pcl::io::loadPCDFile ("bun0.pcd", *cloud_ptr);
Copy to clipboard

Compare to original version, append oneapi namespace to original MovingLeastSquares class. The first template type is used for the input and output cloud. Only the XYZ dimensions of the input are smoothed in the output.

  // Init object (second point type is for the normals, even if unused)
  pcl::oneapi::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;
Copy to clipboard

If normal estimation is required:

  mls.setComputeNormals (true);
Copy to clipboard

The maximum polynomial order is five. See the code API (pcl:MovingLeastSquares) for default values and additional parameters to control the smoothing process.

  // Set parameters
  mls.setInputCloud (cloud_ptr);
  mls.setPolynomialOrder (2);
  mls.setSearchMethod (tree);
  mls.setSearchRadius (0.03);
Copy to clipboard

Perform reconstruction

  // Reconstruct
  mls.process (mls_points);
Copy to clipboard