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.
Prepare the environment:
cd <path-to-oneapi-tutorials>/mls
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}
Source the Intel® oneAPI Base Toolkit environment:
source /opt/intel/oneapi/setvars.sh
(Optional) Set up proxy setting to download test data:
export http_proxy="http://<http_proxy>:port" export https_proxy="http://<https_proxy>:port"
Build the code:
mkdir build && cd build cmake ../ make -j
Run the binary:
./oneapi_mls
The reconstructed surface saves as
bun0-mls.pcd
. To view the smoothed surfacepcl_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);