Detecting Specific Models and Their Parameters in 3D Point Clouds#
This tutorial shows how to use these optimizations inside a Docker* image. For the same functionality outside of Docker* images, see PCL Optimizations Outside of Docker* Images.
Prepare the environment:
cd <edge_insights_for_amr_path>/Edge_Insights_for_Autonomous_Mobile_Robots_<version>/AMR_containers ./run_interactive_docker.sh eiforamr-full-flavour-sdk:2023.1 root -c full_flavor mkdir sample_consensus && cd sample_consensus
Create the file
oneapi_sample_consensus.cpp
:vim oneapi_sample_consensus.cpp
Place the following inside the file:
/* * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org * Copyright (c) 2010-2012, Willow Garage, Inc. * Copyright (c) 2014-, Open Perception, Inc. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the copyright holder(s) nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include <pcl/oneapi/sample_consensus/sac_model_plane.h> #include <pcl/oneapi/sample_consensus/ransac.h> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/point_cloud.h> int main (int argc, char** argv) { // Read Point Cloud pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr( new pcl::PointCloud<pcl::PointXYZ>() ); pcl::PointCloud<pcl::PointXYZ>::Ptr convex_ptr; int result = pcl::io::loadPCDFile(argv[1], *cloud_ptr); if (result != 0) { pcl::console::print_info ("Load pcd file failed.\n"); return result; } // Prepare Device Point Cloud Memory pcl::oneapi::SampleConsensusModel::PointCloud_xyz cloud_device_xyz; cloud_device_xyz.upload(cloud_ptr->points); pcl::oneapi::SampleConsensusModel::PointCloud & cloud_device = (pcl::oneapi::SampleConsensusModel::PointCloud &)cloud_device_xyz; // Algorithm tests typename pcl::oneapi::SampleConsensusModelPlane::Ptr sac_model (new pcl::oneapi::SampleConsensusModelPlane (cloud_device)); pcl::oneapi::RandomSampleConsensus sac (sac_model); sac.setMaxIterations (10000); sac.setDistanceThreshold (0.03); result = sac.computeModel (); // Best model pcl::oneapi::SampleConsensusModelPlane::Indices sample; sac.getModel (sample); // Coefficient pcl::oneapi::SampleConsensusModelPlane::Coefficients coeffs; sac.getModelCoefficients (coeffs); // Inliers pcl::Indices pcl_inliers; int inliers_size = sac.getInliersSize (); pcl_inliers.resize(inliers_size); pcl::oneapi::SampleConsensusModelPlane::IndicesPtr inliers = sac.getInliers (); inliers->download(pcl_inliers.data(), 0, inliers_size); // Refined coefficient pcl::oneapi::SampleConsensusModelPlane::Coefficients coeff_refined; sac_model->optimizeModelCoefficients (*cloud_ptr, pcl_inliers, coeffs, coeff_refined); // print log std::cout << "input cloud size: " << cloud_ptr->points.size() << std::endl; std::cout << "inliers size : " << inliers_size << std::endl; std::cout << " plane model coefficient: " << coeffs[0] << ", " << coeffs[1] << ", " << coeffs[2] << ", " << coeffs[3] << std::endl; std::cout << " Optimized coefficient : " << coeff_refined[0] << ", " << coeff_refined[1] << ", " << coeff_refined[2] << ", " << coeff_refined[3] << std::endl; }
Create a CMakeLists.txt file:
vim CMakeLists.txt
Place the following inside the file:
cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(target oneapi_sample_consensus) set(CMAKE_CXX_COMPILER dpcpp) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "-Wall -Wpedantic -Wno-unknown-pragmas -Wno-pass-failed -Wno-unneeded-internal-declaration -Wno-unused-function -Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-extra-semi -Wno-unused-local-typedef -fsycl -fsycl-unnamed-lambda -ferror-limit=1") project(${target}) find_package(PCL 1.12 REQUIRED) find_package(PCL-ONEAPI 1.12 REQUIRED) include_directories(${PCL_INCLUDE_DIRS} ${PCL-ONEAPI_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS} ${PCL-ONEAPI_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS} ${PCL-ONEAPI_DEFINITIONS}) add_executable (${target} oneapi_sample_consensus.cpp) target_link_libraries (${target} sycl pcl_oneapi_sample_consensus ${PCL_LIBRARIES})
Source the Intel® oneAPI Base Toolkit environment:
export PATH=/home/eiforamr/workspace/lib/pcl/share/pcl-1.12:/home/eiforamr/workspace/lib/pcl/share/pcl-oneapi-1.12:$PATH source /opt/intel/oneapi/setvars.sh
Build the code:
cd /home/eiforamr/workspace/sample_consensus/ mkdir build && cd build cmake ../ make -j
Download the test data from GitHub*:
wget https://raw.githubusercontent.com/PointCloudLibrary/data/5c26bdd0591ba150b91858b5c9fe5e91cb39ae86/segmentation/mOSD/test/test59.pcd # if the binary is not downloaded try setting the proxies first and try again: export http_proxy="http://<http_proxy>:port" export https_proxy="http://<https_proxy>:port"
Run the binary:
./oneapi_sample_consensus ./test59.pcd
Expected results example:
input cloud size: 307200
inliers size : 77316
plane model coefficient: -0.0789502, -0.816661, -0.571692, 0.546386
Optimized coefficient : -0.0722213, -0.818286, -0.570256, 0.547587
Code Explanation#
Load the test data from GitHub* into a PointCloud<PointXYZ>.
// Read Point Cloud
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr( new pcl::PointCloud<pcl::PointXYZ>() );
pcl::PointCloud<pcl::PointXYZ>::Ptr convex_ptr;
int result = pcl::io::loadPCDFile(argv[1], *cloud_ptr);
if (result != 0)
{
pcl::console::print_info ("Load pcd file failed.\n");
return result;
}
Create GPU input and output device arrays, and load point cloud data into the input device array.
// Prepare Device Point Cloud Memory
pcl::oneapi::SampleConsensusModel::PointCloud_xyz cloud_device_xyz;
cloud_device_xyz.upload(cloud_ptr->points);
pcl::oneapi::SampleConsensusModel::PointCloud & cloud_device = (pcl::oneapi::SampleConsensusModel::PointCloud &)cloud_device_xyz;
GPU: Start computing the model.
typename pcl::oneapi::SampleConsensusModelPlane::Ptr sac_model (new pcl::oneapi::SampleConsensusModelPlane (cloud_device));
pcl::oneapi::RandomSampleConsensus sac (sac_model);
sac.setMaxIterations (10000);
sac.setDistanceThreshold (0.03);
result = sac.computeModel ();
Result (best model):
pcl::oneapi::SampleConsensusModelPlane::Indices sample;
sac.getModel (sample);
Result (coefficient model):
pcl::oneapi::SampleConsensusModelPlane::Coefficients coeffs;
sac.getModelCoefficients (coeffs);
Result (inliers model):
pcl::Indices pcl_inliers;
int inliers_size = sac.getInliersSize ();
pcl_inliers.resize(inliers_size);
pcl::oneapi::SampleConsensusModelPlane::IndicesPtr inliers = sac.getInliers ();
inliers->download(pcl_inliers.data(), 0, inliers_size);
Result (refined coefficient model):
pcl::oneapi::SampleConsensusModelPlane::Coefficients coeff_refined;
sac_model->optimizeModelCoefficients (*cloud_ptr, pcl_inliers, coeffs, coeff_refined);
Result (output log):
std::cout << "input cloud size: " << cloud_ptr->points.size() << std::endl;
std::cout << "inliers size : " << inliers_size << std::endl;
std::cout << " plane model coefficient: " << coeffs[0] << ", " << coeffs[1] << ", " << coeffs[2] << ", " << coeffs[3] << std::endl;
std::cout << " Optimized coefficient : " << coeff_refined[0] << ", " << coeff_refined[1] << ", " << coeff_refined[2] << ", " << coeff_refined[3] << std::endl;