PCL官网:https://pointclouds.org/

turtorials:https://pcl.readthedocs.io/projects/tutorials/en/latest/

PCL官方提供了一系列案例,方便用户对点云数据进行处理:

点云库(PCL)是一个独立的、大规模的、开放的项目,用于2D/3D图像和点云处理。PCL是根据BSD许可的条款发布的,因此可以免费用于商业和研究。

无论你是刚刚发现了PCL还是你是一个长期的老手,这个页面包含了一组资源的链接,这些资源将有助于巩固你对PCL和3D处理的知识。开发人员的附加Wiki资源可在https://github.com/PointCloudLibrary/pcl/wiki。

为了简化使用和开发,我们将PCL分成一系列模块化库。PCL中最重要的发布模块集如下所示。

我们全面的PCL教程列表涵盖了许多主题,从简单的点云输入/输出操作到更复杂的应用程序,包括可视化、特征估计、分割等。

教程中可以用的案例汇总一下

目录

0 PCL源码安装:

0.1 安装依赖

0.2 下载PCL源码

0.3 编译库

0.4 安装OpenNI、OpenNI2(需要PCLVisualizer的话)

1 案例整理

1.1 <滤波>按照坐标信息过滤点云数据

1.2 <滤波>体素化网格降数据

1.3<滤波>根据表面法线、曲率变化去除噪声点

1.4<投影>点投影到平面,球体

1.5<分割>提取平面,曲面元素

1.6<滤波>邻近点个数滤除离散点

1.7<分割>提取在平面上的点

1.8<分割>圆柱型分割

1.9 <分割> 欧几里得分割

1.10 <分割> 区域增长细分

1.11 <分割> 基于颜色的区域增长分割

1.12 <分割> 基于最小剪切的细分

1.13<分割> 条件欧几里得聚类

1.14 <分割> 基于法线的分割的差异(没有点云数据,不能复现)

1.15 <分割> 将点云聚类为Supervoxels(报错误了不能复现)

1.16 <分割> 分割(没找到官方网址)

1.17 <分割>提取平面或球面的参数模型

1.18 <分割> 基于多项式重构的平滑和法线估计

1.19 <分割> 为平面模型构造凹凸的船体多边形

1.20 <分割> 无序点云的快速三角剖分

1.21 <分割> 将修剪的B样条曲线拟合到无序点云

1.22  使用积分图像进行正态估计

1.23  如何从范围图像中提取NARF特征

1.24 <分割> 基于惯性矩和偏心率的描述符

21


0 PCL源码安装:

环境:ubuntu16.04/18.04

知识共享开源有利于知识迭代本是好事儿,我坚持初心,知道多少写多少,不藏着掖着,

但是如果没有好的激励机制,笔者定会心生倦怠,理解我不容易的,可以下载我整理好的包,请我吃根雪糕

下面的程序使用是没问题的;

0.1 安装依赖

注:中间涉及到的需要选择Y/N,需要一句一句终端运行;带#号的是我自己验证出问题的,忽略这两个,也能用

    sudo apt-get update  sudo apt-get install git build-essential linux-libc-dev  #sudo apt-get install cmake cmake-gui   sudo apt-get install libusb-1.0-0-dev libusb-dev libudev-dev  sudo apt-get install mpi-default-dev openmpi-bin openmpi-common    sudo apt-get install libflann1.8 libflann-dev  sudo apt-get install libeigen3-dev  sudo apt-get install libboost-all-dev  sudo apt-get install libvtk5.10-qt4 libvtk5.10 libvtk5-dev  sudo apt-get install libqhull* libgtest-dev  sudo apt-get install freeglut3-dev pkg-config  sudo apt-get install libxmu-dev libxi-dev   sudo apt-get install mono-complete  #sudo apt-get install qt-sdk openjdk-8-jdk openjdk-8-jre 

0.2 下载PCL源码

下载位置:https://github.com/PointCloudLibrary/pcl

下载后解压到主目录下,默认名字为pcl_版本号,建议下载高于8.0的版本,默认下载是1.7.2,后面教程有的跑不通;

下载解压后,名字统一改成pcl

0.3 编译库

在PCL文件夹下进行cmake编译

ls
cd pcl
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=None -DCMAKE_INSTALL_PREFIX=/usr \ -DBUILD_GPU=ON -DBUILD_apps=ON -DBUILD_examples=ON \ -DCMAKE_INSTALL_PREFIX=/usr ..
make -j8
sudo make install

0.4 安装OpenNI、OpenNI2(需要PCLVisualizer的话)

sudo apt-get install libopenni-dev
sudo apt-get install libopenni2-dev

1 案例整理

PCL官方提供的可以用于使用的案例目录太长了,目录如下:https://blog.csdn.net/weixin_36662031/article/details/79352100

我把自己跑通过的案例,进行汇总了一下,便于随时调用:

1.1 <滤波>按照坐标信息过滤点云数据

在本教程中,我们将学习如何删除沿指定维度在用户给定间隔内/外的值的点。

注意,坐标轴表示为红色(x),绿色(y)和蓝色(z)。这五个点用绿色表示,表示过滤后剩余的点,用红色表示已被过滤器删除的点。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/passthrough.html#passthrough

创建目录,终端运行

mkdir 1
cd 1
mkdir passthrough
cd passthrough
gedit passthrough.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./passthrough

代码展示

##########################################
##########################################
##########################################
passthrough.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>intmain (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datacloud->width  = 5;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);for (std::size_t i = 0; i < cloud->points.size (); ++i){cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);}std::cerr << "Cloud before filtering: " << std::endl;for (std::size_t i = 0; i < cloud->points.size (); ++i)std::cerr << "    " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;// Create the filtering objectpcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0.0, 1.0);//pass.setFilterLimitsNegative (true);pass.filter (*cloud_filtered);std::cerr << "Cloud after filtering: " << std::endl;for (std::size_t i = 0; i < cloud_filtered->points.size (); ++i)std::cerr << "    " << cloud_filtered->points[i].x << " " << cloud_filtered->points[i].y << " " << cloud_filtered->points[i].z << std::endl;return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(passthrough)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (passthrough passthrough.cpp)
target_link_libraries (passthrough ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.2 <滤波>体素化网格降数据

学习如何使用体素化网格方法对点云数据集进行降采样(即减少点数)

官方链接 :https://pcl.readthedocs.io/projects/tutorials/en/latest/voxel_grid.html#voxelgrid

创建目录,终端运行

table_scene_lms400.pcd下载地址:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd

mkdir 2
cd 2
mkdir voxel_grid
cd voxel_grid
gedit voxel_grid.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_lms400.pcd放到./2/voxel_grid/build目录下
#有代码包的:cp ../../table_scene_lms400.pcd ./
./voxel_grid

显示结果

pcl_viewer table_scene_lms400.pcd#查看之前的pcd文件
#ctrl+shift+t新建一个终端
pcl_viewer table_scene_lms400_downsampled.pcd#查看处理后的文件

代码展示

##########################################
##########################################
##########################################
voxel_grid.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>int
main (int argc, char** argv)
{pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2 ());pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ());// Fill in the cloud datapcl::PCDReader reader;// Replace the path below with the path where you saved your filereader.read ("table_scene_lms400.pcd", *cloud); // Remember to download the file first!std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height << " data points (" << pcl::getFieldsList (*cloud) << ")." << std::endl;// Create the filtering objectpcl::VoxelGrid<pcl::PCLPointCloud2> sor;sor.setInputCloud (cloud);sor.setLeafSize (0.01f, 0.01f, 0.01f);sor.filter (*cloud_filtered);std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points (" << pcl::getFieldsList (*cloud_filtered) << ")." << std::endl;pcl::PCDWriter writer;writer.write ("table_scene_lms400_downsampled.pcd", *cloud_filtered, Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(voxel_grid)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (voxel_grid voxel_grid.cpp)
target_link_libraries (voxel_grid ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.3<滤波>根据表面法线、曲率变化去除噪声点

学习如何使用统计分析技术从点云数据集中去除噪声测量值,例如离群值

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/statistical_outlier.html#statistical-outlier-removal

创建目录,终端运行

table_scene_lms400.pcd下载地址:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd

mkdir 3
cd 3
mkdir statistical_removal
cd statistical_removal
gedit statistical_removal.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_lms400.pcd放到./3/statistical_removal/build目录下
#有代码包的:cp ../../table_scene_lms400.pcd ./
./statistical_removal

显示结果

pcl_viewer table_scene_lms400.pcd#查看之前的pcd文件
#ctrl+shift+t新建一个终端
pcl_viewer table_scene_lms400_inliers.pcd#查看处理后的文件
#ctrl+shift+t新建一个终端
pcl_viewer table_scene_lms400_outliers.pcd#查看处理后的文件

代码展示

##########################################
##########################################
##########################################
statistical_removal.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>int
main (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datapcl::PCDReader reader;// Replace the path below with the path where you saved your filereader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud);std::cerr << "Cloud before filtering: " << std::endl;std::cerr << *cloud << std::endl;// Create the filtering objectpcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;sor.setInputCloud (cloud);sor.setMeanK (50);sor.setStddevMulThresh (1.0);sor.filter (*cloud_filtered);std::cerr << "Cloud after filtering: " << std::endl;std::cerr << *cloud_filtered << std::endl;pcl::PCDWriter writer;writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);sor.setNegative (true);sor.filter (*cloud_filtered);writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(statistical_removal)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (statistical_removal statistical_removal.cpp)
target_link_libraries (statistical_removal ${PCL_LIBRARIES})

激光扫描通常会生成变化的点密度的点云数据集。此外,测量误差会导致稀疏的异常值,从而进一步破坏结果。这会使局部点云特性(例如表面法线或曲率变化)的估计复杂化,从而导致错误的值,进而可能导致点云配准失败。通过对每个点的邻域进行统计分析,并修整不符合特定标准的那些不规则现象,可以解决其中的一些不规则现象。我们稀疏的异常值消除是基于输入数据集中点到邻居距离分布的计算。对于每个点,我们计算从它到所有相邻点的平均距离。假设结果的分布是高斯分布,具有均值和标准差,

下图显示了稀疏离群值分析和删除的效果:原始数据集显示在左侧,而结果数据集显示在右侧。该图显示了滤波前后一个点邻域中的平均k最近邻距离。

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.4<投影>点投影到平面,球体

学习如何将点投影到参数模型(例如,平面,球体等)上。参数模型通过一组系数给出-在平面情况下,通过其方程式:ax + by + cz + d = 0

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/project_inliers.html#project-inliers

创建目录,终端运行

mkdir 4
cd 4
gedit project_inliers.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./project_inliers

显示结果

代码展示

##########################################
##########################################
##########################################
project_inliers.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/ModelCoefficients.h>
#include <pcl/filters/project_inliers.h>intmain (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datacloud->width  = 5;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);for (std::size_t i = 0; i < cloud->points.size (); ++i){cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);}std::cerr << "Cloud before projection: " << std::endl;for (std::size_t i = 0; i < cloud->points.size (); ++i)std::cerr << "    " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;// Create a set of planar coefficients with X=Y=0,Z=1pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());coefficients->values.resize (4);coefficients->values[0] = coefficients->values[1] = 0;coefficients->values[2] = 1.0;coefficients->values[3] = 0;// Create the filtering objectpcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType (pcl::SACMODEL_PLANE);proj.setInputCloud (cloud);proj.setModelCoefficients (coefficients);proj.filter (*cloud_projected);std::cerr << "Cloud after projection: " << std::endl;for (std::size_t i = 0; i < cloud_projected->points.size (); ++i)std::cerr << "    " << cloud_projected->points[i].x << " " << cloud_projected->points[i].y << " " << cloud_projected->points[i].z << std::endl;return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(project_inliers)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (project_inliers project_inliers.cpp)
target_link_libraries (project_inliers ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.5<分割>提取平面,曲面元素

基于分段算法输出的索引从点云中提取点的子集

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/extract_indices.html#extract-indices

创建目录,终端运行

table_scene_lms400.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd

mkdir 5
cd 5
gedit extract_indices.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_lms400.pcd放到./5/extract_indices/build目录下
#有代码包的:cp ../../table_scene_lms400.pcd ./
./extract_indices

结果显示

pcl_viewer table_scene_lms400.pcd#查看之前的pcd文件
#ctrl+shift+t新建一个终端
pcl_viewer table_scene_lms400_downsampled.pcd#查看处理后的文件
#ctrl+shift+t新建一个终端
pcl_viewer pcl_viewer  table_scene_lms400_plane_*.pcd#查看处理后的文件

代码展示

##########################################
##########################################
##########################################
extract_indices.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/extract_indices.h>int
main (int argc, char** argv)
{pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datapcl::PCDReader reader;reader.read ("table_scene_lms400.pcd", *cloud_blob);std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;// Create the filtering object: downsample the dataset using a leaf size of 1cmpcl::VoxelGrid<pcl::PCLPointCloud2> sor;sor.setInputCloud (cloud_blob);sor.setLeafSize (0.01f, 0.01f, 0.01f);sor.filter (*cloud_filtered_blob);// Convert to the templated PointCloudpcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;// Write the downsampled version to diskpcl::PCDWriter writer;writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());// Create the segmentation objectpcl::SACSegmentation<pcl::PointXYZ> seg;// Optionalseg.setOptimizeCoefficients (true);// Mandatoryseg.setModelType (pcl::SACMODEL_PLANE);seg.setMethodType (pcl::SAC_RANSAC);seg.setMaxIterations (1000);seg.setDistanceThreshold (0.01);// Create the filtering objectpcl::ExtractIndices<pcl::PointXYZ> extract;int i = 0, nr_points = (int) cloud_filtered->points.size ();// While 30% of the original cloud is still therewhile (cloud_filtered->points.size () > 0.3 * nr_points){// Segment the largest planar component from the remaining cloudseg.setInputCloud (cloud_filtered);seg.segment (*inliers, *coefficients);if (inliers->indices.size () == 0){std::cerr << "Could not estimate a planar model for the given dataset." << std::endl;break;}// Extract the inliersextract.setInputCloud (cloud_filtered);extract.setIndices (inliers);extract.setNegative (false);extract.filter (*cloud_p);std::cerr << "PointCloud representing the planar component: " << cloud_p->width * cloud_p->height << " data points." << std::endl;std::stringstream ss;ss << "table_scene_lms400_plane_" << i << ".pcd";writer.write<pcl::PointXYZ> (ss.str (), *cloud_p, false);// Create the filtering objectextract.setNegative (true);extract.filter (*cloud_f);cloud_filtered.swap (cloud_f);i++;}return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(extract_indices)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (extract_indices extract_indices.cpp)
target_link_libraries (extract_indices ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.6<滤波>邻近点个数滤除离散点

该过滤器将删除其输入云中在一定范围内没有至少一些邻居的所有索引

每个索引必须具有指定半径内的邻居才能保留在PointCloud中。例如,如果指定了1个邻居,则只会从PointCloud中删除黄点。如果指定了2个邻居,则黄点和绿点都将从PointCloud中删除。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/remove_outliers.html#remove-outliers

创建目录,终端运行

mkdir 6
cd 6
gedit remove_outliers.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./remove_outliers
./remove_outliers -c
./remove_outliers -r

结果显示

代码展示

##########################################
##########################################
##########################################
remove_outliers.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>intmain (int argc, char** argv)
{if (argc != 2){std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;exit(0);}pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datacloud->width  = 5;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);for (std::size_t i = 0; i < cloud->points.size (); ++i){cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);}if (strcmp(argv[1], "-r") == 0){pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;// build the filteroutrem.setInputCloud(cloud);outrem.setRadiusSearch(0.8);outrem.setMinNeighborsInRadius (2);// apply filteroutrem.filter (*cloud_filtered);}else if (strcmp(argv[1], "-c") == 0){// build the conditionpcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond (newpcl::ConditionAnd<pcl::PointXYZ> ());range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (newpcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::GT, 0.0)));range_cond->addComparison (pcl::FieldComparison<pcl::PointXYZ>::ConstPtr (newpcl::FieldComparison<pcl::PointXYZ> ("z", pcl::ComparisonOps::LT, 0.8)));// build the filterpcl::ConditionalRemoval<pcl::PointXYZ> condrem;condrem.setCondition (range_cond);condrem.setInputCloud (cloud);condrem.setKeepOrganized(true);// apply filtercondrem.filter (*cloud_filtered);}else{std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;exit(0);}std::cerr << "Cloud before filtering: " << std::endl;for (std::size_t i = 0; i < cloud->points.size (); ++i)std::cerr << "    " << cloud->points[i].x << " "<< cloud->points[i].y << " "<< cloud->points[i].z << std::endl;// display pointcloud after filteringstd::cerr << "Cloud after filtering: " << std::endl;for (std::size_t i = 0; i < cloud_filtered->points.size (); ++i)std::cerr << "    " << cloud_filtered->points[i].x << " "<< cloud_filtered->points[i].y << " "<< cloud_filtered->points[i].z << std::endl;return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(remove_outliers)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (remove_outliers remove_outliers.cpp)
target_link_libraries (remove_outliers ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.7<分割>提取在平面上的点

学习提取在某一平面上的点

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/planar_segmentation.html#planar-segmentation

创建目录,终端运行

mkdir 7
cd 7
gedit planar_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./planar_segmentation

结果显示

代码展示

##########################################
##########################################
##########################################
planar_segmentation.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>intmain (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datacloud->width  = 15;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);// Generate the datafor (std::size_t i = 0; i < cloud->points.size (); ++i){cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].z = 1.0;}// Set a few outlierscloud->points[0].z = 2.0;cloud->points[3].z = -2.0;cloud->points[6].z = 4.0;std::cerr << "Point cloud data: " << cloud->points.size () << " points" << std::endl;for (std::size_t i = 0; i < cloud->points.size (); ++i)std::cerr << "    " << cloud->points[i].x << " "<< cloud->points[i].y << " "<< cloud->points[i].z << std::endl;pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers (new pcl::PointIndices);// Create the segmentation objectpcl::SACSegmentation<pcl::PointXYZ> seg;// Optionalseg.setOptimizeCoefficients (true);// Mandatoryseg.setModelType (pcl::SACMODEL_PLANE);seg.setMethodType (pcl::SAC_RANSAC);seg.setDistanceThreshold (0.01);seg.setInputCloud (cloud);seg.segment (*inliers, *coefficients);if (inliers->indices.size () == 0){PCL_ERROR ("Could not estimate a planar model for the given dataset.");return (-1);}std::cerr << "Model coefficients: " << coefficients->values[0] << " " << coefficients->values[1] << " "<< coefficients->values[2] << " " << coefficients->values[3] << std::endl;std::cerr << "Model inliers: " << inliers->indices.size () << std::endl;for (std::size_t i = 0; i < inliers->indices.size (); ++i)std::cerr << inliers->indices[i] << "    " << cloud->points[inliers->indices[i]].x << " "<< cloud->points[inliers->indices[i]].y << " "<< cloud->points[inliers->indices[i]].z << std::endl;return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(planar_segmentation)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (planar_segmentation planar_segmentation.cpp)
target_link_libraries (planar_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.8<分割>圆柱型分割

提取圆柱数据

  • 距离1.5米以外的数据点被过滤
  • 估计每个点的表面法线
  • 平面模型(描述我们的演示数据集中的表)被分割并保存到磁盘
  • 圆柱模型(在我们的演示数据集中描述了杯子)被分段并保存到磁盘

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/cylinder_segmentation.html#cylinder-segmentation

创建目录,终端运行

table_scene_mug_stereo_textured.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_mug_stereo_textured.pcd

mkdir 8
cd 8
gedit cylinder_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_mug_stereo_textured.pcd放到./8/cylinder_segmentation/build目录下
#有代码包的:cp ../../table_scene_mug_stereo_textured.pcd ./
./cylinder_segmentation

结果显示

代码展示

##########################################
##########################################
##########################################
cylinder_segmentation.cpp
##########################################
##########################################
##########################################
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/passthrough.h>
#include <pcl/features/normal_3d.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>typedef pcl::PointXYZ PointT;int
main (int argc, char** argv)
{// All the objects neededpcl::PCDReader reader;pcl::PassThrough<PointT> pass;pcl::NormalEstimation<PointT, pcl::Normal> ne;pcl::SACSegmentationFromNormals<PointT, pcl::Normal> seg; pcl::PCDWriter writer;pcl::ExtractIndices<PointT> extract;pcl::ExtractIndices<pcl::Normal> extract_normals;pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT> ());// Datasetspcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);pcl::PointCloud<PointT>::Ptr cloud_filtered (new pcl::PointCloud<PointT>);pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);pcl::PointCloud<PointT>::Ptr cloud_filtered2 (new pcl::PointCloud<PointT>);pcl::PointCloud<pcl::Normal>::Ptr cloud_normals2 (new pcl::PointCloud<pcl::Normal>);pcl::ModelCoefficients::Ptr coefficients_plane (new pcl::ModelCoefficients), coefficients_cylinder (new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers_plane (new pcl::PointIndices), inliers_cylinder (new pcl::PointIndices);// Read in the cloud datareader.read ("table_scene_mug_stereo_textured.pcd", *cloud);std::cerr << "PointCloud has: " << cloud->points.size () << " data points." << std::endl;// Build a passthrough filter to remove spurious NaNspass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0, 1.5);pass.filter (*cloud_filtered);std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl;// Estimate point normalsne.setSearchMethod (tree);ne.setInputCloud (cloud_filtered);ne.setKSearch (50);ne.compute (*cloud_normals);// Create the segmentation object for the planar model and set all the parametersseg.setOptimizeCoefficients (true);seg.setModelType (pcl::SACMODEL_NORMAL_PLANE);seg.setNormalDistanceWeight (0.1);seg.setMethodType (pcl::SAC_RANSAC);seg.setMaxIterations (100);seg.setDistanceThreshold (0.03);seg.setInputCloud (cloud_filtered);seg.setInputNormals (cloud_normals);// Obtain the plane inliers and coefficientsseg.segment (*inliers_plane, *coefficients_plane);std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;// Extract the planar inliers from the input cloudextract.setInputCloud (cloud_filtered);extract.setIndices (inliers_plane);extract.setNegative (false);// Write the planar inliers to diskpcl::PointCloud<PointT>::Ptr cloud_plane (new pcl::PointCloud<PointT> ());extract.filter (*cloud_plane);std::cerr << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;writer.write ("table_scene_mug_stereo_textured_plane.pcd", *cloud_plane, false);// Remove the planar inliers, extract the restextract.setNegative (true);extract.filter (*cloud_filtered2);extract_normals.setNegative (true);extract_normals.setInputCloud (cloud_normals);extract_normals.setIndices (inliers_plane);extract_normals.filter (*cloud_normals2);// Create the segmentation object for cylinder segmentation and set all the parametersseg.setOptimizeCoefficients (true);seg.setModelType (pcl::SACMODEL_CYLINDER);seg.setMethodType (pcl::SAC_RANSAC);seg.setNormalDistanceWeight (0.1);seg.setMaxIterations (10000);seg.setDistanceThreshold (0.05);seg.setRadiusLimits (0, 0.1);seg.setInputCloud (cloud_filtered2);seg.setInputNormals (cloud_normals2);// Obtain the cylinder inliers and coefficientsseg.segment (*inliers_cylinder, *coefficients_cylinder);std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;// Write the cylinder inliers to diskextract.setInputCloud (cloud_filtered2);extract.setIndices (inliers_cylinder);extract.setNegative (false);pcl::PointCloud<PointT>::Ptr cloud_cylinder (new pcl::PointCloud<PointT> ());extract.filter (*cloud_cylinder);if (cloud_cylinder->points.empty ()) std::cerr << "Can't find the cylindrical component." << std::endl;else{std::cerr << "PointCloud representing the cylindrical component: " << cloud_cylinder->points.size () << " data points." << std::endl;writer.write ("table_scene_mug_stereo_textured_cylinder.pcd", *cloud_cylinder, false);}return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(cylinder_segmentation)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (cylinder_segmentation cylinder_segmentation.cpp)
target_link_libraries (cylinder_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.9 <分割> 欧几里得分割

学习:欧几里得分割

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/cluster_extraction.html#cluster-extraction

创建目录,终端运行

table_scene_lms400.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_lms400.pcd

mkdir 9
cd 9
mkdir cluster_extraction
cd cluster_extraction
gedit cluster_extraction.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_lms400.pcd放到./9/cluster_extraction/build目录下
#有代码包的:cp ../../table_scene_lms400.pcd ./
./cluster_extraction

结果显示

pcl_viewer table_scene_lms400.pcd
ctrl+ shift + t
pcl_viewer  cloud_cluster_*.pcd

代码展示

##########################################
##########################################
##########################################
cluster_extraction.cpp
##########################################
##########################################
##########################################
#include <pcl/ModelCoefficients.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>int
main (int argc, char** argv)
{// Read in the cloud datapcl::PCDReader reader;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);reader.read ("table_scene_lms400.pcd", *cloud);std::cout << "PointCloud before filtering has: " << cloud->points.size () << " data points." << std::endl; //*// Create the filtering object: downsample the dataset using a leaf size of 1cmpcl::VoxelGrid<pcl::PointXYZ> vg;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);vg.setInputCloud (cloud);vg.setLeafSize (0.01f, 0.01f, 0.01f);vg.filter (*cloud_filtered);std::cout << "PointCloud after filtering has: " << cloud_filtered->points.size ()  << " data points." << std::endl; //*// Create the segmentation object for the planar model and set all the parameterspcl::SACSegmentation<pcl::PointXYZ> seg;pcl::PointIndices::Ptr inliers (new pcl::PointIndices);pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane (new pcl::PointCloud<pcl::PointXYZ> ());pcl::PCDWriter writer;seg.setOptimizeCoefficients (true);seg.setModelType (pcl::SACMODEL_PLANE);seg.setMethodType (pcl::SAC_RANSAC);seg.setMaxIterations (100);seg.setDistanceThreshold (0.02);int i=0, nr_points = (int) cloud_filtered->points.size ();while (cloud_filtered->points.size () > 0.3 * nr_points){// Segment the largest planar component from the remaining cloudseg.setInputCloud (cloud_filtered);seg.segment (*inliers, *coefficients);if (inliers->indices.size () == 0){std::cout << "Could not estimate a planar model for the given dataset." << std::endl;break;}// Extract the planar inliers from the input cloudpcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud (cloud_filtered);extract.setIndices (inliers);extract.setNegative (false);// Get the points associated with the planar surfaceextract.filter (*cloud_plane);std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;// Remove the planar inliers, extract the restextract.setNegative (true);extract.filter (*cloud_f);*cloud_filtered = *cloud_f;}// Creating the KdTree object for the search method of the extractionpcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);tree->setInputCloud (cloud_filtered);std::vector<pcl::PointIndices> cluster_indices;pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;ec.setClusterTolerance (0.02); // 2cmec.setMinClusterSize (100);ec.setMaxClusterSize (25000);ec.setSearchMethod (tree);ec.setInputCloud (cloud_filtered);ec.extract (cluster_indices);int j = 0;for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it){pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit)cloud_cluster->points.push_back (cloud_filtered->points[*pit]); //*cloud_cluster->width = cloud_cluster->points.size ();cloud_cluster->height = 1;cloud_cluster->is_dense = true;std::cout << "PointCloud representing the Cluster: " << cloud_cluster->points.size () << " data points." << std::endl;std::stringstream ss;ss << "cloud_cluster_" << j << ".pcd";writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false); //*j++;}return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(cluster_extraction)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (cluster_extraction cluster_extraction.cpp)
target_link_libraries (cluster_extraction ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.10 <分割> 区域增长细分

学习:区域增长细分

学习如何使用在pcl::RegionGrowing课程中实现的区域增长算法。所述算法的目的是合并就平滑度约束而言足够接近的点。因此,该算法的输出是一组聚类,其中每个聚类都是被认为是同一光滑表面一部分的一组点。该算法的工作基于点法线之间的角度比较。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/region_growing_segmentation.html#region-growing-segmentation

创建目录,终端运行

region_growing_tutorial.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/region_growing_tutorial.pcd

mkdir 10
cd 10
mkdir region_growing_segmentation
cd region_growing_segmentation
gedit region_growing_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载region_growing_tutorial.pcd放到./10/region_growing_segmentation/build目录下
#有代码包的:cp ../../region_growing_tutorial.pcd ./
./region_growing_segmentation

结果显示

代码展示

##########################################
##########################################
##########################################
region_growing_segmentation.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <vector>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing.h>int
main (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("region_growing_tutorial.pcd", *cloud) == -1){std::cout << "Cloud reading failed." << std::endl;return (-1);}pcl::search::Search<pcl::PointXYZ>::Ptr tree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> > (new pcl::search::KdTree<pcl::PointXYZ>);pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;normal_estimator.setSearchMethod (tree);normal_estimator.setInputCloud (cloud);normal_estimator.setKSearch (50);normal_estimator.compute (*normals);pcl::IndicesPtr indices (new std::vector <int>);pcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0.0, 1.0);pass.filter (*indices);pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;reg.setMinClusterSize (50);reg.setMaxClusterSize (1000000);reg.setSearchMethod (tree);reg.setNumberOfNeighbours (30);reg.setInputCloud (cloud);//reg.setIndices (indices);reg.setInputNormals (normals);reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);reg.setCurvatureThreshold (1.0);std::vector <pcl::PointIndices> clusters;reg.extract (clusters);std::cout << "Number of clusters is equal to " << clusters.size () << std::endl;std::cout << "First cluster has " << clusters[0].indices.size () << " points." << endl;std::cout << "These are the indices of the points of the initial" <<std::endl << "cloud that belong to the first cluster:" << std::endl;int counter = 0;while (counter < clusters[0].indices.size ()){std::cout << clusters[0].indices[counter] << ", ";counter++;if (counter % 10 == 0)std::cout << std::endl;}std::cout << std::endl;pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();pcl::visualization::CloudViewer viewer ("Cluster viewer");viewer.showCloud(colored_cloud);while (!viewer.wasStopped ()){}return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(region_growing_segmentation)
find_package(PCL 1.5 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (region_growing_segmentation region_growing_segmentation.cpp)
target_link_libraries (region_growing_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.11 <分割> 基于颜色的区域增长分割

学习:学习如何使用pcl::RegionGrowingRGB该类中实现的基于颜色的区域增长算法。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/region_growing_rgb_segmentation.html#region-growing-rgb-segmentation

创建目录,终端运行

region_growing_rgb_tutorial.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/region_growing_rgb_tutorial.pcd

mkdir 11
cd 11
mkdir region_growing_rgb_segmentation
cd region_growing_rgb_segmentation
gedit region_growing_rgb_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载region_growing_rgb_tutorial.pcd放到./11/region_growing_rgb_segmentation/build目录下
#有代码包的:cp ../../region_growing_rgb_tutorial.pcd ./
./region_growing_rgb_segmentation

结果显示

ctrl + shift + t
pcl_viewer  region_growing_rgb_tutorial.pcd

代码展示

##########################################
##########################################
##########################################
region_growing_rgb_segmentation.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <thread>
#include <vector>#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/search.h>
#include <pcl/search/kdtree.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/region_growing_rgb.h>using namespace std::chrono_literals;int
main (int argc, char** argv)
{pcl::search::Search <pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>);pcl::PointCloud <pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZRGB>);if ( pcl::io::loadPCDFile <pcl::PointXYZRGB> ("region_growing_rgb_tutorial.pcd", *cloud) == -1 ){std::cout << "Cloud reading failed." << std::endl;return (-1);}pcl::IndicesPtr indices (new std::vector <int>);pcl::PassThrough<pcl::PointXYZRGB> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0.0, 1.0);pass.filter (*indices);pcl::RegionGrowingRGB<pcl::PointXYZRGB> reg;reg.setInputCloud (cloud);reg.setIndices (indices);reg.setSearchMethod (tree);reg.setDistanceThreshold (10);reg.setPointColorThreshold (6);reg.setRegionColorThreshold (5);reg.setMinClusterSize (600);std::vector <pcl::PointIndices> clusters;reg.extract (clusters);pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = reg.getColoredCloud ();pcl::visualization::CloudViewer viewer ("Cluster viewer");viewer.showCloud (colored_cloud);while (!viewer.wasStopped ()){std::this_thread::sleep_for(100us);}return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
SET( CMAKE_CXX_FLAGS "-std=c++11 -O3")
project(region_growing_rgb_segmentation)
find_package(PCL 1.5 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include(CheckCXXCompilerFlag)
add_compile_options(-std=gnu++11)
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (region_growing_rgb_segmentation region_growing_rgb_segmentation.cpp)
target_link_libraries (region_growing_rgb_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.12 <分割> 基于最小剪切的细分

学习:学习如何使用在pcl::MinCutSegmentation类中实现的基于最小剪切的分割算法。该算法对给定的输入云进行了二进制分割。具有对象中心和半径的算法将云分为两组:前景点和背景点(属于对象的点和不属于对象的点)。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/min_cut_segmentation.html#min-cut-segmentation

创建目录,终端运行

min_cut_segmentation_tutorial.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/min_cut_segmentation_tutorial.pcd

mkdir 12
cd 12
mkdir min_cut_segmentation
cd min_cut_segmentation
gedit min_cut_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载min_cut_segmentation_tutorial.pcd放到./12/min_cut_segmentation/build目录下
#有代码包的:cp ../../min_cut_segmentation_tutorial.pcd ./
./min_cut_segmentation

结果显示

ctrl + shift + t
pcl_viewer  min_cut_segmentation_tutorial.pcd

代码展示

##########################################
##########################################
##########################################
min_cut_segmentation.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/filters/passthrough.h>
#include <pcl/segmentation/min_cut_segmentation.h>int main (int argc, char** argv)
{pcl::PointCloud <pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud <pcl::PointXYZ>);if ( pcl::io::loadPCDFile <pcl::PointXYZ> ("min_cut_segmentation_tutorial.pcd", *cloud) == -1 ){std::cout << "Cloud reading failed." << std::endl;return (-1);}pcl::IndicesPtr indices (new std::vector <int>);pcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0.0, 1.0);pass.filter (*indices);pcl::MinCutSegmentation<pcl::PointXYZ> seg;seg.setInputCloud (cloud);seg.setIndices (indices);pcl::PointCloud<pcl::PointXYZ>::Ptr foreground_points(new pcl::PointCloud<pcl::PointXYZ> ());pcl::PointXYZ point;point.x = 68.97;point.y = -18.55;point.z = 0.57;foreground_points->points.push_back(point);seg.setForegroundPoints (foreground_points);seg.setSigma (0.25);seg.setRadius (3.0433856);seg.setNumberOfNeighbours (14);seg.setSourceWeight (0.8);std::vector <pcl::PointIndices> clusters;seg.extract (clusters);std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl;pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = seg.getColoredCloud ();pcl::visualization::CloudViewer viewer ("Cluster viewer");viewer.showCloud(colored_cloud);while (!viewer.wasStopped ()){}return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(min_cut_segmentation)
find_package(PCL 1.5 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (min_cut_segmentation min_cut_segmentation.cpp)
target_link_libraries (min_cut_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.13<分割> 条件欧几里得聚类

学习:一种分割算法,该算法基于欧几里得距离和需要保持的用户可自定义条件对点进行聚类。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/conditional_euclidean_clustering.html#conditional-euclidean-clustering

创建目录,终端运行

Statues_4.pcd下载链接:https://sourceforge.net/projects/pointclouds/files/PCDdatasets/Trimble/Outdoor1/Statues_4.pcd.zip

mkdir 13
cd 13
mkdir conditional_euclidean_clustering
cd conditional_euclidean_clustering
gedit conditional_euclidean_clustering.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载Statues_4.pcd放到./13/conditional_euclidean_clustering/build目录下
#有代码包的:cp ../../Statues_4.pcd ./
./conditional_euclidean_clustering

结果显示

pcl_viewer  output.pcd
ctrl + shift + t
pcl_viewer  Statues_4.pcd
按“ 5”将切换到强度通道可视化。太小的簇将被涂成红色,太大的簇将被涂成蓝色,并且实际的感兴趣的簇/对象将在黄色和青色之间随机着色。

代码展示

##########################################
##########################################
##########################################
conditional_euclidean_clustering.cpp
##########################################
##########################################
##########################################
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/time.h>#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/conditional_euclidean_clustering.h>typedef pcl::PointXYZI PointTypeIO;
typedef pcl::PointXYZINormal PointTypeFull;bool
enforceIntensitySimilarity (const PointTypeFull& point_a, const PointTypeFull& point_b, float squared_distance)
{if (fabs (point_a.intensity - point_b.intensity) < 5.0f)return (true);elsereturn (false);
}bool
enforceCurvatureOrIntensitySimilarity (const PointTypeFull& point_a, const PointTypeFull& point_b, float squared_distance)
{Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap (), point_b_normal = point_b.getNormalVector3fMap ();if (fabs (point_a.intensity - point_b.intensity) < 5.0f)return (true);if (fabs (point_a_normal.dot (point_b_normal)) < 0.05)return (true);return (false);
}bool
customRegionGrowing (const PointTypeFull& point_a, const PointTypeFull& point_b, float squared_distance)
{Eigen::Map<const Eigen::Vector3f> point_a_normal = point_a.getNormalVector3fMap (), point_b_normal = point_b.getNormalVector3fMap ();if (squared_distance < 10000){if (fabs (point_a.intensity - point_b.intensity) < 8.0f)return (true);if (fabs (point_a_normal.dot (point_b_normal)) < 0.06)return (true);}else{if (fabs (point_a.intensity - point_b.intensity) < 3.0f)return (true);}return (false);
}int
main (int argc, char** argv)
{// Data containers usedpcl::PointCloud<PointTypeIO>::Ptr cloud_in (new pcl::PointCloud<PointTypeIO>), cloud_out (new pcl::PointCloud<PointTypeIO>);pcl::PointCloud<PointTypeFull>::Ptr cloud_with_normals (new pcl::PointCloud<PointTypeFull>);pcl::IndicesClustersPtr clusters (new pcl::IndicesClusters), small_clusters (new pcl::IndicesClusters), large_clusters (new pcl::IndicesClusters);pcl::search::KdTree<PointTypeIO>::Ptr search_tree (new pcl::search::KdTree<PointTypeIO>);pcl::console::TicToc tt;// Load the input point cloudstd::cerr << "Loading...\n", tt.tic ();pcl::io::loadPCDFile ("Statues_4.pcd", *cloud_in);std::cerr << ">> Done: " << tt.toc () << " ms, " << cloud_in->points.size () << " points\n";// Downsample the cloud using a Voxel Grid classstd::cerr << "Downsampling...\n", tt.tic ();pcl::VoxelGrid<PointTypeIO> vg;vg.setInputCloud (cloud_in);vg.setLeafSize (80.0, 80.0, 80.0);vg.setDownsampleAllData (true);vg.filter (*cloud_out);std::cerr << ">> Done: " << tt.toc () << " ms, " << cloud_out->points.size () << " points\n";// Set up a Normal Estimation class and merge data in cloud_with_normalsstd::cerr << "Computing normals...\n", tt.tic ();pcl::copyPointCloud (*cloud_out, *cloud_with_normals);pcl::NormalEstimation<PointTypeIO, PointTypeFull> ne;ne.setInputCloud (cloud_out);ne.setSearchMethod (search_tree);ne.setRadiusSearch (300.0);ne.compute (*cloud_with_normals);std::cerr << ">> Done: " << tt.toc () << " ms\n";// Set up a Conditional Euclidean Clustering classstd::cerr << "Segmenting to clusters...\n", tt.tic ();pcl::ConditionalEuclideanClustering<PointTypeFull> cec (true);cec.setInputCloud (cloud_with_normals);cec.setConditionFunction (&customRegionGrowing);cec.setClusterTolerance (500.0);cec.setMinClusterSize (cloud_with_normals->points.size () / 1000);cec.setMaxClusterSize (cloud_with_normals->points.size () / 5);cec.segment (*clusters);cec.getRemovedClusters (small_clusters, large_clusters);std::cerr << ">> Done: " << tt.toc () << " ms\n";// Using the intensity channel for lazy visualization of the outputfor (int i = 0; i < small_clusters->size (); ++i)for (int j = 0; j < (*small_clusters)[i].indices.size (); ++j)cloud_out->points[(*small_clusters)[i].indices[j]].intensity = -2.0;for (int i = 0; i < large_clusters->size (); ++i)for (int j = 0; j < (*large_clusters)[i].indices.size (); ++j)cloud_out->points[(*large_clusters)[i].indices[j]].intensity = +10.0;for (int i = 0; i < clusters->size (); ++i){int label = rand () % 8;for (int j = 0; j < (*clusters)[i].indices.size (); ++j)cloud_out->points[(*clusters)[i].indices[j]].intensity = label;}// Save the output point cloudstd::cerr << "Saving...\n", tt.tic ();pcl::io::savePCDFile ("output.pcd", *cloud_out);std::cerr << ">> Done: " << tt.toc () << " ms\n";return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(conditional_euclidean_clustering)
find_package(PCL 1.7 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (conditional_euclidean_clustering conditional_euclidean_clustering.cpp)
target_link_libraries (conditional_euclidean_clustering ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.14 <分割> 基于法线的分割的差异(没有点云数据,不能复现)

学习:学习如何使用在pcl::DifferenceOfNormalsEstimation类中实现的“法线差异”功能对无组织点云进行基于比例的分割。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/don_segmentation.html#don-segmentation

创建目录,终端运行

*****.pcd下载链接:

mkdir 14
cd 14
mkdir don_segmentation
cd don_segmentation
gedit don_segmentation.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载*****.pcd放到./14/don_segmentation/build目录下
#有代码包的:cp ../../*****.pcd ./
./don_segmentation

结果显示

代码展示

##########################################
##########################################
##########################################
don_segmentation.cpp
##########################################
##########################################
##########################################
/*** @file don_segmentation.cpp* Difference of Normals Example for PCL Segmentation Tutorials.** @author Yani Ioannou* @date 2012-09-24*/
#include <string>#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/search/organized.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/filters/conditional_removal.h>
#include <pcl/segmentation/extract_clusters.h>#include <pcl/features/don.h>using namespace pcl;
using namespace std;int
main (int argc, char *argv[])
{///The smallest scale to use in the DoN filter.double scale1;///The largest scale to use in the DoN filter.double scale2;///The minimum DoN magnitude to threshold bydouble threshold;///segment scene into clusters with given distance tolerance using euclidean clusteringdouble segradius;if (argc < 6){cerr << "usage: " << argv[0] << " inputfile smallscale largescale threshold segradius" << endl;exit (EXIT_FAILURE);}/// the file to read from.string infile = argv[1];/// small scaleistringstream (argv[2]) >> scale1;/// large scaleistringstream (argv[3]) >> scale2;istringstream (argv[4]) >> threshold;   // threshold for DoN magnitudeistringstream (argv[5]) >> segradius;   // threshold for radius segmentation// Load cloud in blob formatpcl::PCLPointCloud2 blob;pcl::io::loadPCDFile (infile.c_str (), blob);pcl::PointCloud<PointXYZRGB>::Ptr cloud (new pcl::PointCloud<PointXYZRGB>);pcl::fromPCLPointCloud2 (blob, *cloud);// Create a search tree, use KDTreee for non-organized data.pcl::search::Search<PointXYZRGB>::Ptr tree;if (cloud->isOrganized ()){tree.reset (new pcl::search::OrganizedNeighbor<PointXYZRGB> ());}else{tree.reset (new pcl::search::KdTree<PointXYZRGB> (false));}// Set the input pointcloud for the search treetree->setInputCloud (cloud);if (scale1 >= scale2){cerr << "Error: Large scale must be > small scale!" << endl;exit (EXIT_FAILURE);}// Compute normals using both small and large scales at each pointpcl::NormalEstimationOMP<PointXYZRGB, PointNormal> ne;ne.setInputCloud (cloud);ne.setSearchMethod (tree);/*** NOTE: setting viewpoint is very important, so that we can ensure* normals are all pointed in the same direction!*/ne.setViewPoint (std::numeric_limits<float>::max (), std::numeric_limits<float>::max (), std::numeric_limits<float>::max ());// calculate normals with the small scalecout << "Calculating normals for scale..." << scale1 << endl;pcl::PointCloud<PointNormal>::Ptr normals_small_scale (new pcl::PointCloud<PointNormal>);ne.setRadiusSearch (scale1);ne.compute (*normals_small_scale);// calculate normals with the large scalecout << "Calculating normals for scale..." << scale2 << endl;pcl::PointCloud<PointNormal>::Ptr normals_large_scale (new pcl::PointCloud<PointNormal>);ne.setRadiusSearch (scale2);ne.compute (*normals_large_scale);// Create output cloud for DoN resultsPointCloud<PointNormal>::Ptr doncloud (new pcl::PointCloud<PointNormal>);copyPointCloud<PointXYZRGB, PointNormal>(*cloud, *doncloud);cout << "Calculating DoN... " << endl;// Create DoN operatorpcl::DifferenceOfNormalsEstimation<PointXYZRGB, PointNormal, PointNormal> don;don.setInputCloud (cloud);don.setNormalScaleLarge (normals_large_scale);don.setNormalScaleSmall (normals_small_scale);if (!don.initCompute ()){std::cerr << "Error: Could not intialize DoN feature operator" << std::endl;exit (EXIT_FAILURE);}// Compute DoNdon.computeFeature (*doncloud);// Save DoN featurespcl::PCDWriter writer;writer.write<pcl::PointNormal> ("don.pcd", *doncloud, false); // Filter by magnitudecout << "Filtering out DoN mag <= " << threshold << "..." << endl;// Build the condition for filteringpcl::ConditionOr<PointNormal>::Ptr range_cond (new pcl::ConditionOr<PointNormal> ());range_cond->addComparison (pcl::FieldComparison<PointNormal>::ConstPtr (new pcl::FieldComparison<PointNormal> ("curvature", pcl::ComparisonOps::GT, threshold)));// Build the filterpcl::ConditionalRemoval<PointNormal> condrem (range_cond);condrem.setInputCloud (doncloud);pcl::PointCloud<PointNormal>::Ptr doncloud_filtered (new pcl::PointCloud<PointNormal>);// Apply filtercondrem.filter (*doncloud_filtered);doncloud = doncloud_filtered;// Save filtered outputstd::cout << "Filtered Pointcloud: " << doncloud->points.size () << " data points." << std::endl;writer.write<pcl::PointNormal> ("don_filtered.pcd", *doncloud, false); // Filter by magnitudecout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << endl;pcl::search::KdTree<PointNormal>::Ptr segtree (new pcl::search::KdTree<PointNormal>);segtree->setInputCloud (doncloud);std::vector<pcl::PointIndices> cluster_indices;pcl::EuclideanClusterExtraction<PointNormal> ec;ec.setClusterTolerance (segradius);ec.setMinClusterSize (50);ec.setMaxClusterSize (100000);ec.setSearchMethod (segtree);ec.setInputCloud (doncloud);ec.extract (cluster_indices);int j = 0;for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++){pcl::PointCloud<PointNormal>::Ptr cloud_cluster_don (new pcl::PointCloud<PointNormal>);for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit){cloud_cluster_don->points.push_back (doncloud->points[*pit]);}cloud_cluster_don->width = int (cloud_cluster_don->points.size ());cloud_cluster_don->height = 1;cloud_cluster_don->is_dense = true;//Save clustercout << "PointCloud representing the Cluster: " << cloud_cluster_don->points.size () << " data points." << std::endl;stringstream ss;ss << "don_cluster_" << j << ".pcd";writer.write<pcl::PointNormal> (ss.str (), *cloud_cluster_don, false);}
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(don_segmentation)
find_package(PCL 1.7 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (don_segmentation don_segmentation.cpp)
target_link_libraries (don_segmentation ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.15 <分割> 将点云聚类为Supervoxels(报错误了不能复现)

学习:点云聚类为Supervoxels

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/supervoxel_clustering.html#supervoxel-clustering

创建目录,终端运行

mkdir 15
cd 15
gedit supervoxel_clustering.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make ./supervoxel_clustering

结果显示

代码展示

##########################################
##########################################
##########################################
supervoxel_clustering.cpp
##########################################
##########################################
##########################################
#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/supervoxel_clustering.h>//VTK include needed for drawing graph lines
#include <vtkPolyLine.h>// Types
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
typedef pcl::PointNormal PointNT;
typedef pcl::PointCloud<PointNT> PointNCloudT;
typedef pcl::PointXYZL PointLT;
typedef pcl::PointCloud<PointLT> PointLCloudT;void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,PointCloudT &adjacent_supervoxel_centers,std::string supervoxel_name,boost::shared_ptr<pcl::visualization::PCLVisualizer> & viewer);int
main (int argc, char ** argv)
{if (argc < 2){pcl::console::print_error ("Syntax is: %s <pcd-file> \n ""--NT Dsables the single cloud transform \n""-v <voxel resolution>\n-s <seed resolution>\n""-c <color weight> \n-z <spatial weight> \n""-n <normal_weight>\n", argv[0]);return (1);}PointCloudT::Ptr cloud = boost::shared_ptr <PointCloudT> (new PointCloudT ());pcl::console::print_highlight ("Loading point cloud...\n");if (pcl::io::loadPCDFile<PointT> (argv[1], *cloud)){pcl::console::print_error ("Error loading cloud file!\n");return (1);}bool disable_transform = pcl::console::find_switch (argc, argv, "--NT");float voxel_resolution = 0.008f;bool voxel_res_specified = pcl::console::find_switch (argc, argv, "-v");if (voxel_res_specified)pcl::console::parse (argc, argv, "-v", voxel_resolution);float seed_resolution = 0.1f;bool seed_res_specified = pcl::console::find_switch (argc, argv, "-s");if (seed_res_specified)pcl::console::parse (argc, argv, "-s", seed_resolution);float color_importance = 0.2f;if (pcl::console::find_switch (argc, argv, "-c"))pcl::console::parse (argc, argv, "-c", color_importance);float spatial_importance = 0.4f;if (pcl::console::find_switch (argc, argv, "-z"))pcl::console::parse (argc, argv, "-z", spatial_importance);float normal_importance = 1.0f;if (pcl::console::find_switch (argc, argv, "-n"))pcl::console::parse (argc, argv, "-n", normal_importance);//  //// This is how to use supervoxels//  //pcl::SupervoxelClustering<PointT> super (voxel_resolution, seed_resolution);if (disable_transform)super.setUseSingleCameraTransform (false);super.setInputCloud (cloud);super.setColorImportance (color_importance);super.setSpatialImportance (spatial_importance);super.setNormalImportance (normal_importance);std::map <uint32_t, pcl::Supervoxel<PointT>::Ptr > supervoxel_clusters;pcl::console::print_highlight ("Extracting supervoxels!\n");super.extract (supervoxel_clusters);pcl::console::print_info ("Found %d supervoxels\n", supervoxel_clusters.size ());boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));viewer->setBackgroundColor (0, 0, 0);PointCloudT::Ptr voxel_centroid_cloud = super.getVoxelCentroidCloud ();viewer->addPointCloud (voxel_centroid_cloud, "voxel centroids");viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,2.0, "voxel centroids");viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY,0.95, "voxel centroids");PointLCloudT::Ptr labeled_voxel_cloud = super.getLabeledVoxelCloud ();viewer->addPointCloud (labeled_voxel_cloud, "labeled voxels");viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY,0.8, "labeled voxels");PointNCloudT::Ptr sv_normal_cloud = super.makeSupervoxelNormalCloud (supervoxel_clusters);//We have this disabled so graph is easy to see, uncomment to see supervoxel normals//viewer->addPointCloudNormals<PointNormal> (sv_normal_cloud,1,0.05f, "supervoxel_normals");pcl::console::print_highlight ("Getting supervoxel adjacency\n");std::multimap<uint32_t, uint32_t> supervoxel_adjacency;super.getSupervoxelAdjacency (supervoxel_adjacency);//To make a graph of the supervoxel adjacency, we need to iterate through the supervoxel adjacency multimapstd::multimap<uint32_t,uint32_t>::iterator label_itr = supervoxel_adjacency.begin ();for ( ; label_itr != supervoxel_adjacency.end (); ){//First get the labeluint32_t supervoxel_label = label_itr->first;//Now get the supervoxel corresponding to the labelpcl::Supervoxel<PointT>::Ptr supervoxel = supervoxel_clusters.at (supervoxel_label);//Now we need to iterate through the adjacent supervoxels and make a point cloud of themPointCloudT adjacent_supervoxel_centers;std::multimap<uint32_t,uint32_t>::iterator adjacent_itr = supervoxel_adjacency.equal_range (supervoxel_label).first;for ( ; adjacent_itr!=supervoxel_adjacency.equal_range (supervoxel_label).second; ++adjacent_itr){pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel = supervoxel_clusters.at (adjacent_itr->second);adjacent_supervoxel_centers.push_back (neighbor_supervoxel->centroid_);}//Now we make a name for this polygonstd::stringstream ss;ss << "supervoxel_" << supervoxel_label;//This function is shown below, but is beyond the scope of this tutorial - basically it just generates a "star" polygon mesh from the points givenaddSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer);//Move iterator forward to next labellabel_itr = supervoxel_adjacency.upper_bound (supervoxel_label);}while (!viewer->wasStopped ()){viewer->spinOnce (100);}return (0);
}void
addSupervoxelConnectionsToViewer (PointT &supervoxel_center,PointCloudT &adjacent_supervoxel_centers,std::string supervoxel_name,boost::shared_ptr<pcl::visualization::PCLVisualizer> & viewer)
{vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New ();vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New ();//Iterate through all adjacent points, and add a center point to adjacent point pairPointCloudT::iterator adjacent_itr = adjacent_supervoxel_centers.begin ();for ( ; adjacent_itr != adjacent_supervoxel_centers.end (); ++adjacent_itr){points->InsertNextPoint (supervoxel_center.data);points->InsertNextPoint (adjacent_itr->data);}// Create a polydata to store everything invtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();// Add the points to the datasetpolyData->SetPoints (points);polyLine->GetPointIds  ()->SetNumberOfIds(points->GetNumberOfPoints ());for(unsigned int i = 0; i < points->GetNumberOfPoints (); i++)polyLine->GetPointIds ()->SetId (i,i);cells->InsertNextCell (polyLine);// Add the lines to the datasetpolyData->SetLines (cells);viewer->addModelFromPolyData (polyData,supervoxel_name);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(supervoxel_clustering)find_package(PCL 1.7 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (supervoxel_clustering supervoxel_clustering.cpp)
target_link_libraries (supervoxel_clustering ${PCL_LIBRARIES}) 

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.16 <分割> 分割(没找到官方网址)

学习:

官方链接:

创建目录,终端运行

samp11-utm.pcd下载链接:

mkdir 16
cd 16
gedit bare_earth.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载samp11-utm.pcd放到./16/bare_earth/build目录下
#有代码包的:cp ../../samp11-utm.pcd ./
./bare_earth

结果显示

等待时间特别长

pcl_viewer samle_tum.pcd
ctrl+shift+t
pcl_viewer samle_tum_object.pcd
ctrl+shift+t
pcl_viewer samle_tum_ground.pcd

代码展示

##########################################
##########################################
##########################################
bare_earth.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/progressive_morphological_filter.h>int
main (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointIndicesPtr ground (new pcl::PointIndices);// Fill in the cloud datapcl::PCDReader reader;// Replace the path below with the path where you saved your filereader.read<pcl::PointXYZ> ("samp11-utm.pcd", *cloud);std::cerr << "Cloud before filtering: " << std::endl;std::cerr << *cloud << std::endl;// Create the filtering objectpcl::ProgressiveMorphologicalFilter<pcl::PointXYZ> pmf;pmf.setInputCloud (cloud);pmf.setMaxWindowSize (20);pmf.setSlope (1.0f);pmf.setInitialDistance (0.5f);pmf.setMaxDistance (3.0f);pmf.extract (ground->indices);// Create the filtering objectpcl::ExtractIndices<pcl::PointXYZ> extract;extract.setInputCloud (cloud);extract.setIndices (ground);extract.filter (*cloud_filtered);std::cerr << "Ground cloud after filtering: " << std::endl;std::cerr << *cloud_filtered << std::endl;pcl::PCDWriter writer;writer.write<pcl::PointXYZ> ("samp11-utm_ground.pcd", *cloud_filtered, false);// Extract non-ground returnsextract.setNegative (true);extract.filter (*cloud_filtered);std::cerr << "Object cloud after filtering: " << std::endl;std::cerr << *cloud_filtered << std::endl;writer.write<pcl::PointXYZ> ("samp11-utm_object.pcd", *cloud_filtered, false);return (0);
}##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(bare_earth)
find_package(PCL 1.7.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (bare_earth bare_earth.cpp)
target_link_libraries (bare_earth ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.17 <分割>提取平面或球面的参数模型

学习:通过使用具有已知系数的SAC_Models来从PointCloud中提取例如平面或球面的参数模型

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/model_outlier_removal.html#model-outlier-removal

https://pcl.readthedocs.io/projects/tutorials/en/latest/random_sample_consensus.html#random-sample-consensus

创建目录,终端运行

mkdir 17
cd 17
gedit model_outlier_removal.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./model_outlier_removal

结果显示

代码展示

##########################################
##########################################
##########################################
model_outlier_removal.cpp
##########################################
##########################################
##########################################
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/model_outlier_removal.h>int
main ()
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_sphere_filtered (new pcl::PointCloud<pcl::PointXYZ>);// 1. Generate cloud dataint noise_size = 5;int sphere_data_size = 10;cloud->width = noise_size + sphere_data_size;cloud->height = 1;cloud->points.resize (cloud->width * cloud->height);// 1.1 Add noisefor (size_t i = 0; i < noise_size; ++i){cloud->points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);cloud->points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);}// 1.2 Add sphere:double rand_x1 = 1;double rand_x2 = 1;for (size_t i = noise_size; i < noise_size + sphere_data_size; ++i){// See: http://mathworld.wolfram.com/SpherePointPicking.htmlwhile (pow (rand_x1, 2) + pow (rand_x2, 2) >= 1){rand_x1 = (rand () % 100) / (50.0f) - 1;rand_x2 = (rand () % 100) / (50.0f) - 1;}double pre_calc = sqrt (1 - pow (rand_x1, 2) - pow (rand_x2, 2));cloud->points[i].x = 2 * rand_x1 * pre_calc;cloud->points[i].y = 2 * rand_x2 * pre_calc;cloud->points[i].z = 1 - 2 * (pow (rand_x1, 2) + pow (rand_x2, 2));rand_x1 = 1;rand_x2 = 1;}std::cerr << "Cloud before filtering: " << std::endl;for (size_t i = 0; i < cloud->points.size (); ++i)std::cout << "    " << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << std::endl;// 2. filter sphere:// 2.1 generate model:// modelparameter for this sphere:// position.x: 0, position.y: 0, position.z:0, radius: 1pcl::ModelCoefficients sphere_coeff;sphere_coeff.values.resize (4);sphere_coeff.values[0] = 0;sphere_coeff.values[1] = 0;sphere_coeff.values[2] = 0;sphere_coeff.values[3] = 1;pcl::ModelOutlierRemoval<pcl::PointXYZ> sphere_filter;sphere_filter.setModelCoefficients (sphere_coeff);sphere_filter.setThreshold (0.05);sphere_filter.setModelType (pcl::SACMODEL_SPHERE);sphere_filter.setInputCloud (cloud);sphere_filter.filter (*cloud_sphere_filtered);std::cerr << "Sphere after filtering: " << std::endl;for (size_t i = 0; i < cloud_sphere_filtered->points.size (); ++i)std::cout << "    " << cloud_sphere_filtered->points[i].x << " " << cloud_sphere_filtered->points[i].y << " " << cloud_sphere_filtered->points[i].z<< std::endl;return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(model_outlier_removal)
find_package(PCL 1.7 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (model_outlier_removal model_outlier_removal.cpp)
target_link_libraries (model_outlier_removal ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.18 <分割> 分割

学习:使用移动最小二乘(MLS)曲面重构方法来平滑和重采样嘈杂的数据。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/resampling.html#moving-least-squares

bun0.pcd:https://raw.githubusercontent.com/PointCloudLibrary/pcl/master/test/bun0.pcd

创建目录,终端运行

bun0.pcd下载链接:

mkdir 18
cd 18
gedit resampling.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载bun0.pcd放到./18/resampling/build目录下
#有代码包的:cp ../../bun0.pcd ./
./resampling

结果显示

代码展示

##########################################
##########################################
##########################################
resampling.cpp
##########################################
##########################################
##########################################
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/mls.h>int
main (int argc, char** argv)
{// Load input file into a PointCloud<T> with an appropriate typepcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());// Load bun0.pcd -- should be available with the PCL archive in test pcl::io::loadPCDFile ("bun0.pcd", *cloud);// Create a KD-Treepcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);// Output has the PointNormal type in order to store the normals calculated by MLSpcl::PointCloud<pcl::PointNormal> mls_points;// Init object (second point type is for the normals, even if unused)pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointNormal> mls;mls.setComputeNormals (true);// Set parametersmls.setInputCloud (cloud);mls.setPolynomialFit (true);mls.setSearchMethod (tree);mls.setSearchRadius (0.03);// Reconstructmls.process (mls_points);// Save outputpcl::io::savePCDFile ("bun0-mls.pcd", mls_points);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(resampling)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (resampling resampling.cpp)
target_link_libraries (resampling ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.19 <分割> 为平面模型构造凹凸的船体多边形

学习:学习如何为平面所支持的一组点计算简单的2D船体多边形(凹面或凸面)

concave_hull_2d

convex_hull_2d

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/hull_2d.html#hull-2d

创建目录,终端运行

table_scene_mug_stereo_textured.pcd下载链接:https://raw.github.com/PointCloudLibrary/data/master/tutorials/table_scene_mug_stereo_textured.pcd

mkdir 19
cd 19
mkdir concave_hull_2d
gedit concave_hull_2d.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_mug_stereo_textured.pcd放到./19/concave_hull_2d/build目录下
#有代码包的:cp ../../table_scene_mug_stereo_textured.pcd ./
./concave_hull_2dcd ..
mkdir convex_hull_2d
gedit convex_hull_2d.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_mug_stereo_textured.pcd放到./19/convex_hull_2d/build目录下
#有代码包的:cp ../../table_scene_mug_stereo_textured.pcd ./
./convex_hull_2d

结果显示

pcl_viewer bun0.pcd
ctrl+shift+t
pcl_viewer bun0-mls.pcd

代码展示

##########################################
##########################################
##########################################
concave_hull_2d.cpp
##########################################
##########################################
##########################################
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/surface/concave_hull.h>int
main (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);pcl::PCDReader reader;reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);// Build a filter to remove spurious NaNspcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0, 1.1);pass.filter (*cloud_filtered);std::cerr << "PointCloud after filtering has: "<< cloud_filtered->points.size () << " data points." << std::endl;pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers (new pcl::PointIndices);// Create the segmentation objectpcl::SACSegmentation<pcl::PointXYZ> seg;// Optionalseg.setOptimizeCoefficients (true);// Mandatoryseg.setModelType (pcl::SACMODEL_PLANE);seg.setMethodType (pcl::SAC_RANSAC);seg.setDistanceThreshold (0.01);seg.setInputCloud (cloud_filtered);seg.segment (*inliers, *coefficients);std::cerr << "PointCloud after segmentation has: "<< inliers->indices.size () << " inliers." << std::endl;// Project the model inlierspcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType (pcl::SACMODEL_PLANE);proj.setIndices (inliers);proj.setInputCloud (cloud_filtered);proj.setModelCoefficients (coefficients);proj.filter (*cloud_projected);std::cerr << "PointCloud after projection has: "<< cloud_projected->points.size () << " data points." << std::endl;// Create a Concave Hull representation of the projected inlierspcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);pcl::ConcaveHull<pcl::PointXYZ> chull;chull.setInputCloud (cloud_projected);chull.setAlpha (0.1);chull.reconstruct (*cloud_hull);std::cerr << "Concave hull has: " << cloud_hull->points.size ()<< " data points." << std::endl;pcl::PCDWriter writer;writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(concave_hull_2d)find_package(PCL 1.2 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (concave_hull_2d concave_hull_2d.cpp)
target_link_libraries (concave_hull_2d ${PCL_LIBRARIES})
##########################################
##########################################
##########################################
convex_hull_2d.cpp
##########################################
##########################################
##########################################
#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/project_inliers.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/surface/convex_hull.h>intmain (int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>), cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);pcl::PCDReader reader;reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);// Build a filter to remove spurious NaNspcl::PassThrough<pcl::PointXYZ> pass;pass.setInputCloud (cloud);pass.setFilterFieldName ("z");pass.setFilterLimits (0, 1.1);pass.filter (*cloud_filtered);std::cerr << "PointCloud after filtering has: " << cloud_filtered->points.size () << " data points." << std::endl;pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);pcl::PointIndices::Ptr inliers (new pcl::PointIndices);// Create the segmentation objectpcl::SACSegmentation<pcl::PointXYZ> seg;// Optionalseg.setOptimizeCoefficients (true);// Mandatoryseg.setModelType (pcl::SACMODEL_PLANE);seg.setMethodType (pcl::SAC_RANSAC);seg.setDistanceThreshold (0.01);seg.setInputCloud (cloud_filtered);seg.segment (*inliers, *coefficients);// Project the model inlierspcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType (pcl::SACMODEL_PLANE);proj.setInputCloud (cloud_filtered);proj.setIndices (inliers);proj.setModelCoefficients (coefficients);proj.filter (*cloud_projected);// Create a Convex Hull representation of the projected inlierspcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);pcl::ConvexHull<pcl::PointXYZ> chull;chull.setInputCloud (cloud_projected);chull.reconstruct (*cloud_hull);std::cerr << "Convex hull has: " << cloud_hull->points.size () << " data points." << std::endl;pcl::PCDWriter writer;writer.write ("table_scene_mug_stereo_textured_hull.pcd", *cloud_hull, false);return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(convex_hull_2d)find_package(PCL 1.2 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (convex_hull_2d convex_hull_2d.cpp)
target_link_libraries (convex_hull_2d ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.20 <分割> 无序点云的快速三角剖分

学习:该方法通过维护可从其扩展网格的点的列表(“边缘”点)并将其扩展到连接所有可能的点来起作用。它可以处理来自一次或多次扫描并具有多个相连部分的无组织点。如果表面局部光滑并且在具有不同点密度的区域之间存在平滑过渡,则效果最佳。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/greedy_projection.html#greedy-triangulation

创建目录,终端运行

bun0.pcd下载链接:pcl / test / bun0.pcd中找到输入文件

mkdir 20
cd 20
mkdir greedy_projection
gedit greedy_projection.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载bun0.pcd放到./20/greedy_projection/build目录下
#有代码包的:cp ../../bun0.pcd ./
./greedy_projection

结果显示

pcl_viewer bun0.pcd
ctrl+shift+t
pcl_viewer mesh.vtk

代码展示

##########################################
##########################################
##########################################
greedy_projection.cpp
##########################################
##########################################
##########################################
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/io/vtk_io.h>int
main (int argc, char** argv)
{// Load input file into a PointCloud<T> with an appropriate typepcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::PCLPointCloud2 cloud_blob;pcl::io::loadPCDFile ("bun0.pcd", cloud_blob);pcl::fromPCLPointCloud2 (cloud_blob, *cloud);//* the data should be available in cloud// Normal estimation*pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);tree->setInputCloud (cloud);n.setInputCloud (cloud);n.setSearchMethod (tree);n.setKSearch (20);n.compute (*normals);//* normals should not contain the point normals + surface curvatures// Concatenate the XYZ and normal fields*pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals (new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);//* cloud_with_normals = cloud + normals// Create search tree*pcl::search::KdTree<pcl::PointNormal>::Ptr tree2 (new pcl::search::KdTree<pcl::PointNormal>);tree2->setInputCloud (cloud_with_normals);// Initialize objectspcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;pcl::PolygonMesh triangles;// Set the maximum distance between connected points (maximum edge length)gp3.setSearchRadius (0.025);// Set typical values for the parametersgp3.setMu (2.5);gp3.setMaximumNearestNeighbors (100);gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degreesgp3.setMinimumAngle(M_PI/18); // 10 degreesgp3.setMaximumAngle(2*M_PI/3); // 120 degreesgp3.setNormalConsistency(false);// Get resultgp3.setInputCloud (cloud_with_normals);gp3.setSearchMethod (tree2);gp3.reconstruct (triangles);// Additional vertex informationstd::vector<int> parts = gp3.getPartIDs();std::vector<int> states = gp3.getPointStates();pcl::io::saveVTKFile ("mesh.vtk", triangles);// Finishreturn (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(greedy_projection)find_package(PCL 1.2 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (greedy_projection greedy_projection.cpp)
target_link_libraries (greedy_projection ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.21 <分割> 将修剪的B样条曲线拟合到无序点云

学习:在点云上运行B样条拟合算法,以获得平滑的参数化曲面表示形式

结果图

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/bspline_fitting.html#bspline-fitting

创建目录,终端运行

bunny.pcd下载链接:

mkdir 21
cd 21
mkdir bspline_fitting
gedit bunny.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载bunny.pcd放到./20/bspline_fitting/build目录下
#有代码包的:cp ../../bunny.pcd ./
./bspline_fitting

结果显示

代码展示

##########################################
##########################################
##########################################
bspline_fitting.cpp
##########################################
##########################################
##########################################
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
#include <pcl/surface/on_nurbs/fitting_curve_2d_asdm.h>
#include <pcl/surface/on_nurbs/triangulation.h>typedef pcl::PointXYZ Point;void
PointCloud2Vector3d (pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d &data);void
visualizeCurve (ON_NurbsCurve &curve,ON_NurbsSurface &surface,pcl::visualization::PCLVisualizer &viewer);int
main (int argc, char *argv[])
{std::string pcd_file, file_3dm;if (argc < 3){printf ("\nUsage: pcl_example_nurbs_fitting_surface pcd<PointXYZ>-in-file 3dm-out-file\n\n");exit (0);}pcd_file = argv[1];file_3dm = argv[2];pcl::visualization::PCLVisualizer viewer ("B-spline surface fitting");viewer.setSize (800, 600);// ############################################################################// load point cloudprintf ("  loading %s\n", pcd_file.c_str ());pcl::PointCloud<Point>::Ptr cloud (new pcl::PointCloud<Point>);pcl::PCLPointCloud2 cloud2;pcl::on_nurbs::NurbsDataSurface data;if (pcl::io::loadPCDFile (pcd_file, cloud2) == -1)throw std::runtime_error ("  PCD file not found.");fromPCLPointCloud2 (cloud2, *cloud);PointCloud2Vector3d (cloud, data.interior);pcl::visualization::PointCloudColorHandlerCustom<Point> handler (cloud, 0, 255, 0);viewer.addPointCloud<Point> (cloud, handler, "cloud_cylinder");printf ("  %lu points in data set\n", cloud->size ());// ############################################################################// fit B-spline surface// parametersunsigned order (3);unsigned refinement (5);unsigned iterations (10);unsigned mesh_resolution (256);pcl::on_nurbs::FittingSurface::Parameter params;params.interior_smoothness = 0.2;params.interior_weight = 1.0;params.boundary_smoothness = 0.2;params.boundary_weight = 0.0;// initializeprintf ("  surface fitting ...\n");ON_NurbsSurface nurbs = pcl::on_nurbs::FittingSurface::initNurbsPCABoundingBox (order, &data);pcl::on_nurbs::FittingSurface fit (&data, nurbs);//  fit.setQuiet (false); // enable/disable debug output// mesh for visualizationpcl::PolygonMesh mesh;pcl::PointCloud<pcl::PointXYZ>::Ptr mesh_cloud (new pcl::PointCloud<pcl::PointXYZ>);std::vector<pcl::Vertices> mesh_vertices;std::string mesh_id = "mesh_nurbs";pcl::on_nurbs::Triangulation::convertSurface2PolygonMesh (fit.m_nurbs, mesh, mesh_resolution);viewer.addPolygonMesh (mesh, mesh_id);// surface refinementfor (unsigned i = 0; i < refinement; i++){fit.refine (0);fit.refine (1);fit.assemble (params);fit.solve ();pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id);viewer.spinOnce ();}// surface fitting with final refinement levelfor (unsigned i = 0; i < iterations; i++){fit.assemble (params);fit.solve ();pcl::on_nurbs::Triangulation::convertSurface2Vertices (fit.m_nurbs, mesh_cloud, mesh_vertices, mesh_resolution);viewer.updatePolygonMesh<pcl::PointXYZ> (mesh_cloud, mesh_vertices, mesh_id);viewer.spinOnce ();}// ############################################################################// fit B-spline curve// parameterspcl::on_nurbs::FittingCurve2dAPDM::FitParameter curve_params;curve_params.addCPsAccuracy = 5e-2;curve_params.addCPsIteration = 3;curve_params.maxCPs = 200;curve_params.accuracy = 1e-3;curve_params.iterations = 100;curve_params.param.closest_point_resolution = 0;curve_params.param.closest_point_weight = 1.0;curve_params.param.closest_point_sigma2 = 0.1;curve_params.param.interior_sigma2 = 0.00001;curve_params.param.smooth_concavity = 1.0;curve_params.param.smoothness = 1.0;// initialisation (circular)printf ("  curve fitting ...\n");pcl::on_nurbs::NurbsDataCurve2d curve_data;curve_data.interior = data.interior_param;curve_data.interior_weight_function.push_back (true);ON_NurbsCurve curve_nurbs = pcl::on_nurbs::FittingCurve2dAPDM::initNurbsCurve2D (order, curve_data.interior);// curve fittingpcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs);// curve_fit.setQuiet (false); // enable/disable debug outputcurve_fit.fitting (curve_params);visualizeCurve (curve_fit.m_nurbs, fit.m_nurbs, viewer);// ############################################################################// triangulation of trimmed surfaceprintf ("  triangulate trimmed surface ...\n");viewer.removePolygonMesh (mesh_id);pcl::on_nurbs::Triangulation::convertTrimmedSurface2PolygonMesh (fit.m_nurbs, curve_fit.m_nurbs, mesh,mesh_resolution);viewer.addPolygonMesh (mesh, mesh_id);// save trimmed B-spline surfaceif ( fit.m_nurbs.IsValid() ){ONX_Model model;ONX_Model_Object& surf = model.m_object_table.AppendNew();surf.m_object = new ON_NurbsSurface(fit.m_nurbs);surf.m_bDeleteObject = true;surf.m_attributes.m_layer_index = 1;surf.m_attributes.m_name = "surface";ONX_Model_Object& curv = model.m_object_table.AppendNew();curv.m_object = new ON_NurbsCurve(curve_fit.m_nurbs);curv.m_bDeleteObject = true;curv.m_attributes.m_layer_index = 2;curv.m_attributes.m_name = "trimming curve";model.Write(file_3dm.c_str());printf("  model saved: %s\n", file_3dm.c_str());}printf ("  ... done.\n");viewer.spin ();return 0;
}void
PointCloud2Vector3d (pcl::PointCloud<Point>::Ptr cloud, pcl::on_nurbs::vector_vec3d &data)
{for (unsigned i = 0; i < cloud->size (); i++){Point &p = cloud->at (i);if (!pcl_isnan (p.x) && !pcl_isnan (p.y) && !pcl_isnan (p.z))data.push_back (Eigen::Vector3d (p.x, p.y, p.z));}
}void
visualizeCurve (ON_NurbsCurve &curve, ON_NurbsSurface &surface, pcl::visualization::PCLVisualizer &viewer)
{pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);pcl::on_nurbs::Triangulation::convertCurve2PointCloud (curve, surface, curve_cloud, 4);for (std::size_t i = 0; i < curve_cloud->size () - 1; i++){pcl::PointXYZRGB &p1 = curve_cloud->at (i);pcl::PointXYZRGB &p2 = curve_cloud->at (i + 1);std::ostringstream os;os << "line" << i;viewer.removeShape (os.str ());viewer.addLine<pcl::PointXYZRGB> (p1, p2, 1.0, 0.0, 0.0, os.str ());}pcl::PointCloud<pcl::PointXYZRGB>::Ptr curve_cps (new pcl::PointCloud<pcl::PointXYZRGB>);for (int i = 0; i < curve.CVCount (); i++){ON_3dPoint p1;curve.GetCV (i, p1);double pnt[3];surface.Evaluate (p1.x, p1.y, 0, 3, pnt);pcl::PointXYZRGB p2;p2.x = float (pnt[0]);p2.y = float (pnt[1]);p2.z = float (pnt[2]);p2.r = 255;p2.g = 0;p2.b = 0;curve_cps->push_back (p2);}viewer.removePointCloud ("cloud_cps");viewer.addPointCloud (curve_cps, "cloud_cps");
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(bspline_fitting)find_package(PCL 1.7 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (bspline_fitting bspline_fitting.cpp)
target_link_libraries (bspline_fitting ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.22 <surface> 使用积分图像进行正态估计

学习:我们将学习如何使用积分图像为有组织的点云计算法线。

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/normal_estimation_using_integral_images.html#normal-estimation-using-integral-images

创建目录,终端运行

table_scene_mug_stereo_textured.pcd下载链接:未提供

mkdir 22
cd 22
mkdir normal_estimation_using_integral_images
gedit normal_estimation_using_integral_images.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载table_scene_mug_stereo_textured.pcd放到./22/normal_estimation_using_integral_images/build目录下
#有代码包的:cp ../../table_scene_mug_stereo_textured.pcd ./
./normal_estimation_using_integral_images

结果显示

代码展示

##########################################
##########################################
##########################################
normal_estimation_using_integral_images.cpp
##########################################
##########################################
##########################################
#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/integral_image_normal.h>int
main ()
{// load point cloudpcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile ("table_scene_mug_stereo_textured.pcd", *cloud);// estimate normalspcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);ne.setMaxDepthChangeFactor(0.02f);ne.setNormalSmoothingSize(10.0f);ne.setInputCloud(cloud);ne.compute(*normals);// visualize normalspcl::visualization::PCLVisualizer viewer("PCL Viewer");viewer.setBackgroundColor (0.0, 0.0, 0.5);viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, normals);while (!viewer.wasStopped ()){viewer.spinOnce ();}return 0;
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)project(normal_estimation_using_integral_images)find_package(PCL 1.3 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (normal_estimation_using_integral_images normal_estimation_using_integral_images.cpp)
target_link_libraries (normal_estimation_using_integral_images ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.23 <Features> 如何从范围图像中提取NARF特征

学习:如何从范围图像中提取NARF关键点位置的NARF描述符

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/normal_estimation_using_integral_images.html#normal-estimation-using-integral-images

1.pcd :自己下载的

创建目录,终端运行

mkdir 23
cd 23
gedit narf_feature_extraction.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
./narf_feature_extraction 1.pcd

结果显示

代码展示

##########################################
##########################################
##########################################
narf_feature_extraction.cpp
##########################################
##########################################
##########################################
/* \author Bastian Steder */#include <iostream>#include <boost/thread/thread.hpp>
#include <pcl/range_image/range_image.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/range_image_visualizer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/features/range_image_border_extractor.h>
#include <pcl/keypoints/narf_keypoint.h>
#include <pcl/features/narf_descriptor.h>
#include <pcl/console/parse.h>typedef pcl::PointXYZ PointType;// --------------------
// -----Parameters-----
// --------------------
float angular_resolution = 0.5f;
float support_size = 0.2f;
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
bool setUnseenToMaxRange = false;
bool rotation_invariant = true;// --------------
// -----Help-----
// --------------
void
printUsage (const char* progName)
{std::cout << "\n\nUsage: "<<progName<<" [options] <scene.pcd>\n\n"<< "Options:\n"<< "-------------------------------------------\n"<< "-r <float>   angular resolution in degrees (default "<<angular_resolution<<")\n"<< "-c <int>     coordinate frame (default "<< (int)coordinate_frame<<")\n"<< "-m           Treat all unseen points to max range\n"<< "-s <float>   support size for the interest points (diameter of the used sphere - ""default "<<support_size<<")\n"<< "-o <0/1>     switch rotational invariant version of the feature on/off"<<               " (default "<< (int)rotation_invariant<<")\n"<< "-h           this help\n"<< "\n\n";
}void
setViewerPose (pcl::visualization::PCLVisualizer& viewer, const Eigen::Affine3f& viewer_pose)
{Eigen::Vector3f pos_vector = viewer_pose * Eigen::Vector3f (0, 0, 0);Eigen::Vector3f look_at_vector = viewer_pose.rotation () * Eigen::Vector3f (0, 0, 1) + pos_vector;Eigen::Vector3f up_vector = viewer_pose.rotation () * Eigen::Vector3f (0, -1, 0);viewer.setCameraPosition (pos_vector[0], pos_vector[1], pos_vector[2],look_at_vector[0], look_at_vector[1], look_at_vector[2],up_vector[0], up_vector[1], up_vector[2]);
}// --------------
// -----Main-----
// --------------
int
main (int argc, char** argv)
{// --------------------------------------// -----Parse Command Line Arguments-----// --------------------------------------if (pcl::console::find_argument (argc, argv, "-h") >= 0){printUsage (argv[0]);return 0;}if (pcl::console::find_argument (argc, argv, "-m") >= 0){setUnseenToMaxRange = true;cout << "Setting unseen values in range image to maximum range readings.\n";}if (pcl::console::parse (argc, argv, "-o", rotation_invariant) >= 0)cout << "Switching rotation invariant feature version "<< (rotation_invariant ? "on" : "off")<<".\n";int tmp_coordinate_frame;if (pcl::console::parse (argc, argv, "-c", tmp_coordinate_frame) >= 0){coordinate_frame = pcl::RangeImage::CoordinateFrame (tmp_coordinate_frame);cout << "Using coordinate frame "<< (int)coordinate_frame<<".\n";}if (pcl::console::parse (argc, argv, "-s", support_size) >= 0)cout << "Setting support size to "<<support_size<<".\n";if (pcl::console::parse (argc, argv, "-r", angular_resolution) >= 0)cout << "Setting angular resolution to "<<angular_resolution<<"deg.\n";angular_resolution = pcl::deg2rad (angular_resolution);// ------------------------------------------------------------------// -----Read pcd file or create example point cloud if not given-----// ------------------------------------------------------------------pcl::PointCloud<PointType>::Ptr point_cloud_ptr (new pcl::PointCloud<PointType>);pcl::PointCloud<PointType>& point_cloud = *point_cloud_ptr;pcl::PointCloud<pcl::PointWithViewpoint> far_ranges;Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());std::vector<int> pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");if (!pcd_filename_indices.empty ()){std::string filename = argv[pcd_filename_indices[0]];if (pcl::io::loadPCDFile (filename, point_cloud) == -1){cerr << "Was not able to open file \""<<filename<<"\".\n";printUsage (argv[0]);return 0;}scene_sensor_pose = Eigen::Affine3f (Eigen::Translation3f (point_cloud.sensor_origin_[0],point_cloud.sensor_origin_[1],point_cloud.sensor_origin_[2])) *Eigen::Affine3f (point_cloud.sensor_orientation_);std::string far_ranges_filename = pcl::getFilenameWithoutExtension (filename)+"_far_ranges.pcd";if (pcl::io::loadPCDFile (far_ranges_filename.c_str (), far_ranges) == -1)std::cout << "Far ranges file \""<<far_ranges_filename<<"\" does not exists.\n";}else{setUnseenToMaxRange = true;cout << "\nNo *.pcd file given => Genarating example point cloud.\n\n";for (float x=-0.5f; x<=0.5f; x+=0.01f){for (float y=-0.5f; y<=0.5f; y+=0.01f){PointType point;  point.x = x;  point.y = y;  point.z = 2.0f - y;point_cloud.points.push_back (point);}}point_cloud.width = (int) point_cloud.points.size ();  point_cloud.height = 1;}// -----------------------------------------------// -----Create RangeImage from the PointCloud-----// -----------------------------------------------float noise_level = 0.0;float min_range = 0.0f;int border_size = 1;boost::shared_ptr<pcl::RangeImage> range_image_ptr (new pcl::RangeImage);pcl::RangeImage& range_image = *range_image_ptr;   range_image.createFromPointCloud (point_cloud, angular_resolution, pcl::deg2rad (360.0f), pcl::deg2rad (180.0f),scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);range_image.integrateFarRanges (far_ranges);if (setUnseenToMaxRange)range_image.setUnseenToMaxRange ();// --------------------------------------------// -----Open 3D viewer and add point cloud-----// --------------------------------------------pcl::visualization::PCLVisualizer viewer ("3D Viewer");viewer.setBackgroundColor (1, 1, 1);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 0, 0, 0);viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "range image");//viewer.addCoordinateSystem (1.0f, "global");//PointCloudColorHandlerCustom<PointType> point_cloud_color_handler (point_cloud_ptr, 150, 150, 150);//viewer.addPointCloud (point_cloud_ptr, point_cloud_color_handler, "original point cloud");viewer.initCameraParameters ();setViewerPose (viewer, range_image.getTransformationToWorldSystem ());// --------------------------// -----Show range image-----// --------------------------pcl::visualization::RangeImageVisualizer range_image_widget ("Range image");range_image_widget.showRangeImage (range_image);// --------------------------------// -----Extract NARF keypoints-----// --------------------------------pcl::RangeImageBorderExtractor range_image_border_extractor;pcl::NarfKeypoint narf_keypoint_detector;narf_keypoint_detector.setRangeImageBorderExtractor (&range_image_border_extractor);narf_keypoint_detector.setRangeImage (&range_image);narf_keypoint_detector.getParameters ().support_size = support_size;pcl::PointCloud<int> keypoint_indices;narf_keypoint_detector.compute (keypoint_indices);std::cout << "Found "<<keypoint_indices.points.size ()<<" key points.\n";// ----------------------------------------------// -----Show keypoints in range image widget-----// ----------------------------------------------//for (size_t i=0; i<keypoint_indices.points.size (); ++i)//range_image_widget.markPoint (keypoint_indices.points[i]%range_image.width,//keypoint_indices.points[i]/range_image.width);// -------------------------------------// -----Show keypoints in 3D viewer-----// -------------------------------------pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_ptr (new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>& keypoints = *keypoints_ptr;keypoints.points.resize (keypoint_indices.points.size ());for (size_t i=0; i<keypoint_indices.points.size (); ++i)keypoints.points[i].getVector3fMap () = range_image.points[keypoint_indices.points[i]].getVector3fMap ();pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> keypoints_color_handler (keypoints_ptr, 0, 255, 0);viewer.addPointCloud<pcl::PointXYZ> (keypoints_ptr, keypoints_color_handler, "keypoints");viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");// ------------------------------------------------------// -----Extract NARF descriptors for interest points-----// ------------------------------------------------------std::vector<int> keypoint_indices2;keypoint_indices2.resize (keypoint_indices.points.size ());for (unsigned int i=0; i<keypoint_indices.size (); ++i) // This step is necessary to get the right vector typekeypoint_indices2[i]=keypoint_indices.points[i];pcl::NarfDescriptor narf_descriptor (&range_image, &keypoint_indices2);narf_descriptor.getParameters ().support_size = support_size;narf_descriptor.getParameters ().rotation_invariant = rotation_invariant;pcl::PointCloud<pcl::Narf36> narf_descriptors;narf_descriptor.compute (narf_descriptors);cout << "Extracted "<<narf_descriptors.size ()<<" descriptors for "<<keypoint_indices.points.size ()<< " keypoints.\n";//--------------------// -----Main loop-----//--------------------while (!viewer.wasStopped ()){range_image_widget.spinOnce ();  // process GUI eventsviewer.spinOnce ();pcl_sleep(0.01);}
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)project(narf_feature_extraction)find_package(PCL 1.3 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (narf_feature_extraction narf_feature_extraction.cpp)
target_link_libraries (narf_feature_extraction ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

1.24 <features> 基于惯性矩和偏心率的描述符

学习:学习如何使用pcl :: MomentOfInertiaEstimation类来获取基于偏心率和惯性矩的描述符。该类还允许提取云的轴对齐和定向的边界框

官方链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/moment_of_inertia.html#moment-of-inertia

创建目录,终端运行

lamppost.pcd下载链接:https://github.com/PointCloudLibrary/data/blob/master/tutorials/min_cut_segmentation_tutorial.pcd

mkdir 24
cd 24
mkdir moment_of_inertia
gedit moment_of_inertia.cpp  ##加入代码
gedit CMakeLists.txt   ##加入代码
mkdir build
cd build
cmake ..
make
#下载lamppost.pcd放到./24/moment_of_inertia/build目录下
#有代码包的:cp ../../lamppost.pcd ./
./moment_of_inertia lamppost.pcd

结果显示

代码展示

##########################################
##########################################
##########################################
moment_of_inertia.cpp
##########################################
##########################################
##########################################
#include <pcl/features/moment_of_inertia_estimation.h>
#include <vector>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <boost/thread/thread.hpp>int main (int argc, char** argv)
{if (argc != 2)return (0);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ> ());if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)return (-1);pcl::MomentOfInertiaEstimation <pcl::PointXYZ> feature_extractor;feature_extractor.setInputCloud (cloud);feature_extractor.compute ();std::vector <float> moment_of_inertia;std::vector <float> eccentricity;pcl::PointXYZ min_point_AABB;pcl::PointXYZ max_point_AABB;pcl::PointXYZ min_point_OBB;pcl::PointXYZ max_point_OBB;pcl::PointXYZ position_OBB;Eigen::Matrix3f rotational_matrix_OBB;float major_value, middle_value, minor_value;Eigen::Vector3f major_vector, middle_vector, minor_vector;Eigen::Vector3f mass_center;feature_extractor.getMomentOfInertia (moment_of_inertia);feature_extractor.getEccentricity (eccentricity);feature_extractor.getAABB (min_point_AABB, max_point_AABB);feature_extractor.getOBB (min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);feature_extractor.getEigenValues (major_value, middle_value, minor_value);feature_extractor.getEigenVectors (major_vector, middle_vector, minor_vector);feature_extractor.getMassCenter (mass_center);boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));viewer->setBackgroundColor (0, 0, 0);viewer->addCoordinateSystem (1.0);viewer->initCameraParameters ();viewer->addPointCloud<pcl::PointXYZ> (cloud, "sample cloud");viewer->addCube (min_point_AABB.x, max_point_AABB.x, min_point_AABB.y, max_point_AABB.y, min_point_AABB.z, max_point_AABB.z, 1.0, 1.0, 0.0, "AABB");Eigen::Vector3f position (position_OBB.x, position_OBB.y, position_OBB.z);Eigen::Quaternionf quat (rotational_matrix_OBB);viewer->addCube (position, quat, max_point_OBB.x - min_point_OBB.x, max_point_OBB.y - min_point_OBB.y, max_point_OBB.z - min_point_OBB.z, "OBB");pcl::PointXYZ center (mass_center (0), mass_center (1), mass_center (2));pcl::PointXYZ x_axis (major_vector (0) + mass_center (0), major_vector (1) + mass_center (1), major_vector (2) + mass_center (2));pcl::PointXYZ y_axis (middle_vector (0) + mass_center (0), middle_vector (1) + mass_center (1), middle_vector (2) + mass_center (2));pcl::PointXYZ z_axis (minor_vector (0) + mass_center (0), minor_vector (1) + mass_center (1), minor_vector (2) + mass_center (2));viewer->addLine (center, x_axis, 1.0f, 0.0f, 0.0f, "major eigen vector");viewer->addLine (center, y_axis, 0.0f, 1.0f, 0.0f, "middle eigen vector");viewer->addLine (center, z_axis, 0.0f, 0.0f, 1.0f, "minor eigen vector");//Eigen::Vector3f p1 (min_point_OBB.x, min_point_OBB.y, min_point_OBB.z);//Eigen::Vector3f p2 (min_point_OBB.x, min_point_OBB.y, max_point_OBB.z);//Eigen::Vector3f p3 (max_point_OBB.x, min_point_OBB.y, max_point_OBB.z);//Eigen::Vector3f p4 (max_point_OBB.x, min_point_OBB.y, min_point_OBB.z);//Eigen::Vector3f p5 (min_point_OBB.x, max_point_OBB.y, min_point_OBB.z);//Eigen::Vector3f p6 (min_point_OBB.x, max_point_OBB.y, max_point_OBB.z);//Eigen::Vector3f p7 (max_point_OBB.x, max_point_OBB.y, max_point_OBB.z);//Eigen::Vector3f p8 (max_point_OBB.x, max_point_OBB.y, min_point_OBB.z);//p1 = rotational_matrix_OBB * p1 + position;//p2 = rotational_matrix_OBB * p2 + position;//p3 = rotational_matrix_OBB * p3 + position;//p4 = rotational_matrix_OBB * p4 + position;//p5 = rotational_matrix_OBB * p5 + position;//p6 = rotational_matrix_OBB * p6 + position;//p7 = rotational_matrix_OBB * p7 + position;//p8 = rotational_matrix_OBB * p8 + position;//pcl::PointXYZ pt1 (p1 (0), p1 (1), p1 (2));//pcl::PointXYZ pt2 (p2 (0), p2 (1), p2 (2));//pcl::PointXYZ pt3 (p3 (0), p3 (1), p3 (2));//pcl::PointXYZ pt4 (p4 (0), p4 (1), p4 (2));//pcl::PointXYZ pt5 (p5 (0), p5 (1), p5 (2));//pcl::PointXYZ pt6 (p6 (0), p6 (1), p6 (2));//pcl::PointXYZ pt7 (p7 (0), p7 (1), p7 (2));//pcl::PointXYZ pt8 (p8 (0), p8 (1), p8 (2));//viewer->addLine (pt1, pt2, 1.0, 0.0, 0.0, "1 edge");//viewer->addLine (pt1, pt4, 1.0, 0.0, 0.0, "2 edge");//viewer->addLine (pt1, pt5, 1.0, 0.0, 0.0, "3 edge");//viewer->addLine (pt5, pt6, 1.0, 0.0, 0.0, "4 edge");//viewer->addLine (pt5, pt8, 1.0, 0.0, 0.0, "5 edge");//viewer->addLine (pt2, pt6, 1.0, 0.0, 0.0, "6 edge");//viewer->addLine (pt6, pt7, 1.0, 0.0, 0.0, "7 edge");//viewer->addLine (pt7, pt8, 1.0, 0.0, 0.0, "8 edge");//viewer->addLine (pt2, pt3, 1.0, 0.0, 0.0, "9 edge");//viewer->addLine (pt4, pt8, 1.0, 0.0, 0.0, "10 edge");//viewer->addLine (pt3, pt4, 1.0, 0.0, 0.0, "11 edge");//viewer->addLine (pt3, pt7, 1.0, 0.0, 0.0, "12 edge");while(!viewer->wasStopped()){viewer->spinOnce (100);boost::this_thread::sleep (boost::posix_time::microseconds (100000));}return (0);
}
##########################################
##########################################
##########################################
CMakeLists.txt
##########################################
##########################################
##########################################
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)project(moment_of_inertia)find_package(PCL 1.8 REQUIRED)include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})add_executable (moment_of_inertia moment_of_inertia.cpp)
target_link_libraries (moment_of_inertia ${PCL_LIBRARIES})

<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码

《《《总结》》》PCL的42个实例整理:1~24相关推荐

  1. PHP输出结构类型变量输出,php输出形式实例整理

    php中有几种输出形式 在php中有5种输出形式,分别是echo.print_r.print.var_dump和die. echo 只能输出字符串等单一数据 不能输出数据类型 不能输出数组等多种数据. ...

  2. Fiddler工具使用与配置 【实例整理】

    文章目录 1.引言 2.从事测试岗位需要掌握哪些技能 3.HTTP协议的主要特点: 4.Fiddler简介 5.Fiddler环境配置 6.Fiddler的使用 6.1.请求行 6.2.请求头 6.3 ...

  3. 关于DG(域泛化)领域的PCL方法的代码实例

    分享一下文章PCL: Proxy-based Contrastive Learning for Domain Generalization,代码已经在GitHub上已经开源,其使用的是在DomainB ...

  4. c++ svd实例整理

    矩阵简单封装,下面两个是一样的 http://download.csdn.net/download/o07sai/2206411 https://github.com/jiaohaitao/svd d ...

  5. opencl fft实例整理

    ocl版的: https://github.com/betaupsx86/FFT_OCL python版的: A Python wrapper for the OpenCL FFT library c ...

  6. kcf跟踪算法实例整理

    http://blog.csdn.NET/shenxiaolu1984/article/details/50905283 本文的跟踪方法效果甚好,速度奇高,思想和实现均十分简洁.其中利用循环矩阵进行快 ...

  7. 三菱fx 3u plc官方定位实例 整理

  8. GPS定位及获取卫星参数实例整理

    1.Android定位服务接口 sdk中已有一些可用的定位服务接口: 这里着重说一下GpsSatellite 接口 GpsSatellite结构 继承关系 public final class Gps ...

  9. 吐血整理:24种可视化图表优缺点对比,一图看懂!

    来源:大数据DT 本文约3900字,建议阅读7分钟 史上最全图表类型术语&指南来了! 安德鲁·阿伯拉(Andrew Abela)制作的<这份指南>(This Guide)是思考图表 ...

  10. 没有bug队——加贝——Python 练习实例 23,24

    23.题目:打印菱形 程序分析:先把图形分成两部分来看待,前四行一个规律,后三行一个规律,利用双重for循环,第一层控制行,第二层控制列. 注:将这个图形看成对称的,前面和后面的编辑方式正好相反 代码 ...

最新文章

  1. hdu 1599 find the mincost route(找无向图最小环)(floyd求最小环)
  2. 保镖机器人作文_我的保镖作文500字
  3. 概率整形技术(PCS)介绍
  4. 水文特点是什么意思_水文监测仪器设备简介
  5. Protobuf生成Java代码(Maven)
  6. 关于.Net Application Server对象访问方式的设计(2.上)
  7. 单片机六位抢答器c语言程序,八路电子抢答器(基于51单片机的8路抢答器设计C语言程序)...
  8. Matlab~30个算法
  9. Android实现Telnet客户端
  10. 汉王数据导入java环境,怎样把u盆内容导入汉王门禁考勤管理软件
  11. matlab水汽计算公式,饱和水汽压的计算
  12. 微表情识别 · 读脸读心满分答案
  13. arduino 44键盘制作简易计算器
  14. android5.0 root工具,ROOT大师:Android 5.0 ROOT并没那么难
  15. ubuntu12.04/14.04/16.04 安装搜狗输入法 解决shift按键不能切换英文输入
  16. linux加载和卸载驱动模块出现 'XXX': device or resource busy 错误提示
  17. 使用SpriteAtlas打包图集并显示
  18. IDEA的插件,IDEA强大的插件库
  19. 在自己的数据集上训练CrowdDet过程记录
  20. 实现textarea不自动换行

热门文章

  1. ubuntu 14.04 安装 diffmerge
  2. 大学生mysql实训心得_大学生实训心得与收获
  3. QT样式表设置 之 QComboBox下拉框样式
  4. 网络基础之冲突域和广播域
  5. linux获取电信超级密码吗,最新中国电信光猫超级密码获取方法
  6. Filter中获取传递参数(解决post请求参数问题)
  7. jsp文字上下居中显示_div+css:页面整体布局居中显示:上下居中||垂直居中,左右居中||水平居中...
  8. 瘦AP如何连接到无线控制器AC
  9. H5app 调用手机摄像头拍照、录制视频并上传demo
  10. 连点器android版本,连点器安卓手机版