PCL C++版【学习备忘】

一、PCL基础及相关介绍

1、PCL官网及教程用例

请点击—> PCL官网链接 <-----&&&----->PCL教程用例

2、PCL中各个模块介绍

请点击—> PCL-简介(包含各个模块介绍)

PCL包含的模块:
libpcl filters:如采样、去除离群点、特征提取、拟合估计等数据实现过滤器;
libpcl features:实现多种三维特征,如曲面法线、曲率、边界点估计、矩不变量、主曲率,
        PFH和FPFH特征,旋转图像、积分图像,NARF描述子,RIFT,相对标准偏差,数据强度的筛选等等;
libpcl I/O:实现数据的输入和输出操作,例如点云数据文件(PCD)的读写;
libpcl segmentation:实现聚类提取,如通过采样一致性方法对一系列参数模型(如平面、
         柱面、球面、直线等)进行模型拟合点云分割提取,提取多边形棱镜内部点云等等;
libpcl surface:实现表面重建技术,如网格重建、凸包重建、移动最小二乘法平滑等;
libpcl register:实现点云配准方法,如ICP、NDT等;
libpcl keypoints:实现不同关键点的提取方法,可用来作为预处理步骤,决定在哪儿提取特征描述符;
libpcl range :实现支持不同点云数据集生成的范围图像。

3、PCL编程风格

请点击-> PCL编程风格

二、PCL中 I/O 模块

//所需头文件
#include <iostream>           //标准 C++ 库中的输入输出类相关头文件
#include <pcl/io/pcd_io.h>    //PCD 读写类相关的头文件
#include <pcl/point_types.h>  //PCL 中支持的点类型头文件

1、PCD文件相关介绍

&&&& PCD文件头 必须用ASCII码来编写。在连接两个不同点云为一个点云之前。要确保两个数据集中字段的类型相同和维度相同。

pcd文件头示例值含义
VERSION0.7指定 PCD 文件版本为 0.7
FIELDSx y z intensity指定点的每一个维度的名称(x, y, z, intensity)
SIZE4 4 4 4以字节为单位指定每个维度的大小(
unsigned char/char 1字节
unsigned short/short 2字节
unsigned int/int/float 4字节
double 8字节
TYPEF F F F用一个字符指定每一个维度的类型(目前支持的类型有:
I 表示有符号类型int8 ( char ), int16 ( short ) , int32 ( int )
U 表示无符号类型uint8 ( unsigned char ), uint16 ( unsigned short ) , uint32 ( unsigned int )
F 表示浮点型 .
COUNT1 1 1 1指定每个维度有多少个元素。例如,x 数据通常有 1 个元素,但像 VFH 这样的特征描述符有 308 个。基本上这是一种在每个点引入 n 维度直方图描述符,并将它们视为单个连续内存块的方法。默认情况下,如果 COUNT 不存在,则所有维度的计数都设置为 1。
WIDTH69088以点数指定点云数据集的宽度。有序点云数据集是对类似于有序的图像(或矩阵)结构的点云的名称,其中数据被分成行和列。此类点云的示例包括来自立体相机或飞行时间相机的数据。有组织的数据集的优点在于,通过了解相邻点(例如像素)之间的关系,最近邻操作的效率要高得多,从而加快了计算速度并降低了 PCL 中某些算法的成本。宽度有两个含义
1)它可以为无序数据集指定点云中的总点数(等于 POINTS,见下文);
2)它可以指定有组织的点云数据集的宽度(一行中的总点数)
HEIGHT1以点数指定点云数据集的高度。高度有两个含义
1)它可以指定一个有序的点云数据集的高度(总行数)
2)对于无序数据集,它被设置为 1(因此用于检查数据集是否有序)。
VIEWPOINT0 0 0 1 0 0 0指定数据集中点的采集视点。VIEWPOINT有可能在不同坐标系之间转换的时候应用,在辅助获取其他特征时,也比较有用,例如曲面法线,在判断方向一致时,需要知道视点的方位。视点信息被指定为平移(txtytz)+ 四元数(qwqxqyqz),默认值如左所示。
POINTS69088指定点云中点的总数。从 0.7 版本开始,它的目的有点多余,所以我们希望在未来的版本中删除它。
DATAbinary指定存储点云数据的数据类型。从 0.7 版本开始,支持两种数据类型:ASCII 和 binary(二进制)。

2、加载 PointCloud 数据,两种方式

(1)
pcl::PointCloud <pcl::PointXYZ>::Ptr cloud( new pcl::PointCloud<pcl::PointXYZ> );
sensor_msgs::PointCloud2 cloud_blob; // PointCloud2 适合版本低的点云文件
pcl::io::loadPCDFile("test_pcd.pcd", cloud_blob);
(2)
pcl::PCDReader reader;	//定义点云读取对象
if (reader.read("test.pcd", *cloud_in) < 0)
{
	PCL_ERROR("\a->点云文件不存在!\n");
	system("pause");
	return -1;
}
 
pcl::fromROSMsg(cloud_blob, *cloud); //  sensor_msgs/PointCloud2 转换为 pcl::PointCloud <T>
PCL中点云数据类型描述
pcl::PointCloud <pcl::PointXYZ> cloudPointXYZ 成员:float x,y,z;
表示了xyz3D信息,可以通过points[i].data[0]或points[i].x访问点X的坐标值
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr( new pcl::PointCloud<pcl::PointXYZ> );相互转换链接(可点击)
cloud = *cloud_ptr;
cloud_ptr = cloud.makeShared();
pcl::PointCloud<pcl::PointXYZI>PointXYZI成员:float x, y, z, intensity;
表示XYZ信息加上强度信息的类型。
pcl::PointCloud<pcl::PointXYZRGB>PointXYZRGB 成员:float x,y,z,rgb;
表示XYZ信息加上RGB信息,RGB存储为一个float。
pcl::PointCloud<pcl::PointXYZRGBA>PointXYZRGBA 成员:float x , y, z; uint32_t rgba;
表示XYZ信息加上RGBA信息,RGBA用32bit的int型存储的。

3、解析rosbag文件得到pcd文件和查看pcd文件

3.1 解析rosbag文件(命令)
// [命令实现] 解析rosbag文件得到带时间戳的.pcd点云数据文件 在rosbag数据包所在文件夹下新建pcd文件夹,新建终端输入如下命令可实现pcd文件的解析。 rosrun pcl_ros bag_to_pcd <*.bag(path)> <topic> <output_directory> 示例如下: rosrun pcl_ros bag_to_pcd lidar.bag /lidar_top ./pcd

3.2 查看.pcd文件

// [命令实现] 
pcl_viewer [pcd文件名]
// sudo apt install pcl-tools

3.3 解析rosbag文件(代码)
以下代码参考:C++读取rosbag并转pcd和bin文件

// [代码实现] 
从rosbag 中提取pcd文件数据(部分代码)
int frame_cnt = 0;
rosbag::Bag bag;
bag.open(path, rosbag::bagmode::Read); //open *.bag
std::vector<std::string> topics; //set topics which you want to read
topics.push_back(std::string("/iv_points2")); //这个是我指定要读取的消息topic
rosbag::View view(bag, rosbag::TopicQuery(topics));; //read defined topics
for (rosbag::MessageInstance const m : view) 
{
    sensor_msgs::PointCloud2::ConstPtr input = m.instantiate<sensor_msgs::PointCloud2>();
    ++frame_cnt;
    if (input == NULL) { continue; }
    bool do_convert = true;
    pcl::PointCloud<pcl::PointXYZI> cloud;//定义转换的点云数据类型
    pcl::fromROSMsg(*input, cloud);
    //...//省略的代码...
}

三、 PCL中REGISTER(配准)模块

1、ICP

ICP算法英文全称为iterative closest point,即最近点迭代算法。该算法用于具有公共点的两幅点云间的匹配或者点云与模型的匹配问题。
ICP算法本质上是基于 最小二乘法 的最优配准方法。该算法重复进行选择对应关系点对, 计算最优刚体变换,直到满足正确配准的收敛精度要求。
请点击–> PCL中的点云配准(Registration)ICP算法

2、NDT

NDT全称为Normal Distributions Transform,正态分布转换,属于用 非线性优化方法 解决Slam中帧间匹配算法中的一种。阅读论文:The Normal Distributions Transform: A New Approach to Laser Scan Matching,熟悉NDT算法的整个流程。
请点击–> 正态分布变换(NDT)配准与无人车定位

X、PCL中类与函数汇总(列表)

PCL类的分类PCL中类以及函数描述
可视化类pcl::visualization::PCLVisualizer

点云视窗类CloudViewer和PCLVisualizer区别
创建普通类对象: pcl::visualization::CloudViewer viewer(“Cloud Viewer”);
创建共享指针对象:boost::shared_ptr< pcl::visualization::PCLVisualizer > viewer(new pcl::visualization::PCLVisualizer(“3D Viewer”));
需包含头文件:#include <pcl/visualization/pcl_visualizer.h>
可视化类中的函数(可点击)
可视化类viewer->registerKeyboardCallback (keyboardEventOccurred, (void*)&viewer);
viewer->registerMouseCallback (mouseEventOccurred, (void*)&viewer);
可视化类pcl::visualization::CloudViewer创建普通类对象:pcl::visualization::CloudViewer viewer(“Cloud Viewer”);
vieweraddPointClout(cloud_ptr, “sample_cloud”);
需包含头文件:#include <pcl/visualization/cloud_viewer.h>
随机颜色pcl::visualization::PointCloudColorHandlerRandom<pcl::PointXYZ>pcl::visualization::PointCloudColorHandlerRandom<pcl::PointXYZ> RandomColor(Cloud(指针类型));
定制颜色pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> custom_color(cloud(指针类型), 0, 0, 255);
模型系数pcl::ModelCoefficients指针类型(两种:Ptr,ConstPtr):pcl::ModelCoefficients::Ptr coefficients( new pcl::ModelCoefficients );
创建分割时所需要的模型系数对象,coefficients,
需包含头文件:#include <pcl/ModelCoefficients.h>
点数据索引pcl::PointIndices指针类型(两种:Ptr,ConstPtr):pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
创建分割时,用来保存分割后点云的数据索引
需包含头文件:#include <pcl/PointIndices.h>
聚类提取(分割) 类pcl::SACSegmentation<pcl::PointXYZ >pcl::SACSegmentation<pcl::PointXYZ> seg;
需包含头文件:#include <pcl/segmentation/sac_segmentation.h> //基于采样一致性分割的类的头文件
from官网
pcl::SACSegmentationFromNormals<pcl::PointXYZRGBA, pcl::Normal>初始化对象:pcl::SACSegmentationFromNormals<pcl::PointXYZRGBA, pcl::Normal> seg;
配准函数ICPpcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ>pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp
需包含头文件:#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/icp.h>
配准函数NDT-案例讲解pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ>

pcl::NormalDistributionsTransform< PointSource, PointTarget >
初始化正态分布变换(NDT)from官网:pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;
//设置依赖尺度NDT参数
//为终止条件设置最小转换差异
ndt.setTransformationEpsilon(0.01);
//为More-Thuente线搜索设置最大步长
ndt.setStepSize(0.1);
//设置NDT网格结构的分辨率(VoxelGridCovariance)
ndt.setResolution(1.0);
//设置匹配迭代的最大次数
ndt.setMaximumIterations(35);
// 设置要配准的点云
ndt.setInputCloud(filtered_cloud);
//设置点云配准目标
ndt.setInputTarget(target_cloud);
ndt.align (PointCloudSource &output, const Matrix4 &guess);
需包含头文件:#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/registration/ndt.h> //NDT配准类对应头文件
#include <pcl/filters/approximate_voxel_grid.h> //滤波类对应头文件
#include <pcl/visualization/pcl_visualizer.h>//可视化头文件
#include <boost/thread/thread.hpp>//多线程相关头文件
pcl::PCDReaderpcl::PCDReader reader;
pcl::io::loadPCDFile(“pcd_path”, Cloud(非指针类型));//读入点云数据
pcl::io::savePCDFile<pcl::PointXYZ> (“pcd_path”, cloud_filter(非指针类型));pcl::io::savePCDFile<pcl::PointXYZ> (“demo_filter.pcd”, cloud_filter);
pcl::io::savePCDFileASCIIpcl::io::savePCDFileASCII (“test_pcd.pcd”, cloud(非指针类型));
需包含头文件:#include <pcl/io/pcd_io.h> //PCD读写类相关的头文件
pcl::io::savePCDFileBinary()
pcl::PCDWriterpcl::PCDWriter writer;
pcl::ApproximateVoxelGrid<pcl::PointXYZI>pcl库中的VoxelGrid对点云进行体素化,主要就是创建一个三维体素栅格(就是每个比较小的立方体组成的体素栅格)。
初始化创建对象:pcl::ApproximateVoxelGrid<pcl::PointXYZI> avg;
直通滤波类pcl::PassThrough<pcl::PointXYZ>初始化滤波器对象:pcl::PassThrough<pcl::PointXYZ> pass;
成员函数:
pass.setInputCloud(cloud); //设置待滤波的点云
pass.setFilterFieldName(“z”); //设置在Z轴方向上进行滤波
pass.setFilterLimits(0, maxPt.z - 12); //设置滤波范围(从最高点向下12米去除)
pass.setFilterLimitsNegative(false); //保留
pass.filter(cloud_filter(非指针类型)); //滤波并存储
pcl几种滤波方法点云滤波方法:直通滤波器、体素滤波器、统计滤波器、条件滤波器、半径滤波器。
pcl::NormalEstimation< PointInT, PointOutT >//创建法线估计对象:pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne1;
所需头文件:#include <pcl/features/normal_3d.h>
pcl::search::KdTree<pcl::PointXYZ>::Ptr
它的子类:pcl::KdTreeFLANN<pcl::PointXYZ>
// 定义初始化KDTree对象:pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
所需头文件:#include <pcl/search/kdtree.h>
保存点云索引pcl::PointIndicespcl::PointIndices inliers;
pcl::ExtractIndices<pcl::PointXYZ>//实例化一个提取对象:pcl::ExtractIndices<pcl::PointXYZ> extract;
需包含头文件:#include <pcl/filters/extract_indices.h>
pcl::ProjectInliers<pcl::PointXYZ>//创建投影滤波对象: pcl::ProjectInliers<pcl::PointXYZ> proj;
作用:点云投射;
需包含头文件:#include <pcl/filters/project_inliers.h>
聚类提取pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary>pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundEst;
同时,需要pcl::NormalEstimation先计算法线
需包含头文件:#include <pcl/features/boundary.h>
滤波器移除离群点pcl::StatisticalOutlierRemoval<pcl::PointXYZ >创建滤波器对象:pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
需包含头文件:#include <pcl/filters/statistical_outlier_removal.h> //滤波相关
void pcl::fromROSMsg ( const sensor_msgs::PointCloud2 & cloud, pcl::PointCloud< T > & pcl_cloud )
需包含头文件:#include <pcl_conversions/pcl_conversions.h>
#include <pcl/conversions.h>
#include <pcl_ros/transforms.h>
pcl::toROSMsg ( pcl::PointCloud<pcl::PointXYZ>, sensor_msgs::PointCloud2 );
pcl::Grabber采集的类,此类还有很多派生类
void pcl::transformPointCloud ( const pcl::PointCloud< PointT > & cloud_in, pcl::PointCloud< PointT > & cloud_out, const Eigen::Matrix< Scalar, 4, 4 > & transform, bool copy_all_fields = true )应用由4x4矩阵定义的刚性变换。from官网
点云降采样点云降采样分为:(1)体素降采样(2) 随机降采样(3)均匀降采样
VoxelGrid体素采样(内含三个类的区别)pcl::VoxelGrid<pcl::PointXYZ>from官网,pcl库中的VoxelGrid对点云进行体素化,主要就是创建一个三维体素栅格(就是每个比较小的立方体组成的体素栅格)。在每个体素(三维立方体)里面,求取该立方体内的所有点云重心点来代表这个立方体的表示,以此达到下采样的目的。
VoxelGrid体素采样pcl::VoxelGrid<pcl::PCLPointCloud2>其中,举例:
pcl::VoxelGrid<pcl::PCLPointCloud2> voxel_filter; // 创建滤波器对象
voxel_filter.setLeafSize (0.01f, 0.01f, 0.01f); //设置滤波时创建的体素大小为1cm立方体(单位:米)
VoxelGrid体素采样pcl::ApproximateVoxelGrid<pcl::PointXYZ>from官网
pcl::copyPointCloud()
另种用法:pcl::copyPointCloud<Velodyne::Point>(*edges_cloud, inliers2, *pattern_cloud)
改变点云中点的类型用法,请点击 && 用法from官网
欧式聚类分割类 &&–概念原理 -&&-from官网讲解pcl::EuclideanClusterExtraction< PointT > 需包含头文件:#include <pcl/segmentation/extract_clusters.h>
from官网
计算欧式距离pcl::euclideanDistance( const PointType1 & p1, const PointType2 & p2 )计算已知两个点的欧式距离。
from官网
求两线的交点bool pcl::lineWithLineIntersection ( const Eigen::VectorXf & line_a, const Eigen::VectorXf & line_b, Eigen::Vector4f & point, double sqr_eps = 1e-4 )获取空间中两条三维直线的交点。
需包含头文件:#include <pcl/common/impl/intersections.hpp>
pcl::SampleConsensusModelPlane< PointT >用于定义三维平面分割的模型。
所需头文件:#include <pcl/sample_consensus/sac_model_plane.h>
pcl::console::setVerbosityLevel()setVerbosityLevel用于设置控制台输出的信息。(pcl::console::L_ALWAYS)不会输出任何信息; L_DEBUG会输出DEBUG信息; L_ERROR会输出ERROR信息。from官网
pcl::getMinMax3D()Get the minimum and maximum values on each of the 3 (x-y-z) dimensions in a given pointcloud.

XXX、多库合作知识(额外知识)

1、ROS消息数据与PCL数据相互转换

在ROS中表示点云的数据结构有:sensor_msgs::PointCloud, sensor_msgs::PointCloud2。
pcl::PointCloud 关于PCL在ros数据的结构,具体的介绍可查看 此链接(fromROS官网)
关于sensor_msgs::PointCloud2 和 pcl::PointCloud<PointT>之间的转换,使用
pcl::fromROSMsg()pcl::toROSMsg()
sensor_msgs::PointCloud 和 sensor_msgs::PointCloud2之间的转换,使用
sensor_msgs::convertPointCloud2ToPointCloudsensor_msgs::convertPointCloudToPointCloud2

2、拼接点云

请点击–> PCL系列——拼接两个点云

3、PCL的指针说明

请点击–> PCL之指针Ptr详解

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PCL (Point Cloud Library) 是一个非常强大的点云处理库,它提供了丰富的功能来处理、分析和可视化点云数据。下面将从学习教程的角度来介绍PCL C++ 学习教程。 在学习PCL C++学习教程之前,我们先了解一下PCL的基础知识。PCL是一个开源项目,可以在Windows、Linux和Mac OS等操作系统上使用。它提供了常见的点云数据类型、滤波、分割、配准、特征提取和重建等功能。此外,PCL还有一个强大的可视化模块,可以方便地实时显示点云数据。 对于初学者而言,可以从PCL官方网站上的教程入手。官方网站提供了完整的文档和示例代码,可供学习者参考。此外,还有一些博客和视频教程可以帮助学习者更好地掌握PCL的使用。 学习PCL C++,需要一定的编程基础知识,例如掌握C++语言、面向对象编程和基本的算法理论等。在学习过程中,可以按照如下步骤进行: 1. 安装PCL库:根据自己的操作系统选择合适的安装方式,到PCL官方网站下载安装包并按照指南进行安装。 2. 学习PCL的基础知识:首先熟悉PCL的常见数据类型,例如点云表示和常见的PCL数据结构。然后学习如何读取和保存点云数据,以及基本的点云操作和可视化。 3. 学习PCL的模块功能:PCL库包含多个模块,例如滤波、分割、配准、特征提取和三维重建等。可以针对自己的需求选择相应的模块进行学习,并掌握它们的基本原理和使用方法。 4. 练习和实践:通过完成一些PCL的实际项目,例如点云配准、目标检测或三维重建等,来巩固所学的知识。 总之,学习PCL C++需要一定的时间和耐心,通过实践和不断学习,逐渐掌握PCL的使用技巧。希望以上简要的回答能对你理解PCL C++学习教程有所帮助。 ### 回答2: PCL(Point Cloud Library)是一个开源的计算机视觉库,主要用于处理和分析点云数据。它提供了许多功能强大的算法和工具,可以帮助开发人员在点云处理方面进行快速开发。 PCL C学习教程是PCL官方提供的一份入门教程,旨在帮助初学者快速上手PCL C的开发。该教程主要介绍了PCL的基本概念和使用方法,并提供了一些常见的点云处理算法的示例代码。通过学习PCL C学习教程,我们可以了解PCL的基本功能和使用技巧,并且可以开始进行简单的点云处理任务。 在学习PCL C的过程中,我们需要掌握一些基础知识,比如点云的表示和存储方式、点云的滤波和分割方法、点云的特征提取和匹配算法等等。PCL C学习教程提供了详细的解释和示例代码,以帮助我们理解和运用这些基础知识。 此外,PCL C学习教程还介绍了一些常见的点云处理应用场景,比如目标检测、点云配准和重建等。通过学习这些应用场景,我们可以了解到PCL C在不同领域的应用和相关的算法思想。 总结来说,PCL C学习教程是学习和使用PCL的入门指南,通过学习教程中的内容,我们可以掌握PCL C的基础知识和技能,并且开始进行简单的点云处理任务。 ### 回答3: PCL(Point Cloud Library)是一个用于点云数据处理的开源库。学习PCL可以帮助我们更好地理解和处理点云数据,从而在计算机视觉、机器人领域等方面开展相关工作。 学习PCL可以从以下几个方面入手。首先,了解PCL的基本概念和原理是非常重要的。PCL涵盖了点云数据获取、滤波、特征提取、配准等算法,了解这些基本概念是进行更高级别的数据处理的基础。 其次,学习PCL的使用方法。PCL提供了丰富的功能库和示例代码,通过实践使用可以更好地掌握PCL的各项功能。可以通过看官方文档、阅读教程、查阅论坛等方式学习PCL的使用方法。 再次,尝试应用PCL解决实际问题。通过完成一些小项目,如点云数据的滤波、分割、配准等任务,可以锻炼我们对PCL的熟练程度,并将PCL应用于实际工程中。 最后,与其他PCL爱好者交流学习。在互联网上可以找到很多与PCL相关的讨论组、社区和论坛,与其他使用PCL的人交流经验、分享学习心得,可以提高我们的学习效果。 总之,学习PCL需要理解基本概念和原理、掌握使用方法、应用于实践项目以及与他人交流学习。希望以上建议对学习PCL有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值