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 <分割> 基于惯性矩和偏心率的描述符
环境:ubuntu16.04/18.04
知识共享开源有利于知识迭代本是好事儿,我坚持初心,知道多少写多少,不藏着掖着,
但是如果没有好的激励机制,笔者定会心生倦怠,理解我不容易的,可以下载我整理好的包,请我吃根雪糕
下面的程序使用是没问题的;
注:中间涉及到的需要选择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
下载位置:https://github.com/PointCloudLibrary/pcl
下载后解压到主目录下,默认名字为pcl_版本号,建议下载高于8.0的版本,默认下载是1.7.2,后面教程有的跑不通;
下载解压后,名字统一改成pcl
在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
sudo apt-get install libopenni-dev
sudo apt-get install libopenni2-dev
PCL官方提供的可以用于使用的案例目录太长了,目录如下:https://blog.csdn.net/weixin_36662031/article/details/79352100
我把自己跑通过的案例,进行汇总了一下,便于随时调用:
在本教程中,我们将学习如何删除沿指定维度在用户给定间隔内/外的值的点。
注意,坐标轴表示为红色(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
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
// Fill in the cloud data
cloud->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 object
pcl::PassThrough 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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习如何使用体素化网格方法对点云数据集进行降采样(即减少点数)
官方链接 :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
#include
#include
#include
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 data
pcl::PCDReader reader;
// Replace the path below with the path where you saved your file
reader.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 object
pcl::VoxelGrid 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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习如何使用统计分析技术从点云数据集中去除噪声测量值,例如离群值
官方链接: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
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
// Fill in the cloud data
pcl::PCDReader reader;
// Replace the path below with the path where you saved your file
reader.read ("table_scene_lms400.pcd", *cloud);
std::cerr << "Cloud before filtering: " << std::endl;
std::cerr << *cloud << std::endl;
// Create the filtering object
pcl::StatisticalOutlierRemoval 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 ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);
sor.setNegative (true);
sor.filter (*cloud_filtered);
writer.write ("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最近邻距离。
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习如何将点投影到参数模型(例如,平面,球体等)上。参数模型通过一组系数给出-在平面情况下,通过其方程式: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
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_projected (new pcl::PointCloud);
// Fill in the cloud data
cloud->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=1
pcl::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 object
pcl::ProjectInliers 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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
基于分段算法输出的索引从点云中提取点的子集
官方链接: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
#include
#include
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud), cloud_p (new pcl::PointCloud), cloud_f (new pcl::PointCloud);
// Fill in the cloud data
pcl::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 1cm
pcl::VoxelGrid sor;
sor.setInputCloud (cloud_blob);
sor.setLeafSize (0.01f, 0.01f, 0.01f);
sor.filter (*cloud_filtered_blob);
// Convert to the templated PointCloud
pcl::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 disk
pcl::PCDWriter writer;
writer.write ("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 object
pcl::SACSegmentation seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setMaxIterations (1000);
seg.setDistanceThreshold (0.01);
// Create the filtering object
pcl::ExtractIndices extract;
int i = 0, nr_points = (int) cloud_filtered->points.size ();
// While 30% of the original cloud is still there
while (cloud_filtered->points.size () > 0.3 * nr_points)
{
// Segment the largest planar component from the remaining cloud
seg.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 inliers
extract.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 (ss.str (), *cloud_p, false);
// Create the filtering object
extract.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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
该过滤器将删除其输入云中在一定范围内没有至少一些邻居的所有索引
每个索引必须具有指定半径内的邻居才能保留在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
#include
#include
#include
int
main (int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
exit(0);
}
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
// Fill in the cloud data
cloud->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 outrem;
// build the filter
outrem.setInputCloud(cloud);
outrem.setRadiusSearch(0.8);
outrem.setMinNeighborsInRadius (2);
// apply filter
outrem.filter (*cloud_filtered);
}
else if (strcmp(argv[1], "-c") == 0){
// build the condition
pcl::ConditionAnd::Ptr range_cond (new
pcl::ConditionAnd ());
range_cond->addComparison (pcl::FieldComparison::ConstPtr (new
pcl::FieldComparison ("z", pcl::ComparisonOps::GT, 0.0)));
range_cond->addComparison (pcl::FieldComparison::ConstPtr (new
pcl::FieldComparison ("z", pcl::ComparisonOps::LT, 0.8)));
// build the filter
pcl::ConditionalRemoval condrem;
condrem.setCondition (range_cond);
condrem.setInputCloud (cloud);
condrem.setKeepOrganized(true);
// apply filter
condrem.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 filtering
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(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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习提取在某一平面上的点
官方链接: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
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud(new pcl::PointCloud);
// Fill in the cloud data
cloud->width = 15;
cloud->height = 1;
cloud->points.resize (cloud->width * cloud->height);
// Generate the data
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 = 1.0;
}
// Set a few outliers
cloud->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 object
pcl::SACSegmentation seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
提取圆柱数据
官方链接: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
#include
#include
#include
#include
#include
#include
#include
#include
typedef pcl::PointXYZ PointT;
int
main (int argc, char** argv)
{
// All the objects needed
pcl::PCDReader reader;
pcl::PassThrough pass;
pcl::NormalEstimation ne;
pcl::SACSegmentationFromNormals seg;
pcl::PCDWriter writer;
pcl::ExtractIndices extract;
pcl::ExtractIndices extract_normals;
pcl::search::KdTree::Ptr tree (new pcl::search::KdTree ());
// Datasets
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_normals (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered2 (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_normals2 (new pcl::PointCloud);
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 data
reader.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 NaNs
pass.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 normals
ne.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 parameters
seg.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 coefficients
seg.segment (*inliers_plane, *coefficients_plane);
std::cerr << "Plane coefficients: " << *coefficients_plane << std::endl;
// Extract the planar inliers from the input cloud
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers_plane);
extract.setNegative (false);
// Write the planar inliers to disk
pcl::PointCloud::Ptr cloud_plane (new pcl::PointCloud ());
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 rest
extract.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 parameters
seg.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 coefficients
seg.segment (*inliers_cylinder, *coefficients_cylinder);
std::cerr << "Cylinder coefficients: " << *coefficients_cylinder << std::endl;
// Write the cylinder inliers to disk
extract.setInputCloud (cloud_filtered2);
extract.setIndices (inliers_cylinder);
extract.setNegative (false);
pcl::PointCloud::Ptr cloud_cylinder (new pcl::PointCloud ());
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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:欧几里得分割
官方链接: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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
// Read in the cloud data
pcl::PCDReader reader;
pcl::PointCloud::Ptr cloud (new pcl::PointCloud), cloud_f (new pcl::PointCloud);
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 1cm
pcl::VoxelGrid vg;
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
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 parameters
pcl::SACSegmentation seg;
pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
pcl::PointCloud::Ptr cloud_plane (new pcl::PointCloud ());
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 cloud
seg.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 cloud
pcl::ExtractIndices extract;
extract.setInputCloud (cloud_filtered);
extract.setIndices (inliers);
extract.setNegative (false);
// Get the points associated with the planar surface
extract.filter (*cloud_plane);
std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size () << " data points." << std::endl;
// Remove the planar inliers, extract the rest
extract.setNegative (true);
extract.filter (*cloud_f);
*cloud_filtered = *cloud_f;
}
// Creating the KdTree object for the search method of the extraction
pcl::search::KdTree::Ptr tree (new pcl::search::KdTree);
tree->setInputCloud (cloud_filtered);
std::vector cluster_indices;
pcl::EuclideanClusterExtraction ec;
ec.setClusterTolerance (0.02); // 2cm
ec.setMinClusterSize (100);
ec.setMaxClusterSize (25000);
ec.setSearchMethod (tree);
ec.setInputCloud (cloud_filtered);
ec.extract (cluster_indices);
int j = 0;
for (std::vector::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
{
pcl::PointCloud::Ptr cloud_cluster (new pcl::PointCloud);
for (std::vector::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 (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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:区域增长细分
学习如何使用在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
#include
#include
#include
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
if ( pcl::io::loadPCDFile ("region_growing_tutorial.pcd", *cloud) == -1)
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
pcl::search::Search::Ptr tree = boost::shared_ptr > (new pcl::search::KdTree);
pcl::PointCloud ::Ptr normals (new pcl::PointCloud );
pcl::NormalEstimation normal_estimator;
normal_estimator.setSearchMethod (tree);
normal_estimator.setInputCloud (cloud);
normal_estimator.setKSearch (50);
normal_estimator.compute (*normals);
pcl::IndicesPtr indices (new std::vector );
pcl::PassThrough pass;
pass.setInputCloud (cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
pass.filter (*indices);
pcl::RegionGrowing 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 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 ::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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:学习如何使用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
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std::chrono_literals;
int
main (int argc, char** argv)
{
pcl::search::Search ::Ptr tree (new pcl::search::KdTree);
pcl::PointCloud ::Ptr cloud (new pcl::PointCloud );
if ( pcl::io::loadPCDFile ("region_growing_rgb_tutorial.pcd", *cloud) == -1 )
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
pcl::IndicesPtr indices (new std::vector );
pcl::PassThrough pass;
pass.setInputCloud (cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
pass.filter (*indices);
pcl::RegionGrowingRGB reg;
reg.setInputCloud (cloud);
reg.setIndices (indices);
reg.setSearchMethod (tree);
reg.setDistanceThreshold (10);
reg.setPointColorThreshold (6);
reg.setRegionColorThreshold (5);
reg.setMinClusterSize (600);
std::vector clusters;
reg.extract (clusters);
pcl::PointCloud ::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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:学习如何使用在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
#include
#include
#include
#include
#include
#include
int main (int argc, char** argv)
{
pcl::PointCloud ::Ptr cloud (new pcl::PointCloud );
if ( pcl::io::loadPCDFile ("min_cut_segmentation_tutorial.pcd", *cloud) == -1 )
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
pcl::IndicesPtr indices (new std::vector );
pcl::PassThrough pass;
pass.setInputCloud (cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
pass.filter (*indices);
pcl::MinCutSegmentation seg;
seg.setInputCloud (cloud);
seg.setIndices (indices);
pcl::PointCloud::Ptr foreground_points(new pcl::PointCloud ());
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 clusters;
seg.extract (clusters);
std::cout << "Maximum flow is " << seg.getMaxFlow () << std::endl;
pcl::PointCloud ::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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:一种分割算法,该算法基于欧几里得距离和需要保持的用户可自定义条件对点进行聚类。
官方链接: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
#include
#include
#include
#include
#include
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);
else
return (false);
}
bool
enforceCurvatureOrIntensitySimilarity (const PointTypeFull& point_a, const PointTypeFull& point_b, float squared_distance)
{
Eigen::Map 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 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 used
pcl::PointCloud::Ptr cloud_in (new pcl::PointCloud), cloud_out (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_with_normals (new pcl::PointCloud);
pcl::IndicesClustersPtr clusters (new pcl::IndicesClusters), small_clusters (new pcl::IndicesClusters), large_clusters (new pcl::IndicesClusters);
pcl::search::KdTree::Ptr search_tree (new pcl::search::KdTree);
pcl::console::TicToc tt;
// Load the input point cloud
std::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 class
std::cerr << "Downsampling...\n", tt.tic ();
pcl::VoxelGrid 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_normals
std::cerr << "Computing normals...\n", tt.tic ();
pcl::copyPointCloud (*cloud_out, *cloud_with_normals);
pcl::NormalEstimation 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 class
std::cerr << "Segmenting to clusters...\n", tt.tic ();
pcl::ConditionalEuclideanClustering 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 output
for (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 cloud
std::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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:学习如何使用在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
#include
#include
#include
#include
#include
#include
#include
#include
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 by
double threshold;
///segment scene into clusters with given distance tolerance using euclidean clustering
double 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 scale
istringstream (argv[2]) >> scale1;
/// large scale
istringstream (argv[3]) >> scale2;
istringstream (argv[4]) >> threshold; // threshold for DoN magnitude
istringstream (argv[5]) >> segradius; // threshold for radius segmentation
// Load cloud in blob format
pcl::PCLPointCloud2 blob;
pcl::io::loadPCDFile (infile.c_str (), blob);
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::fromPCLPointCloud2 (blob, *cloud);
// Create a search tree, use KDTreee for non-organized data.
pcl::search::Search::Ptr tree;
if (cloud->isOrganized ())
{
tree.reset (new pcl::search::OrganizedNeighbor ());
}
else
{
tree.reset (new pcl::search::KdTree (false));
}
// Set the input pointcloud for the search tree
tree->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 point
pcl::NormalEstimationOMP 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::max (), std::numeric_limits::max (), std::numeric_limits::max ());
// calculate normals with the small scale
cout << "Calculating normals for scale..." << scale1 << endl;
pcl::PointCloud::Ptr normals_small_scale (new pcl::PointCloud);
ne.setRadiusSearch (scale1);
ne.compute (*normals_small_scale);
// calculate normals with the large scale
cout << "Calculating normals for scale..." << scale2 << endl;
pcl::PointCloud::Ptr normals_large_scale (new pcl::PointCloud);
ne.setRadiusSearch (scale2);
ne.compute (*normals_large_scale);
// Create output cloud for DoN results
PointCloud::Ptr doncloud (new pcl::PointCloud);
copyPointCloud(*cloud, *doncloud);
cout << "Calculating DoN... " << endl;
// Create DoN operator
pcl::DifferenceOfNormalsEstimation 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 DoN
don.computeFeature (*doncloud);
// Save DoN features
pcl::PCDWriter writer;
writer.write ("don.pcd", *doncloud, false);
// Filter by magnitude
cout << "Filtering out DoN mag <= " << threshold << "..." << endl;
// Build the condition for filtering
pcl::ConditionOr::Ptr range_cond (
new pcl::ConditionOr ()
);
range_cond->addComparison (pcl::FieldComparison::ConstPtr (
new pcl::FieldComparison ("curvature", pcl::ComparisonOps::GT, threshold))
);
// Build the filter
pcl::ConditionalRemoval condrem (range_cond);
condrem.setInputCloud (doncloud);
pcl::PointCloud::Ptr doncloud_filtered (new pcl::PointCloud);
// Apply filter
condrem.filter (*doncloud_filtered);
doncloud = doncloud_filtered;
// Save filtered output
std::cout << "Filtered Pointcloud: " << doncloud->points.size () << " data points." << std::endl;
writer.write ("don_filtered.pcd", *doncloud, false);
// Filter by magnitude
cout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << endl;
pcl::search::KdTree::Ptr segtree (new pcl::search::KdTree);
segtree->setInputCloud (doncloud);
std::vector cluster_indices;
pcl::EuclideanClusterExtraction 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::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++)
{
pcl::PointCloud::Ptr cloud_cluster_don (new pcl::PointCloud);
for (std::vector::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 cluster
cout << "PointCloud representing the Cluster: " << cloud_cluster_don->points.size () << " data points." << std::endl;
stringstream ss;
ss << "don_cluster_" << j << ".pcd";
writer.write (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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:点云聚类为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
#include
#include
#include
#include
#include
//VTK include needed for drawing graph lines
#include
// Types
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud PointCloudT;
typedef pcl::PointNormal PointNT;
typedef pcl::PointCloud PointNCloudT;
typedef pcl::PointXYZL PointLT;
typedef pcl::PointCloud PointLCloudT;
void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,
PointCloudT &adjacent_supervoxel_centers,
std::string supervoxel_name,
boost::shared_ptr & viewer);
int
main (int argc, char ** argv)
{
if (argc < 2)
{
pcl::console::print_error ("Syntax is: %s \n "
"--NT Dsables the single cloud transform \n"
"-v \n-s \n"
"-c \n-z \n"
"-n \n", argv[0]);
return (1);
}
PointCloudT::Ptr cloud = boost::shared_ptr (new PointCloudT ());
pcl::console::print_highlight ("Loading point cloud...\n");
if (pcl::io::loadPCDFile (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 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 ::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 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 (sv_normal_cloud,1,0.05f, "supervoxel_normals");
pcl::console::print_highlight ("Getting supervoxel adjacency\n");
std::multimap supervoxel_adjacency;
super.getSupervoxelAdjacency (supervoxel_adjacency);
//To make a graph of the supervoxel adjacency, we need to iterate through the supervoxel adjacency multimap
std::multimap::iterator label_itr = supervoxel_adjacency.begin ();
for ( ; label_itr != supervoxel_adjacency.end (); )
{
//First get the label
uint32_t supervoxel_label = label_itr->first;
//Now get the supervoxel corresponding to the label
pcl::Supervoxel::Ptr supervoxel = supervoxel_clusters.at (supervoxel_label);
//Now we need to iterate through the adjacent supervoxels and make a point cloud of them
PointCloudT adjacent_supervoxel_centers;
std::multimap::iterator adjacent_itr = supervoxel_adjacency.equal_range (supervoxel_label).first;
for ( ; adjacent_itr!=supervoxel_adjacency.equal_range (supervoxel_label).second; ++adjacent_itr)
{
pcl::Supervoxel::Ptr neighbor_supervoxel = supervoxel_clusters.at (adjacent_itr->second);
adjacent_supervoxel_centers.push_back (neighbor_supervoxel->centroid_);
}
//Now we make a name for this polygon
std::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 given
addSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer);
//Move iterator forward to next label
label_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 & viewer)
{
vtkSmartPointer points = vtkSmartPointer::New ();
vtkSmartPointer cells = vtkSmartPointer::New ();
vtkSmartPointer polyLine = vtkSmartPointer::New ();
//Iterate through all adjacent points, and add a center point to adjacent point pair
PointCloudT::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 in
vtkSmartPointer polyData = vtkSmartPointer::New ();
// Add the points to the dataset
polyData->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 dataset
polyData->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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:
官方链接:
创建目录,终端运行
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
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_filtered (new pcl::PointCloud);
pcl::PointIndicesPtr ground (new pcl::PointIndices);
// Fill in the cloud data
pcl::PCDReader reader;
// Replace the path below with the path where you saved your file
reader.read ("samp11-utm.pcd", *cloud);
std::cerr << "Cloud before filtering: " << std::endl;
std::cerr << *cloud << std::endl;
// Create the filtering object
pcl::ProgressiveMorphologicalFilter 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 object
pcl::ExtractIndices 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 ("samp11-utm_ground.pcd", *cloud_filtered, false);
// Extract non-ground returns
extract.setNegative (true);
extract.filter (*cloud_filtered);
std::cerr << "Object cloud after filtering: " << std::endl;
std::cerr << *cloud_filtered << std::endl;
writer.write ("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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:通过使用具有已知系数的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
#include
#include
int
main ()
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::PointCloud::Ptr cloud_sphere_filtered (new pcl::PointCloud);
// 1. Generate cloud data
int 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 noise
for (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.html
while (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: 1
pcl::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 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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:使用移动最小二乘(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
#include
#include
#include
int
main (int argc, char** argv)
{
// Load input file into a PointCloud with an appropriate type
pcl::PointCloud::Ptr cloud (new pcl::PointCloud ());
// Load bun0.pcd -- should be available with the PCL archive in test
pcl::io::loadPCDFile ("bun0.pcd", *cloud);
// Create a KD-Tree
pcl::search::KdTree::Ptr tree (new pcl::search::KdTree);
// Output has the PointNormal type in order to store the normals calculated by MLS
pcl::PointCloud mls_points;
// Init object (second point type is for the normals, even if unused)
pcl::MovingLeastSquares mls;
mls.setComputeNormals (true);
// Set parameters
mls.setInputCloud (cloud);
mls.setPolynomialFit (true);
mls.setSearchMethod (tree);
mls.setSearchRadius (0.03);
// Reconstruct
mls.process (mls_points);
// Save output
pcl::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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:学习如何为平面所支持的一组点计算简单的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_2d
cd ..
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
#include
#include
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud),
cloud_filtered (new pcl::PointCloud),
cloud_projected (new pcl::PointCloud);
pcl::PCDReader reader;
reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
// Build a filter to remove spurious NaNs
pcl::PassThrough 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 object
pcl::SACSegmentation seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.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 inliers
pcl::ProjectInliers 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 inliers
pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud);
pcl::ConcaveHull 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
#include
#include
#include
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
pcl::PointCloud::Ptr cloud (new pcl::PointCloud), cloud_filtered (new pcl::PointCloud), cloud_projected (new pcl::PointCloud);
pcl::PCDReader reader;
reader.read ("table_scene_mug_stereo_textured.pcd", *cloud);
// Build a filter to remove spurious NaNs
pcl::PassThrough 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 object
pcl::SACSegmentation seg;
// Optional
seg.setOptimizeCoefficients (true);
// Mandatory
seg.setModelType (pcl::SACMODEL_PLANE);
seg.setMethodType (pcl::SAC_RANSAC);
seg.setDistanceThreshold (0.01);
seg.setInputCloud (cloud_filtered);
seg.segment (*inliers, *coefficients);
// Project the model inliers
pcl::ProjectInliers 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 inliers
pcl::PointCloud::Ptr cloud_hull (new pcl::PointCloud);
pcl::ConvexHull 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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:该方法通过维护可从其扩展网格的点的列表(“边缘”点)并将其扩展到连接所有可能的点来起作用。它可以处理来自一次或多次扫描并具有多个相连部分的无组织点。如果表面局部光滑并且在具有不同点密度的区域之间存在平滑过渡,则效果最佳。
官方链接: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
#include
#include
#include
#include
#include
int
main (int argc, char** argv)
{
// Load input file into a PointCloud with an appropriate type
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
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 n;
pcl::PointCloud::Ptr normals (new pcl::PointCloud);
pcl::search::KdTree::Ptr tree (new pcl::search::KdTree);
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::Ptr cloud_with_normals (new pcl::PointCloud);
pcl::concatenateFields (*cloud, *normals, *cloud_with_normals);
//* cloud_with_normals = cloud + normals
// Create search tree*
pcl::search::KdTree::Ptr tree2 (new pcl::search::KdTree);
tree2->setInputCloud (cloud_with_normals);
// Initialize objects
pcl::GreedyProjectionTriangulation gp3;
pcl::PolygonMesh triangles;
// Set the maximum distance between connected points (maximum edge length)
gp3.setSearchRadius (0.025);
// Set typical values for the parameters
gp3.setMu (2.5);
gp3.setMaximumNearestNeighbors (100);
gp3.setMaximumSurfaceAngle(M_PI/4); // 45 degrees
gp3.setMinimumAngle(M_PI/18); // 10 degrees
gp3.setMaximumAngle(2*M_PI/3); // 120 degrees
gp3.setNormalConsistency(false);
// Get result
gp3.setInputCloud (cloud_with_normals);
gp3.setSearchMethod (tree2);
gp3.reconstruct (triangles);
// Additional vertex information
std::vector parts = gp3.getPartIDs();
std::vector states = gp3.getPointStates();
pcl::io::saveVTKFile ("mesh.vtk", triangles);
// Finish
return (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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:在点云上运行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
#include
#include
#include
#include
#include
#include
typedef pcl::PointXYZ Point;
void
PointCloud2Vector3d (pcl::PointCloud::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-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 cloud
printf (" loading %s\n", pcd_file.c_str ());
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
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 handler (cloud, 0, 255, 0);
viewer.addPointCloud (cloud, handler, "cloud_cylinder");
printf (" %lu points in data set\n", cloud->size ());
// ############################################################################
// fit B-spline surface
// parameters
unsigned 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;
// initialize
printf (" 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 visualization
pcl::PolygonMesh mesh;
pcl::PointCloud::Ptr mesh_cloud (new pcl::PointCloud);
std::vector 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 refinement
for (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 (mesh_cloud, mesh_vertices, mesh_id);
viewer.spinOnce ();
}
// surface fitting with final refinement level
for (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 (mesh_cloud, mesh_vertices, mesh_id);
viewer.spinOnce ();
}
// ############################################################################
// fit B-spline curve
// parameters
pcl::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 fitting
pcl::on_nurbs::FittingCurve2dASDM curve_fit (&curve_data, curve_nurbs);
// curve_fit.setQuiet (false); // enable/disable debug output
curve_fit.fitting (curve_params);
visualizeCurve (curve_fit.m_nurbs, fit.m_nurbs, viewer);
// ############################################################################
// triangulation of trimmed surface
printf (" 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 surface
if ( 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::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::Ptr curve_cloud (new pcl::PointCloud);
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 (p1, p2, 1.0, 0.0, 0.0, os.str ());
}
pcl::PointCloud::Ptr curve_cps (new pcl::PointCloud);
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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:我们将学习如何使用积分图像为有组织的点云计算法线。
官方链接: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
#include
#include
#include
#include
int
main ()
{
// load point cloud
pcl::PointCloud::Ptr cloud (new pcl::PointCloud);
pcl::io::loadPCDFile ("table_scene_mug_stereo_textured.pcd", *cloud);
// estimate normals
pcl::PointCloud::Ptr normals (new pcl::PointCloud);
pcl::IntegralImageNormalEstimation ne;
ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
ne.setMaxDepthChangeFactor(0.02f);
ne.setNormalSmoothingSize(10.0f);
ne.setInputCloud(cloud);
ne.compute(*normals);
// visualize normals
pcl::visualization::PCLVisualizer viewer("PCL Viewer");
viewer.setBackgroundColor (0.0, 0.0, 0.5);
viewer.addPointCloudNormals(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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:如何从范围图像中提取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
#include
#include
#include
#include
#include
#include
#include
#include
#include
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: "<\n\n"
<< "Options:\n"
<< "-------------------------------------------\n"
<< "-r angular resolution in degrees (default "< coordinate frame (default "<< (int)coordinate_frame<<")\n"
<< "-m Treat all unseen points to max range\n"
<< "-s support size for the interest points (diameter of the used sphere - "
"default "< 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 "<= 0)
cout << "Setting angular resolution to "<::Ptr point_cloud_ptr (new pcl::PointCloud);
pcl::PointCloud& point_cloud = *point_cloud_ptr;
pcl::PointCloud far_ranges;
Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());
std::vector 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 \""< 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 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 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 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 keypoint_indices;
narf_keypoint_detector.compute (keypoint_indices);
std::cout << "Found "<::Ptr keypoints_ptr (new pcl::PointCloud);
pcl::PointCloud& keypoints = *keypoints_ptr;
keypoints.points.resize (keypoint_indices.points.size ());
for (size_t i=0; i keypoints_color_handler (keypoints_ptr, 0, 255, 0);
viewer.addPointCloud (keypoints_ptr, keypoints_color_handler, "keypoints");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");
// ------------------------------------------------------
// -----Extract NARF descriptors for interest points-----
// ------------------------------------------------------
std::vector keypoint_indices2;
keypoint_indices2.resize (keypoint_indices.points.size ());
for (unsigned int i=0; i narf_descriptors;
narf_descriptor.compute (narf_descriptors);
cout << "Extracted "<
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码
学习:学习如何使用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
#include
#include
#include
#include
#include
int main (int argc, char** argv)
{
if (argc != 2)
return (0);
pcl::PointCloud::Ptr cloud (new pcl::PointCloud ());
if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
return (-1);
pcl::MomentOfInertiaEstimation feature_extractor;
feature_extractor.setInputCloud (cloud);
feature_extractor.compute ();
std::vector moment_of_inertia;
std::vector 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 viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
viewer->setBackgroundColor (0, 0, 0);
viewer->addCoordinateSystem (1.0);
viewer->initCameraParameters ();
viewer->addPointCloud (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})
<注>如果感觉整理麻烦,请博主吃雪糕,下载整理好的全套代码