02-点云输入/输出(I/O)*¶
数据文件格式¶
一个典型的PCD文件如下:
# .PCD v.5 - Point Cloud Data file format
VERSION .5
FIELDS x y z
SIZE 4 4 4
TYPE F F F
COUNT 1 1 1
WIDTH 397
HEIGHT 1
POINTS 397
DATA ascii
0.0054216 0.11349 0.040749
-0.0017447 0.11425 0.041273
-0.010661 0.11338 0.040916
0.026422 0.11499 0.032623
0.024545 0.12284 0.024255
0.034137 0.11316 0.02507
- 格式描述
-
VERSION .5 指定PCS文件版本
-
FIELDS x y z 指定一个点的每一个维度和字段名字,例如
FIELDS x y z # XYZ data
FIELDS x y z rgb # XYZ + colors
FIELDS x y z normal_x normal_y normal_z # XYZ + surface normals
-
SIZE 4 4 4 指定每一个维度的字节数大小
-
TYPE F F F 指定每一个维度的类型,
I
表示int,U
表示uint,F
表示浮点 -
COUNT 1 1 1 指定每一个维度包含的元素数,如果没有COUNT,默认都为1
-
WIDTH 397 点云数据集的宽度
-
HEIGHT 1 点云数据集的高度
-
VIEWPOINT 0 0 0 1 0 0 0 指定点云获取的视点和角度,在不同坐标系之间转换时使用(由3个平移+4个四元数构成)
-
POINTS 397 总共的点数(显得多余)
-
DATA ascii 存储点云数据的数据类型,ASCII和binary
- 其他格式
PCD 不是第 一个支持 3D点云数据的文件类型,尤其是计算机图形学和计算几何学领域,已经创建了很多格式来描述任意多边形和激光扫描仪获取的点云。常见的有下面几种格式:
- PLY 是一种多边形文件格式 , 由 Stanford 大学的 Turk 等人设计开发;
- STL 是 3D Systems 公司创建的模型文件格式,主要应用于 CAD 、 CAM领域 ;
- OBJ 是从几何学上定义的文件格式,首先由 Wavefront Technologies 开发;
- 其他格式
以上所有格式都有其优缺点,因为他们是在不同时期为了满足不同的需求所创建的,那时很多当今流行的传感器和算法都还没有发明。
PCL 中 PCD 文件格式的正式发布是 0.7版本,之前也有0.5,0.6版本。
以及更多关于PCD文件格式详情
反序列化¶
我们可以对一个点云进行反序列化操作,将之保存到PointCloud对象中:load_pcd.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main(int argc, char **argv) {
// 准备pcl::PointXYZ类型的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 将pcd中的数据加载到cloud中
if (pcl::io::loadPCDFile<pcl::PointXYZ>("./data/bunny.pcd", *cloud) == -1) //* load the file
{
PCL_ERROR ("Couldn't read file bunny.pcd \n");
return (-1);
}
std::cout << "Loaded "
<< cloud->width * cloud->height
<< " data points from test_pcd.pcd with the following fields: "
<< 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;
return (0);
}
序列化¶
以下代码,随机生成了5个点,并将之以ASCII形式保存(序列化)在test_pcd.pcd
文件中:save_pcd.cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main(int argc, char **argv) {
pcl::PointCloud<pcl::PointXYZ> cloud;
// Fill in the cloud data
cloud.width = 5;
cloud.height = 1;
cloud.is_dense = false;
cloud.points.resize(cloud.width * cloud.height);
std::cout << rand() << std::endl;
std::cout << rand() / (RAND_MAX + 1.0f) << std::endl;
std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl;
// 随机生成5个点
for (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);
}
pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);
std::cerr << "Saved " << cloud.points.size() << " data points to test_pcd.pcd." << std::endl;
for (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;
return (0);
}
- 输出的文件内容如下
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z
SIZE 4 4 4
TYPE F F F
COUNT 1 1 1
WIDTH 5
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 5
DATA ascii
-0.3974061 -0.47310591 0.29260206
-0.73189831 0.66710472 0.44130373
-0.73476553 0.85458088 -0.036173344
-0.46070004 -0.2774682 -0.91676188
0.1837492 0.96880913 0.5120554
有时为了节省空间,提高读写效率,还会以binary的格式进行序列化,即将save操作改为
pcl::io::savePCDFileBinary("test_pcd_binary.pcd", cloud);
// 或
pcl::io::savePCDFile("test_pcd_binary.pcd", cloud, true);
- 此时输出的内容如下:
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z
SIZE 4 4 4
TYPE F F F
COUNT 1 1 1
WIDTH 5
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 5
DATA binary
�x˾�:��ϕ>�];�`�*?���>�<���Z?�*����P���j��(<>�x??
注意11行的DATA类型为binary,最后的内容由于是以二进制形式保存,故而不可以直接看到值,需要用程序读取。