0 点云数据的输入与输出
前言
本文是PCL调库学习的第一篇的文章,之所以打算写一个这样的系列,最主要的还是为了自己日后复习,或者做项目时,能够快速的了解某个函数或功能的使用
文章所有代码均参考于pcl官网,对于某一种库的学习,很多时候,官方提供给我们的资料就已经足够丰富了,并且还是一手资料。只是可能因为是英文的所以劝退了很多人,但如果你抱着同时学习英语的态度来阅读,可能就会有两份收货,再者现在翻译软件这么多,直接整个全文翻译,即使翻译结果不那么准确,只要加上一点点自己的理解也还是能够将理解大致的意思的,so let’s get it~
温馨提示
本系列文章,较少涉及算法原理的讲解,绝大部分内容的是如何实现某一个功能,以及某些API的讲解,每篇文章都附有完整代码以及详细的注释,都能直接运行。
俗话说:是骡子是马拉出来溜溜,对于某段程序或者某个函数,最直观的感受就是运行起来看效果,在清楚函数的每个参数所代表的意思后,改变参数,再来验证效果。
这种学习方法对于想要快速学习一种库的使用,或者实现某个功能,做某个项目是一种非常好的方式。当然,如果想要实现更好的效果,就得需要对算法背后的原理进行理解,自己通过现有的积木一块一块搭建自己的小屋(函数)。
最后,该系列文章也相当于是自己学习PCL的一个总结,认识都还比较浅薄,如有错误欢迎指正,大家一起交流进步~
参考资料:
https://pointclouds.org/
https://github.com/PointCloudLibrary/pcl/tree/pcl-1.10.1/doc/tutorials/content/sources
https://pcl.readthedocs.io/projects/tutorials/en/latest/index.html
点云库PCL从入门到精通–郭浩
编辑器vs2019 库版本信息:pcl-1.10
0.1 从PCD文件中读取点云数据
实现功能
主要实现了简单的PCD文件读取
关键API
int pcl::io::loadPCDFile (const std::string& file_name, //输入参数:待加载的文件名
pcl::PointCloud< PointT > & cloud //输出参数:用于保存加载进来的点云数据的对象
)
//返回值 == -1 时,表示读取失败
//补充另外一个读取PCD文件的函数
int pcl::PCDReader::read (const std::string& file_name, //输入参数:待加载的文件名
pcl::PointCloud<PointT>& cloud, //输出参数:用于保存加载进来的点云数据的对象
const int offset = 0 //输入参数:偏移量,默认为零
)
完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main(int argc, char** argv)
{
//创建一个保存点云的对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
//从文件中加载点云
if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\code\\pcl\\PointCloudData\\20210506\\1.pcd", *cloud) == -1) //* load the file
{
PCL_ERROR("Couldn't read file test_pcd.pcd \n");
return (-1);
}
std::cout << "Loaded "
<< cloud->width * cloud->height
<< " data points from test_pcd.pcd with the following fields: "
<< std::endl;
//打印点云
for (std::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);
}
0.2 向PCD文件中写入点云数据
实现功能
随机生成了五个点云数据,并将其写入文件中,保存在当前目录下
关键API
//如果文件不存在则创建文件,如果文件存在,则将文件内容覆盖
template<typename PointT >
int pcl::io::savePCDFileASCII(const std::string& file_name, //输入参数:输出文件的文件名
const pcl::PointCloud<PointT>& cloud //输入参数:待保存的点云数据的点云对象
)
//同样有另外一个写入数据的API
template<typename PointT >
int pcl::PCDWriter::write(const std::string& file_name, //输入参数:输出文件的文件名
const pcl::PointCloud<PointT>& cloud, //输入参数:待保存的点云数据的点云对象
const bool binary = false //输入参数:是否以二进制的格式写入文件,默认为否
)
完整代码
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main(int argc, char** argv)
{
srand(time(NULL)); //随机数种子
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); //确定点云的大小
//生成5个0~1的随机数,并存入cloud中
for (std::size_t i = 0; i < cloud.points.size(); ++i)
{
cloud.points[i].x = rand() / (RAND_MAX + 1.0f);
cloud.points[i].y = rand() / (RAND_MAX + 1.0f);
cloud.points[i].z = rand() / (RAND_MAX + 1.0f);
}
//将cloud中的点云数据保存至test_pcd.pcd文件中
pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);
std::cerr << "Saved " << cloud.points.size() << " data points to test_pcd.pcd." << 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;
return (0);
}
运行结果
程序工作目录下也出现了test_pcd.pcd文件