Using SampleConsensusInitialAligment (SCIA) to Initial Align Two Point Clouds#

In this tutorial, we will learn how to initial align two point clouds, using SCIA, provided with the transformation 4x4 matrix.

Note

This tutorial is applicable for execution for 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>/sample_consensus_initial_alignment
    
  2. oneapi_scia.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/registration/ia_ransac.h>
     4#include <pcl/io/pcd_io.h>
     5#include <pcl/point_types.h>
     6#include <pcl/point_cloud.h>
     7
     8
     9using namespace pcl;
    10using namespace pcl::io;
    11
    12int main (int argc, char** argv)
    13{
    14  std::cout << "Running on device: " << dpct::get_default_queue().get_device().get_info<sycl::info::device::name>() << "\n";
    15
    16  // Read Point Cloud
    17  PointCloud<PointXYZ> cloud_source, cloud_target;
    18  PointCloud<FPFHSignature33> FPFH_cloud_source, FPFH_cloud_target;
    19
    20  if (loadPCDFile<PointXYZ>("../../data/scia_source.pcd", cloud_source) < 0)
    21  {
    22    std::cerr << "Failed to read alignment source point cloud, please check scia_source.pcd" << std::endl;
    23    return (-1);
    24  }
    25  if (loadPCDFile<PointXYZ>("../../data/scia_target.pcd", cloud_target) < 0)
    26  {
    27    std::cerr << "Failed to read alignment target point cloud, please check scia_target.pcd" << std::endl;
    28    return (-1);
    29  }
    30  if (loadPCDFile<FPFHSignature33>("../../data/scia_source_fpfh33.pcd", FPFH_cloud_source) < 0)
    31  {
    32    std::cerr << "Failed to read FPFH feature cloud of alignment source point cloud, please check scia_source_fpfh33.pcd" << std::endl;
    33    return (-1);
    34  }
    35  if (loadPCDFile<FPFHSignature33>("../../data/scia_target_fpfh33.pcd", FPFH_cloud_target) < 0)
    36  {
    37    std::cerr << "Failed to read FPFH feature cloud of alignment target point cloud, please check scia_target_fpfh33.pcd" << std::endl;
    38    return (-1);
    39  }
    40
    41  // GPU calculate
    42  pcl::oneapi::SampleConsensusInitialAlignment<PointXYZ, PointXYZ, FPFHSignature33> scia;
    43  scia.setInputSource(cloud_source.makeShared());
    44  scia.setInputTarget(cloud_target.makeShared());
    45  scia.setSourceFeatures(FPFH_cloud_source.makeShared());
    46  scia.setTargetFeatures(FPFH_cloud_target.makeShared());
    47
    48  constexpr float SACdismin = 0.02f;
    49  constexpr int SCANum = 20;
    50  constexpr int SCAradomn = 100;
    51  scia.setMinSampleDistance(SACdismin);
    52  scia.setNumberOfSamples(SCANum);
    53  scia.setCorrespondenceRandomness(SCAradomn);
    54
    55  PointCloud<PointXYZ> cloud_result;
    56  Eigen::Matrix4f sac_trans;
    57  scia.align(cloud_result);
    58  sac_trans = scia.getFinalTransformation();
    59
    60  // print log
    61  std::cout << "[oneapi SCIA] Transformation Matrix 4x4 = " << std::endl << sac_trans << std::endl;
    62}
    
  3. Source the Intel® oneAPI Base Toolkit environment:

    source /opt/intel/oneapi/setvars.sh
    
  4. Build the code:

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

    ./oneapi_scia
    
  6. Expected results example:

    [oneapi SCIA] Transformation Matrix 4x4 =
     0.268113 -0.734448 -0.623458  0.289958
     0.748389 -0.248733  0.614853 -0.208532
    -0.606653  -0.63144  0.482965  0.229585
            0         0         0         1
    

Code Explanation#

Load source/target/fpfh_source/fpfh_target PCD file

if (loadPCDFile<PointXYZ>("../../data/scia_source.pcd", cloud_source) < 0)
{
  std::cerr << "Failed to read alignment source point cloud, please check scia_source.pcd" << std::endl;
  return (-1);
}
if (loadPCDFile<PointXYZ>("../../data/scia_target.pcd", cloud_target) < 0)
{
  std::cerr << "Failed to read alignment target point cloud, please check scia_target.pcd" << std::endl;
  return (-1);
}

Load the example source/target/fpfh_source/fpfh_target PCD into a PointCloud<PointXYZ/FPFHSignature33>.

if (loadPCDFile<FPFHSignature33>("../../data/scia_source_fpfh33.pcd", FPFH_cloud_source) < 0)
{
  std::cerr << "Failed to read FPFH feature cloud of alignment source point cloud, please check scia_source_fpfh33.pcd" << std::endl;
  return (-1);
}
if (loadPCDFile<FPFHSignature33>("../../data/scia_target_fpfh33.pcd", FPFH_cloud_target) < 0)
{
  std::cerr << "Failed to read FPFH feature cloud of alignment target point cloud, please check scia_target_fpfh33.pcd" << std::endl;
  return (-1);
}

Start to compute the model.

// GPU calculate
pcl::oneapi::SampleConsensusInitialAlignment<PointXYZ, PointXYZ, FPFHSignature33> scia;
scia.setInputSource(cloud_source.makeShared());
scia.setInputTarget(cloud_target.makeShared());
scia.setSourceFeatures(FPFH_cloud_source.makeShared());
scia.setTargetFeatures(FPFH_cloud_target.makeShared());

constexpr float SACdismin = 0.02f;
constexpr int SCANum = 20;
constexpr int SCAradomn = 100;
scia.setMinSampleDistance(SACdismin);
scia.setNumberOfSamples(SCANum);
scia.setCorrespondenceRandomness(SCAradomn);

PointCloud<PointXYZ> cloud_result;
Eigen::Matrix4f sac_trans;
scia.align(cloud_result);
sac_trans = scia.getFinalTransformation();

Result (output log).

// print log
std::cout << "[oneapi SCIA] Transformation Matrix 4x4 = " << std::endl << sac_trans << std::endl;