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

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

    source /opt/intel/oneapi/setvars.sh
    
  4. (Optional) Set up proxy setting to download test data:

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

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

    ./oneapi_mls
    
  7. The reconstructed surface saves as bun0-mls.pcd. To view the smoothed surface

    pcl_viewer bun0-mls.pcd
    

Code Explanation#

oneAPI MLS requires this header.

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

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);

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;

If normal estimation is required:

mls.setComputeNormals (true);

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);

Perform reconstruction

// Reconstruct
mls.process (mls_points);