从PCD文件中读取与保存点云文件

2023-11-21 04:40
文章标签 读取 保存 点云 pcd

本文主要是介绍从PCD文件中读取与保存点云文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        序列化和反序列化是将数据结构或对象转换为字节流(序列化)以及将字节流还原为数据结构或对象(反序列化)的过程。
        在计算机科学中,当我们需要将数据从内存中保存到磁盘或通过网络传输时,通常需要进行序列化操作。序列化将数据结构或对象转换为一个字节流的形式,以便能够进行持久化存储或传输。这样,在需要时就可以从字节流中还原出原始的数据结构或对象。
        反序列化则是将之前序列化过的字节流重新转换为原始的数据结构或对象,使其可以被系统再次使用。
        在点云领域中,序列化和反序列化操作允许我们将点云数据保存到文件中或通过网络传输,并在需要时重新加载点云数据。这对于点云处理、共享和传输非常有用。

        PCL(点云库)提供了一些函数来执行点云数据的序列化和反序列化操作,例如 pcl::io::savePCDFile()pcl::io::loadPCDFile()。这些函数将点云数据转换为二进制格式并保存到文件中,然后可以通过读取文件并解析字节流来还原点云数据。
        总结而言,序列化和反序列化操作是将数据结构或对象转换为字节流以及将字节流还原为原始数据结构或对象的过程,用于持久化存储、传输和再利用数据。

        字节流可以有多种不同的表现形式,其中包括二进制表示。
        二进制表示:字节流最常见的表现形式是二进制表示,即将数据转换为由 0 和 1 组成的位序列。在计算机系统中,所有的数据最终都以二进制形式存储和处理。
        文本表示:字节流也可以被解释为字符序列,具体的解释方式取决于所使用的字符编码。例如,在 ASCII 编码中,每个字节对应一个字符;而在 Unicode 编码中,每个字符可能需要多个字节进行表示。
        十六进制表示:为了方便可读性和显示,字节流经常以十六进制的形式进行表示。在十六进制表示中,每个字节用两个十六进制数字(0-9, A-F)表示。
        除了上述常见的表现形式,字节流还可以通过其他编码和压缩算法来进行表示,例如 Base64 编码、gzip 压缩等。
        在点云领域中,点云数据通常以二进制形式表示,因为它们包含大量的浮点数和坐标值,这些数据可以直接以二进制形式存储和处理。
        总结而言,字节流可以以多种不同的表现形式存在,包括二进制表示、文本表示和十六进制表示。具体的表现形式取决于数据的使用场景和编码方式。

        从文件中加载点云数据是反序列化的过程,而将点云保存到文件中是序列化的过程。具体而言:
        序列化:将数据结构或对象转换为字节流的过程。在点云库中,将点云数据转换为二进制形式,并将其写入磁盘文件,是一种序列化操作。这个过程将点云数据序列化为字节流并持久化存储到文件中。
        反序列化:将字节流还原为原始的数据结构或对象的过程。在点云库中,从磁盘文件中读取二进制数据,并将其解析为点云数据结构,是一种反序列化操作。这个过程将之前序列化的字节流反序列化为原始的点云数据。

反序列化:

#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/octants.pcd", *cloud) == -1) //* load the file{PCL_ERROR("Couldn't read file octants.pcd \n");return (-1);}std::cout << "Loaded "<< cloud->width * cloud->height<< " data points from octants.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文件中

#include <pcl/visualization/cloud_viewer.h>
#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 datacloud.width = 5000;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("../output_data/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;
*/pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_show(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPCDFile("../output_data/test_pcd.pcd", *cloud_show) == -1) {PCL_ERROR("Couldn't read file  \n");return (-1);}else {pcl::visualization::CloudViewer viewer("simple cloud viewer");viewer.showCloud(cloud_show);while (!viewer.wasStopped()){// todo::}}return (0);
}

 输出的文件内容如下:

 有时为了节省空间,提高读写效率,还会以binary的格式进行序列化,即将save操作改为

pcl::io::savePCDFileBinary("../output_data/test_pcd_Binary.pcd", cloud);
pcl::io::savePCDFile("../output_data/test_pcd.pcd", cloud, true);

此时输出的内容如下:

ps:11行的DATA类型为binary,最后的内容由于是以二进制形式保存,故而不可以直接看到值,需要用程序读取。

输出文件大小对比:

 


         cloud.is_dense = false;是对点云数据结构中的 is_dense 属性进行设置。这个属性用于指示点云是否密集(dense)。
        当 is_dense 被设置为 false 时,表示点云是非密集的。这意味着点云中可能存在一些缺失或无效的点,例如由于传感器噪声、遮挡或其他原因导致的点云数据不完整。在非密集的点云中,某些点的位置信息可能会丢失或不准确。
        相反,当 is_dense 被设置为 true 时,表示点云是密集的。这意味着点云中的每个点都有有效和准确的位置信息。
        通过设置 cloud.is_dense = false;,你指示该点云是非密集的,即它可能包含缺失或无效的点。


std::cout << rand() << std::endl;
std::cout << rand() / (RAND_MAX + 1.0f) << std::endl;
std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl;

         这段代码使用了 C++ 的随机数生成函数 rand() 和输出流 std::cout,并进行了一些计算和打印操作。

  • std::cout << rand() << std::endl; 打印一个随机整数。rand() 函数会生成一个范围在 0 到 RAND_MAX 之间的整数,其中 RAND_MAX 是库定义的最大随机数值。该行代码将随机整数输出到标准输出流 std::cout 中,并通过 std::endl 进行换行。
  • std::cout << rand() / (RAND_MAX + 1.0f) << std::endl; 打印一个介于 0 和 1 之间的随机浮点数。这里使用 (RAND_MAX + 1.0f)RAND_MAX 转换为浮点数,然后用 rand() 除以该值来得到一个范围在 0 到 1 之间的随机浮点数。该行代码将随机浮点数输出到标准输出流中,并通过 std::endl 进行换行。

  • std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl; 打印一个介于 0 和 1024 之间的随机整数。与上一行类似,这里先将 RAND_MAX 转换为浮点数,然后用 rand() 产生的随机数乘以 1024,再除以 (RAND_MAX + 1.0f) 来得到一个范围在 0 到 1024 之间的随机整数。该行代码将随机整数输出到标准输出流中,并通过 std::endl 进行换行。


#include <iostream> //标准c++库输入输出相关头文件
#include <pcl/io/pcd_io.h> // pcd读写相关头文件
#include <pcl/point_types.h> // pcl中支持的点类型头文件// 定义点云格式,具体见下章
typedef pcl::PointXYZ PointT;int main(int argc, char** argv)
{// 定义点云pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);// 读取点云,失败返回-1if (pcl::io::loadPCDFile<PointT>("../input_cloud/20230605_133316.pcd", *cloud) == -1){PCL_ERROR("couldn't read file\n");return (-1);}// 输出点云大小 cloud->width * cloud->heightstd::cout << "点云大小:" << cloud->size() << std::endl;// 保存点云文件pcl::io::savePCDFile("../output_cloud/01_saveName_2.pcd", *cloud);system("pause"); // windows命令行窗口暂停return (0);
}

参考:02-点云输入/输出(I/O)

这篇关于从PCD文件中读取与保存点云文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/399865

相关文章

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

matlab读取NC文件(含group)

matlab读取NC文件(含group): NC文件数据结构: 代码: % 打开 NetCDF 文件filename = 'your_file.nc'; % 替换为你的文件名% 使用 netcdf.open 函数打开文件ncid = netcdf.open(filename, 'NC_NOWRITE');% 查看文件中的组% 假设我们想读取名为 "group1" 的组groupName

argodb自定义函数读取hdfs文件的注意点,避免FileSystem已关闭异常

一、问题描述 一位同学反馈,他写的argo存过中调用了一个自定义函数,函数会加载hdfs上的一个文件,但有些节点会报FileSystem closed异常,同时有时任务会成功,有时会失败。 二、问题分析 argodb的计算引擎是基于spark的定制化引擎,对于自定义函数的调用跟hive on spark的是一致的。udf要通过反射生成实例,然后迭代调用evaluate。通过代码分析,udf在

下载/保存/读取 文件,并转成流输出

最近对文件的操作又熟悉了下;现在记载下来:学习在于 坚持!!!不以细小而不为。 实现的是:文件的下载、文件的保存到SD卡、文件的读取输出String 类型、最后是文件转换成流输出;一整套够用了; 重点: 1:   操作网络要记得开线程; 2:更新网络获取的数据 切记用Handler机制; 3:注意代码的可读性(这里面只是保存到SD卡,在项目中切记要对SD卡的有无做判断,然后再获取路径!)

ROS1 + Realsense d455 固件安装+读取rostopic数据

目录 安装固件(一定要匹配)ROS1 wrapper 安装方法Realsense SDK 安装方法Realsense Firmware 安装方法 修改roslaunch配置文件,打开双目图像和IMU数据其他坑点参考链接 安装固件(一定要匹配) 如果你是使用ROS1获取realsense数据的话,一定要注意,SDK, Firmware的版本不是越新越好!!,这是因为intel已经不

Python批量读取身份证信息录入系统和重命名

前言 大家好, 如果你对自动化处理身份证图片感兴趣,可以尝试以下操作:从身份证图片中快速提取信息,填入表格并提交到网页系统。如果你无法完成这个任务,我们将在“Python自动化办公2.0”课程中详细讲解实现整个过程。 实现过程概述: 模块与功能: re 模块:用于从 OCR 识别出的文本中提取所需的信息。 日期模块:计算年龄。 pandas:处理和操作表格数据。 PaddleOCR:百度的

FFmpeg系列-视频解码后保存帧图片为ppm

在正常开发中遇到花屏时怎么处理呢?可以把解码后的数据直接保存成帧图片保存起来,然后直接看图片有没有花屏来排除是否是显示的问题,如果花屏,则代表显示无问题,如果图片中没有花屏,则可以往显示的方向去排查了。 void saveFrame(AVFrame* pFrame, int width, int height, int iFrame){FILE *pFile;char szFilename[

【LVI-SAM】激光雷达点云处理特征提取LIO-SAM 之FeatureExtraction实现细节

激光雷达点云处理特征提取LIO-SAM 之FeatureExtraction实现细节 1. 特征提取实现过程总结1.0 特征提取过程小结1.1 类 `FeatureExtraction` 的整体结构与作用1.2 详细特征提取的过程1. 平滑度计算(`calculateSmoothness()`)2. 标记遮挡点(`markOccludedPoints()`)3. 特征提取(`extractF

java读取resource/通过文件名获取文件类型

java读取resource java读取resource目录下文件的方法: 借助Guava库的Resource类 Resources.getResource("test.txt") 通过文件名获取文件类型 mongodb java

Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(4)

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ Unity数据持久化 之 一个通过2进制读取Excel并存储的轮子(3)-CSDN博客  这节就是真正的存储数据了   理清一下思路: 1.存储路径并检查 //2进制文件类存储private static string Data_Binary_Pa