PCD文件操作
本篇文章中会介绍对PCD文件的读写操作,点云的合并
操作类型
1. 读操作
头文件:
#include <pcl/io/pcd_io.h>
关键函数:从硬盘加载一个PCD格式的模板点云
template<typename PointT> inline int
loadPCDFile (const std::string &file_name, pcl::PointCloud<PointT> &cloud)
- 输入输出参数:
- file_name[in]:选择加载的点云文件名
- cloud[out]:加载了点云数据的模板点云.因为loadPCDFiles是一个模板函数,PointT表示加载的点云类型。当然这里可以改为之前章节中提到的所有点的类型。
- 返回值[out]:int类型,0表示成功,-1代表加载失败
举例:
pcl::io::loadPCDFile("Box.pcd", *pPointCloudIn);
2. 写操作
头文件:
#include <pcl/io/pcd_io.h>
关键函数:将一个模板点云保存为PCD格式文件写入硬盘
template<typename PointT> inline int
savePCDFile (const std::string &file_name, const pcl::PointCloud<PointT> &cloud, bool binary_mode = false)
- 输入输出参数:
- file_name[in]:将要写入的文件名
- cloud[in]:将要写的模板点云
- binary_mode:PCD模式,默认是false表示是以ASCII码存储PCD文件,否则是以二进制模式存储。
- 返回值[out]:int类型,0表示成功,-1代表存储失败
举例:
pcl::io::savePCDFile("save.pcd", *pPointCloudIn);
3. 合并点云
合并点云分为两种类型:一是两个点云数据集的字段类型和维度相同,合并之后点云只是点的数量增加了;二是两个点云数据集的字段类型或维度不同,但是点的数量相同,合并之后相当于扩展了字段或维度,例如点云A是N个点的XYZ点集,点云B是N个点的RGB点,则连接两个字段形成的点云C是N个XYZRGB类型。
3.1 扩展点的数量
关键函数:扩展点云数量
inline const PointCloud
operator + (const PointCloud& rhs)
举例:
cloud_c = cloud_a + cloud_b;
3.2 扩展点云字段或维数
关键函数:扩展点云字段或维数
template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
pcl::concatenateFields (const pcl::PointCloud<PointIn1T> &cloud1_in,
const pcl::PointCloud<PointIn2T> &cloud2_in,
pcl::PointCloud<PointOutT> &cloud_out)
- 输入输出参数:
- cloud1_in[in]:合并的第一个点云
- cloud2_in[in]:合并的第二个点云
- cloud_out[out]:输出点云
一定要确定cloud1_in和cloud2_in点云数目相同,并且cloud_out的字段包含两个输入点云的所有字段。
举例:
// 一个PointXYZ类型的点云和一个Normal类型的点云合并为一个PointNormal类型点云
pcl::concatenateFields(cloud_c, cloud_normal, cloud_xyznormal);
程序
/*
* 功能: I/O操作,包括PCD文件读写,点云合并
*/
#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int main()
{
// 1. 扩展点云的点数
pcl::PointCloud<pcl::PointXYZ> cloud_a, cloud_b, cloud_c; // 保证合并的两个点云字段维数相同
// 初始化点云
cloud_a.width = cloud_b.width = 10;
cloud_a.height = cloud_b.height = 1; // 无序点云,每个点云大小为10
cloud_a.points.resize(cloud_a.width*cloud_a.height);
cloud_b.points.resize(cloud_b.width*cloud_b.height); // 不仅要初始化width,height而且还有points
// 随机赋予点的XYZ值
for (size_t i = 0; i < cloud_a.points.size(); ++i)
{
cloud_a.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_a.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_a.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
for (size_t i = 0; i < cloud_b.points.size(); ++i)
{
cloud_b.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_b.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_b.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
std::cerr << "Cloud A(size : " << cloud_a.size() << "):" << std::endl;
for (size_t i = 0; i < cloud_a.points.size(); ++i)
std::cerr << " " << cloud_a.points[i].x << " " << cloud_a.points[i].y << " " << cloud_a.points[i].z << std::endl;
std::cerr << "Cloud B(size : " << cloud_b.size() << "):" << std::endl;
for (size_t i = 0; i < cloud_b.points.size(); ++i)
std::cerr << " " << cloud_b.points[i].x << " " << cloud_b.points[i].y << " " << cloud_b.points[i].z << std::endl;
cloud_c = cloud_a + cloud_b;
std::cerr << "Cloud C(size : " << cloud_c.size() << "):" << std::endl;
for (size_t i = 0; i < cloud_c.points.size(); ++i)
std::cerr << " " << cloud_c.points[i].x << " " << cloud_c.points[i].y << " " << cloud_c.points[i].z << " " << std::endl;
// 2. 扩展点云的字段或维数
pcl::PointCloud<pcl::Normal> cloud_normal;
pcl::PointCloud<pcl::PointNormal> cloud_xyznormal;
cloud_normal.width = cloud_c.width;
cloud_normal.height = cloud_c.height;
cloud_normal.points.resize(cloud_normal.width*cloud_normal.height);
cloud_xyznormal.width = cloud_c.width;
cloud_xyznormal.height = cloud_c.height;
cloud_xyznormal.points.resize(cloud_xyznormal.width*cloud_xyznormal.height); // 保证两个点云数量相同
for (size_t i = 0; i < cloud_normal.points.size(); ++i)
{
cloud_normal.points[i].normal[0] = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_normal.points[i].normal[1] = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_normal.points[i].normal[2] = 1024 * rand() / (RAND_MAX + 1.0f);
}
// 关键函数
pcl::concatenateFields(cloud_c, cloud_normal, cloud_xyznormal);
std::cerr << "Cloud RGB(size : " << cloud_normal.size() << "):" << std::endl;
for (size_t i = 0; i < cloud_normal.points.size(); ++i)
std::cerr << " " << cloud_normal.points[i].normal_x << " " << cloud_normal.points[i].normal_y << " " << cloud_normal.points[i].normal_z << " " << std::endl;
std::cerr << "Cloud XYZRGB(size : " << cloud_xyznormal.size() << "):" << std::endl;
for (size_t i = 0; i < cloud_xyznormal.points.size(); ++i)
std::cerr << " " << cloud_xyznormal.points[i].x << " " << cloud_xyznormal.points[i].y << " " << cloud_xyznormal.points[i].z << " " << cloud_xyznormal.points[i].normal_x << " " << cloud_xyznormal.points[i].normal_y << " " << cloud_xyznormal.points[i].normal_z << " " << std::endl;
// 3. 保存PCD文件格式
std::cout << "Save PCD! " << pcl::io::savePCDFile("save.pcd", cloud_xyznormal) << std::endl;
// 4. 读取PCD文件格式
std::cout << "Load PCD! " << pcl::io::loadPCDFile("save.pcd", cloud_xyznormal) << std::endl;
std::system("pause");
return 0;
}