Removing Outliers Using a StatisticalOutlierRemoval Filter#

This tutorial demonstrates the process of eliminating noisy measurements, e.g. outliers, from a point cloud data set using statistical analysis techniques. This is the oneAPI optimization version of pcl::StatisticalOutlierRemoval.

For more info of pcl::StatusticalOutlierRemoval filter, refer to this page.

Note

This tutorial is applicable for execution both 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>/statistical_outlier_removal
    
  2. oneapi_statistical_outlier_removal.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/filters/statistical_outlier_removal.h>
     4#include <pcl/point_types.h>
     5#include <pcl/point_cloud.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( new pcl::PointCloud<pcl::PointXYZ>() );
    16  // Fill in the cloud data
    17  pcl::io::loadPCDFile ("table_scene_lms400.pcd", *cloud);
    18
    19  std::cerr << "Cloud before filtering: " << std::endl;
    20  std::cerr << *cloud << std::endl;
    21
    22  pcl::PointCloud<pcl::PointXYZ>::Ptr oneapi_cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);
    23
    24  // Create the filtering object
    25  pcl::oneapi::StatisticalOutlierRemoval<pcl::PointXYZ> oneapi_sor;
    26  oneapi_sor.setInputCloud(cloud);
    27  oneapi_sor.setMeanK(50);
    28  oneapi_sor.setStddevMulThresh(1.0);
    29  oneapi_sor.filter(*oneapi_cloud_filtered);
    30
    31  std::cerr << "Cloud after filtering: " << std::endl;
    32  std::cerr << *oneapi_cloud_filtered << std::endl;
    33
    34  pcl::PCDWriter writer;
    35  writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *oneapi_cloud_filtered, false);
    36
    37  oneapi_sor.setNegative (true);
    38  oneapi_sor.filter (*oneapi_cloud_filtered);
    39  writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *oneapi_cloud_filtered, false);
    40
    41  return (0);
    42}
    
  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_statistical_outlier_removal
    
  7. Expected results example:

    Cloud before filtering:
    header: seq: 0 stamp: 0 frame_id:
    
    points[]: 460400
    width: 460400
    height: 1
    is_dense: 1
    sensor origin (xyz): [0, 0, 0] / orientation (xyzw): [0, 0, 0, 1]
    
    Cloud after filtering:
    header: seq: 0 stamp: 0 frame_id:
    
    points[]: 451410
    width: 451410
    height: 1
    is_dense: 1
    sensor origin (xyz): [0, 0, 0] / orientation (xyzw): [0, 0, 0, 1]
    

Code Explanation#

Now, let’s break down the code piece by piece.

The following lines of code will read the point cloud data from disk.

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud( new pcl::PointCloud<pcl::PointXYZ>() );
// Fill in the cloud data
pcl::io::loadPCDFile ("table_scene_lms400.pcd", *cloud);

Then, a pcl::StatisticalOutlierRemoval filter is created. The number of neighbors to analyze for each point is set to 50, and the standard deviation multiplier threshold to 1. What this means is that all points that have distance larger than 1 standard deviation of the mean distance to the query point will be marked as outliers and removed. The output is computed and stored in oneapi_cloud_filtered.

// Create the filtering object
pcl::oneapi::StatisticalOutlierRemoval<pcl::PointXYZ> oneapi_sor;
oneapi_sor.setInputCloud(cloud);
oneapi_sor.setMeanK(50);
oneapi_sor.setStddevMulThresh(1.0);
oneapi_sor.filter(*oneapi_cloud_filtered);

The remaining data (inliers) is written to disk for later inspection.

pcl::PCDWriter writer;

Then, the filter is called with the same parameters, but with the output negated, to obtain the outliers (e.g., the points that were filtered).

oneapi_sor.setNegative (true);
oneapi_sor.filter (*oneapi_cloud_filtered);

And the data is written back to disk.

writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *oneapi_cloud_filtered, false);