由于项目涉及点云目标识别和定位等相关内容,因此开始接触基于PCL的三维点云处理。对于PCL,官方解释是:PCL(Point Cloud Library,点云库)是吸收了前人点云相关研究的基础上建立起来的大型跨平台开源C++编程库,它实现了大量点云相关的通用算法和高效数据结构,涉及点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。本系列文章主要记录关于PCL点云库的学习过程。
本小节主要是关于点云文件格式与IO操作的相关内容。PCL中的IO库提供了点云文件输入输出相关的操作类,IO模块利用50多个类与30多个函数来实现点云的获取、读入、存储等。
一 点云文件格式
3D点云数据的文件格式包括多种,包括pcd、ply、txt等。本节主要基于PCL的内部文件格式——PCD,针对其文件格式以及它在点云库PCL中应用的方法。
1.1 文件头格式
每一个PCD文件都包含一个文件头来确定和声明文件中存储的点云数据的某种特性。PCL正式发布的PCD文件格式是0.7版本,以一个实际的PCD文件举例,说明0.7版本之后,PCD文件头包含的这些字段。
VERSION 0.7 //指定PCD文件版本
FIELDS x y z //指定一个点的维度和字段的名字,此处表示点云维度是XYZ
SIZE 4 4 4 //用字节数指定每一个维度的大小
TYPE F F F //用一个字符指定每一个维度的类型,此处F表示浮点类型(另外还有I表示有符号类型,U表示无符号类型)
COUNT 1 1 1 //每一个维度包含的元素数目,默认情况下为1
WIDTH 6411 //用点的数量表示点云数据集的宽度
HEIGHT 1 //用点的数量表示点云数据集的高度
VIEWPOINT 0 0 0 1 0 0 0 //指定数据集中点云的获取视点,在不同坐标系之间转换会用到,或者在辅助获取其他特征,比如获取曲面法线,判断方向一致性时会用到视点。
POINTS 6411 //点云中点的总数
DATA ascii //指定存储点云的数据类型
补充说明,若在文件头中,有如下字段说明:
WIDTH 640 //每行有640个点
HEIGHT 480 //640行*480列=307200个点
则表示有序点云,也就是类似于图像或者说矩阵的结构,分为行和列。
WIDTH 307200
HEIGHT 1
表示为无序点云,它有307200个点。因此,可以通过检查HEIGHT的值来判断点云属于哪种类型。
相比于无序点云,有序点云的优势在于,可以更高效地处理目标点与邻域之间的关系,可以实现加速计算并降低PCL中某些算法的成本。
1.2 数据存储类型
以上PCD文件中,在DATA行(包含)之前的所有行均为文件头,且必须按照固定顺序进行指定,不同指定之间用换行隔开。在文件头中DATA的下一行开始,就是点云的数据部分了,在0.7版本中,PCD文件用ASCII和二进制两种模式存储数据。若以ASCII形式,每一个点占据一个新行。从PCL1.0.1开始,用”nan”表示NaN无效点,即该点的值不存在或者非法。
二、PCD文件IO操作
由于pcd点云数据格式有它独特的优势,因此本项目基于此继续研究。首先是对点云数据的IO处理,包括从PCD文件读取点云数据和写入点云数据。
依赖头文件如下:
#include <iostream>
#include <pcl/io/pcd_io.h> //PCD读写类相关的头文件
#include <pcl/point_types.h> //PCL中支持的点类型头文件
2.1 PCD文件的读取操作
法一:使用loadPCDFile
读取milk.pcd文件,若文件不存在,返回错误。此处读取数据采用的是相对路径。
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("milk.pcd", *cloud) == -1)
{
std::cout << "Cloud reading failed." << std::endl;
return (-1);
}
法二:使用reader
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read("E://box1.pcd", *cloud);
2.2 PCD文件的写入操作
法一:使用writer
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ>("test_pcd.pcd", *cloud, false);
法二:使用savePCDFileASCII
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::io::savePCDFileASCII("test_pcd.pcd",cloud);
下面截图了目标物的三维点云数据的可视化结果,包括PointXYZ和PointXYZI两种数据格式。
原始图像:
目标物的PointXYZ数据类型的点云:
目标物的PointXYZI数据类型的点云:
总结:本小节简单地介绍了点云文件格式和IO操作,为之后点云数据的进一步处理垫定基础。才疏学浅,如有不妥之处,望指正。