不同格式点云存储结构整理以及基本的读写、可视化方法

  • 一、文本(txt)
    • 1.1、存储结构
    • 1.2、读取
  • 二、PCD格式
    • 1.1、存储结构
    • 1.2、读写
      • 1.2.1、open3d读写(python)
      • 1.2.2、PCL读写(C++)
  • 三、LAS格式
    • 3.1、存储结构
    • 3.2、读写
      • 3.2.1、使用laspy 读写(Python)
      • 3.2.2、使用laslib读写(C++)
  • 四、PLY格式
    • 4.1、存储结构
      • 文件头(header)
      • 数据区域
    • 4.2、读写
      • 4.2.1、使用plyfile读写(Python)
      • 4.2.2、使用pcl读写(C++)

一、文本(txt)

1.1、存储结构

使用文本格式存储的点云数据文件结构比较简单,每个点是一行记录,点的信息存储格式为 x y z或者 x y z r g b。

1.2、读取

读取文本格式的点云数据时,可以按照一般的文本读取方法,这里记录一下如何使用open3d读取txt格式的点云数据

import open3d as o3d
txt_file=r"D:\test_data\bildstein_station1_xyz_intensity_rgb.txt"pcd=o3d.io.read_point_cloud(txt_file,format='xyz')
o3d.visualization.draw([pcd])

二、PCD格式

一个PCD文件是文件头部分和数据部分组成

1.1、存储结构

字段名 字段解释
VERSION 指定PCD文件版本
FIELDS 指定一个点可以有的每一个维度和字段的名字
SIZE 用字节数指定每一个维度的大小
TYPE 用一个字符指定每一个维度的类型
COUNT 指定每一个维度包含的元素数据
WIDTH 无序点的数量或者有序点一行中点的数目
HEIGHT 无序点云中设置为1,有序点云中表示行数
POINTS 点云中点的总数
DATA 数据类型,二进制或者ASCII

1.2、读写

1.2.1、open3d读写(python)

读取pcd点云文件

import open3d as o3d
import numpy as np#读取pcd数据并可视化
pcd_file=r""
pcd=o3d.io.read_point_cloud(pcd_file,format='pcd')#将点云的坐标和颜色转换为numpy格式
points=np.array(pcd.points)
colors=np.array(pcd.colors)#可视化
o3d.visualization.draw([pcd])

保存pcd点云文件

#写入pcd格式
save_file="test2.pcd"#手动定义点云
points=np.array([[8,5,3],[9,0,1],[2,5,3],[0,4,2],[7,2,9],[8,8,4],[9,5,8],[2,5,9],[0,7,5],[11,2,8],[10,9,0]])
colors=np.array([[255,0,0],[255,0,0],[0,255,0],[0,255,0],[0,0,255],[0,0,255],[255,0,255],[255,0,255],[255,255,0],[255,255,0],[255,255,0]])
colors=colors/255pcd=o3d.geometry.PointCloud()pcd.points=o3d.utility.Vector3dVector(points)
pcd.colors=o3d.utility.Vector3dVector(colors)#可视化
o3d.visualization.draw_geometries([pcd])#使用draw方法可视化需要将颜色归一化到0-1之间
# o3d.visualization.draw([pcd])#保存
#o3d.io.write_point_cloud(save_file,pcd,write_ascii=True) #以ascii格式存储点数据集部分
o3d.io.write_point_cloud(save_file,pcd)#以二进制格式存储点数据集部分

pcd点数据集部分保存为ASCII格式

pcd点数据集部分保存为二进制格式,其中rgb是用位存储的方式写入的。

1.2.2、PCL读写(C++)

我们用上面生成的pcd文件做测试

#include<iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/point_types.h>using namespace std;
int main()
{string pcd_file = "D:\\project\\Python\\PointCloud\\test2.pcd";//pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);if (pcl::io::loadPCDFile<pcl::PointXYZRGB>(pcd_file,*cloud)==-1){PCL_ERROR("couldn't read file\n");return(-1);}for (size_t i=0;i<cloud->points.size();++i){cout << " " << cloud->points[i].x << " " <<cloud->points[i].y << " " <<cloud->points[i].z << " " <<(int)cloud->points[i].r<< " "<<(int)cloud->points[i].g<<" "<<(int)cloud->points[i].b<< endl;}return 0;
}

打印结果

保存pcd文件

#include <iostream>#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>using namespace std;
int main()
{string pcd_file = "test2.pcd";pcl::PointCloud<pcl::PointXYZRGB> cloud;int data[11][6] = {{8,5,3,255,0,0},{9,0,1,255,0,0},{2,5,3,0,255,0},{0,4,2,0,255,0},{7,2,9,0,0,255},{8,8,4,0,0,255},{9,5,8,255,0,255},{2,5,9,255,0,255},{0,7,5,255,255,0},{11,2,8,255,255,0},{10,9,0,255,255,0}};cloud.width = 11;cloud.height = 1;cloud.is_dense = false;cloud.points.resize(cloud.width*cloud.height);for (size_t i = 0; i < cloud.points.size(); ++i){cloud.points[i].x = data[i][0];cloud.points[i].y = data[i][1];cloud.points[i].z = data[i][2];cloud.points[i].r = data[i][3];cloud.points[i].g = data[i][4];cloud.points[i].b = data[i][5];}pcl::io::savePCDFileASCII(pcd_file, cloud);//pcl::io::savePCDFileBinary(pcd_file, cloud);return 0;
}

打开输出的ascii文件

可以看到pcl生成的pcd点云文件与open3d生成的点云文件在颜色部分不一致,主要是数据存储类型导致的,pcl1.7之后颜色部分会保存成整型。具体请参看这里。

三、LAS格式

3.1、存储结构

LAS是一种存储点云的公开数据格式,主要用来存储雷达点云数据,LAZ是对LAS格式的无损压缩。

最新的LAS规格版本是LAS 1.4。laspy库支持1.2~1.4版本的LAS文件。

一个LAS文件有三部分组成:文件头区(Header)、可变长记录区(VLRs)、点集记录区(Point Records)

文件头包含数据版本,点的格式(每个点存储的不同维度)等信息;可变长记录包括一些元信息,如坐标系信息,额外的维度等信息;点集记录区是las文件的核心,记录点的x、y、z坐标信息和r、g、b、classification、intensity等其他属性信息。
点的格式共有11个版本,其中第0版为基础,其他后续版本在第0版的基础上增加了其他字段,具体字段参考这里。

3.2、读写

3.2.1、使用laspy 读写(Python)

在python中可以使用laspy包来读写las点云文件

import laspy
import numpy as nplas_file=r""
las=laspy.read(las_file)
#获取文件头
header=las.header
#点类型
point_format=las.point_format
print(point_format.id)
#属性字段名
dimension_names=point_format.dimension_names
print(list(dimension_names))#点集的外边框
print(header.mins)
print(header.maxs)#点个数
point_num=header.point_count#获取坐标和颜色
las_x=np.array(las.x)
las_y=np.array(las.y)
las_z=np.array(las.z)
las_r=np.array(las.red)
las_g=np.array(las.green)
las_b=np.array(las.blue)#组合
pt=np.stack([las_x,las_y,las_z],axis=1)
colors=np.stack([las_r,las_g,las_b],axis=1)

使用laspy写las文件

save_las_file=r"save_las.las"#以x y z r g b的方式定义点云数据
my_data=np.array([[8,5,3,255,0,0],[9,0,1,255,0,0],[2,5,3,0,255,0],[0,4,2,0,255,0],[7,2,9,0,0,255],[8,8,4,0,0,255],[9,5,8,255,0,255],[2,5,9,255,0,255],[0,7,5,255,255,0],[11,2,8,255,255,0],[10,9,0,255,255,0]])#创建点云文件las=laspy.create(file_version="1.2",points_format=3)las.x=my_data[:,0]las.y=my_data[:,1]las.z=my_data[:,2]las.red=my_data[:,3]las.green=my_data[:,4]las.blue=my_data[:,5]#保存las文件las.write(save_las_file)

3.2.2、使用laslib读写(C++)

使用C++操作las文件可以使用laslib库。

#include <iostream>
#include "lasreader.hpp"
#include "laswriter.hpp"
using namespace std;
int main()
{const string las_file="";LASreadOpener lasreadopener;lasreadopener.set_file_name(las_file.data());LASreader* lasreader=lasreadopener.open();LASheader header=lasreader->header;lasreader->header.unlink();int nbPoints = header.number_of_point_records;float x,y,z;int r,g,b;while(lasreader->read_point()){LASpoint& pointReader= lasreader->point;x=pointReader.get_x();y=pointReader.get_y();z=pointReader.get_z();r=pointReader.get_R();g=pointReader.get_G();b=pointReader.get_B();}delete lasreader;
}

写入las文件

#include <iostream>
#include "lasreader.hpp"
#include "laswriter.hpp"
using namespace std;
int main()
{const string las_file="test.las";int data[11][6] = {{8,5,3,255,0,0},{9,0,1,255,0,0},{2,5,3,0,255,0},{0,4,2,0,255,0},{7,2,9,0,0,255},{8,8,4,0,0,255},{9,5,8,255,0,255},{2,5,9,255,0,255},{0,7,5,255,255,0},{11,2,8,255,255,0},{10,9,0,255,255,0}};LASwriteOpener laswriteropener;laswriteropener.set_file_name(las_file.data());LASheader header;header.point_data_format=3;header.point_data_record_length=34;header.number_of_point_records=11;LASWriter* laswriter = laswriteropener.open(&header);LASpoint point;point.init(&header,header.point_data_format,header.point_data_record_length,&header);double minx=DBL_MAX,miny=DBL_MAX,minz=DBL_MAX;double maxx=-DBL_MAX,maxy=-DBL_MAX,maxz=-DBL_MAX;for(size_t i=0;i<header.point_data_record_length;++i){point.set_x(data[i][0]);point.set_y(data[i][1]);point.set_z(data[i][2]);point.set_R(data[i][3]);point.set_G(data[i][4]);point.set_B(data[i][5]);if(data[i][0]<minx){minx=data[i][0];}if(data[i][1]<miny){minx=data[i][1];}if(data[i][2]<minz){minx=data[i][2];}if(data[i][0]>maxx){maxx=data[i][0];}if(data[i][1]>maxy){maxy=data[i][1];}if(data[i][2]>maxz){maxx=data[i][2];}laswriter->write_point(&point);laswriter->update_inventory(&point);}header.set_bounding_box(minx,miny,minz,maxx.maxy.maxz);laswriter->update_header(&header);I64 total_bytes=laswriter->close();delete laswriter;
}

四、PLY格式

4.1、存储结构

PLY(Polygon File Format)是一种常见的点云存储格式,由斯坦福大学开发,其最早主要用于存储三维扫描仪器的点云数据。

PLY文件是由文件头和数据区两部分组成。

文件头(header)

其中文件头记录的是点云文件中的注释、元素类别和属性,以ply开头,以end header结尾。

ply
...
...
end header

文件头的第二行是文件的存储方式和版本,以format开头,依次是编码方式、版本。编码方式有三种分别是ascii、binary_little_endian 、binary_big_endian。目前PLY只有1.0版本。

ply
format ascii 1.0
...
...
end header

format之后跟注释信息,以comment开头,制作者可以添加一些作者信息,点云基本信息。

ply
format ascii 1.0
comment made by anonymous
comment this file is a cube
...
end header

注释信息comment之后是element元素信息+该种元素的property属性信息,element元素信息包括种类、个数,property属性信息包括属性字段的存储类型和属性名。PLY文件中的元素一般包括顶点(vertex)、面(face)、边(edge)等。元素信息和属性信息应该组合出现,格式如下

element <element name> <number in file>
property <data_type> <property name 1>
property <data_type> <property name 2>
property <data_type> <property name 3>

我们定义一个包含6个顶点和8个面元素的ply文件,文件头如下,

ply
format ascii 1.0
comment made by anonymous
comment this file is a cube
element vertex 6
property float32 x
property float32 y
property float32 z
property uchar red
property uchar green
property uchar blue
element face 8
property list uint8 int32 vertex_index
end_header

数据区域

在文件头后直接开始存储数据,存储形式分为ASCII和二进制。以ASCII为例,先按行记录每个点,全部点记录完成后再按行记录每个面。

0 0 0 0 0 0 (开始记录点,按照x,y,z,r,g,b方式排列)
0 100 0 0 0 0
100 100 0 0 0 0
100 0 0 0 0 0
50 50 75 255 255 255
50 50 -75 255 255 255
3 0 1 4 (开始记录面,按照点个数,点的序号排列,3表示这个面由3个点组成,0,1,4代表该面由第0,1,4个点组成)
3 1 2 4
3 2 3 4
3 0 3 4
3 0 1 5
3 1 2 5
3 2 3 5
3 0 3 5

所以完整的一个ply文件如下

ply
format ascii 1.0
comment made by anonymous
comment this file is a cube
element vertex 6
property float32 x
property float32 y
property float32 z
property uchar red
property uchar green
property uchar blue
element face 8
property list uint8 int32 vertex_index
end_header
0 0 0 0 0 0
0 100 0 0 0 0
100 100 0 0 0 0
100 0 0 0 0 0
50 50 75 255 255 255
50 50 -75 255 255 255
3 0 1 4
3 1 2 4
3 2 3 4
3 0 3 4
3 0 1 5
3 1 2 5
3 2 3 5
3 0 3 5

4.2、读写

4.2.1、使用plyfile读写(Python)

使用plyfile读取ply文件

from plyfile import PlyData,PlyElementfile=r"C:\Users\123\Desktop\test2.ply"
plydata=PlyData.read(file)print(plydata)
print("*************************************************")
#第一种读取方法
elements=plydata.elements
for element in elements:for data in element.data:print(data)
print("*************************************************")
#第二种读取方法
vertex_data=elements[0].data
face_data =elements[1].data
print(vertex_data)
print(face_data)

打印结果

ply
format ascii 1.0
comment made by anonymous
comment this file is a cube
element vertex 6
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
element face 8
property list uchar int vertex_index
end_header
*************************************************
(0., 0., 0., 0, 0, 0)
(0., 100., 0., 0, 0, 0)
(100., 100., 0., 0, 0, 0)
(100., 0., 0., 0, 0, 0)
(50., 50., 75., 255, 255, 255)
(50., 50., -75., 255, 255, 255)
(array([0, 1, 4]),)
(array([1, 2, 4]),)
(array([2, 3, 4]),)
(array([0, 3, 4]),)
(array([0, 1, 5]),)
(array([1, 2, 5]),)
(array([2, 3, 5]),)
(array([0, 3, 5]),)
*************************************************
[(  0.,   0.,   0.,   0,   0,   0) (  0., 100.,   0.,   0,   0,   0)(100., 100.,   0.,   0,   0,   0) (100.,   0.,   0.,   0,   0,   0)( 50.,  50.,  75., 255, 255, 255) ( 50.,  50., -75., 255, 255, 255)]
[(array([0, 1, 4]),) (array([1, 2, 4]),) (array([2, 3, 4]),)(array([0, 3, 4]),) (array([0, 1, 5]),) (array([1, 2, 5]),)(array([2, 3, 5]),) (array([0, 3, 5]),)]

使用plyfile写入ply文件

def write_ply(output_file,text=True):points=[(0,0,0),(0,100,0),(100,100,0),(100,0,0),(50,50,75)]face=np.array([((0,1,2),255,0,0),((0,2,3),255,0,0),((0, 1, 4),0,255,0),((1,2,4),0,0,255),((2,3,4),255,255,0),((0,3,4),0,0,0)],dtype=[('vertex_index','i4',(3,)),('red','u1'),('green','u1'),('blue','u1')])print(face)vertex = np.array(points, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])el = PlyElement.describe(vertex, 'vertex')face = PlyElement.describe(face, 'face')PlyData([el,face], text=text).write(out_file)

在meshlab中打开

4.2.2、使用pcl读写(C++)

读取ply点云文件

#include <iostream>#include <pcl-1.8/pcl/io/pcd_io.h>
#include <pcl-1.8/pcl/point_types.h>
#include <pcl-1.8/pcl/visualization/cloud_viewer.h>
#include <pcl-1.8/pcl/io/ply_io.h>using namespace std;
int main()
{string ply_file = "C:\\Users\\123\\Desktop\\test7.ply";pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);if (pcl::io::loadPLYFile<pcl::PointXYZ>(ply_file,*cloud)==-1){return (-1);}cout << cloud->width << " " << cloud->height << endl;for (size_t i=0;i<cloud->points.size();++i){cout << cloud->points[i].x << " " << cloud->points[i].y << " " << cloud->points[i].z << endl;}return (0);
}

保存ply点云文件

#include <iostream>#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>using namespace std;
int main()
{string ply_file = "test2.ply";pcl::PointCloud<pcl::PointXYZRGB> cloud;int data[11][6] = {{8,5,3,255,0,0},{9,0,1,255,0,0},{2,5,3,0,255,0},{0,4,2,0,255,0},{7,2,9,0,0,255},{8,8,4,0,0,255},{9,5,8,255,0,255},{2,5,9,255,0,255},{0,7,5,255,255,0},{11,2,8,255,255,0},{10,9,0,255,255,0}};cloud.width = 11;cloud.height = 1;cloud.is_dense = false;cloud.points.resize(cloud.width*cloud.height);for (size_t i = 0; i < cloud.points.size(); ++i){cloud.points[i].x = data[i][0];cloud.points[i].y = data[i][1];cloud.points[i].z = data[i][2];cloud.points[i].r = data[i][3];cloud.points[i].g = data[i][4];cloud.points[i].b = data[i][5];}pcl::io::savePLYFile(ply_file, cloud);return 0;
}

不同格式点云存储结构(txt、pcd、las、ply)整理以及基本的读写、可视化方法相关推荐

  1. [20150113]关于oracle的存储结构.txt

    [20150113]关于oracle的存储结构.txt --这阵子在看vage写的>,里面第一章提到: --P2 --每个文件的前128个块,都是文件头,被Oracle留用了.在oracle 1 ...

  2. 微信小程序云存储中调用fileid作为图片路径,无法正常显示解决方法

    教同学们写一个图片瀑布流的微信小程序,图片是放到云存储中的,大多数同学都没有问题,有个别同学出现了下方的问题,图片无法正常显示 查阅了官方的资料,发现image组件的src从2.3.0 起开始支持云文 ...

  3. C语言手写二叉树(链式存储结构)

    C语言手写二叉树(链式存储结构) 二叉树结构 二叉树基本运算 代码 图例(main函数执行过程如下:) 阶段I 阶段II 阶段III 阶段IV 阶段V 先序遍历输出过程 二叉树结构 二叉树可以用顺序存 ...

  4. 论文:云存储区块链技术:系统文献综述

    Blockchain Technology for Cloud Storage: A Systematic Literature Review 本文链接:https://download.csdn.n ...

  5. 云豹直播系统源码接入华为云存储,含问题及解决方法

    云豹直播系统源码接入华为云存储该怎么做? 一.云豹直播系统源码接入华为云存储的前期准备工作 1.注册云服务账号开通对象存储服务. (1)登录公有云网站.在页面右上角单击"注册".按 ...

  6. 关于asc、txt格式到pcd、ply格式数据转换

    1 asc数据说明 许多点云数据是asc或txt数据格式,asc(ascii)即文本文件,数据已可视化的文本存储.在点云数据处理时,常面临数据格式转换问题,比如说需要转换成pcd或ply数据格式. 2 ...

  7. 利用 labelCloud 开源工具标注自己的点云数据集为KITTI标注格式教程(支持pcd、bin格式点云)

    先贴地址 github 地址:https://github.com/ch-sa/labelcloud 标注为KITTI格式的复现步骤与操作流程 首先吧pcd格式点云转乘bin格式 克隆代码 git c ...

  8. 《Fabric 云存储的电子健康病历系统》(3)病历结构体API

    1. IPMR初始化患者病历 IPMR 初始化患者病历接口通过 initRecords()方法实现,根据接口传入的病历信息完成病历初始化并将病历 Records 记录到账本中. 5 个参数:病历 ID ...

  9. 实现Scrapy框架爬取酷狗音乐Top100名,并存储为TXT,JSON,CSV和Excel格式数据

    前言 实现Scrapy框架爬取网页数据(酷狗音乐Top100名,包括排名信息.歌手信息.歌曲名.歌曲时长) 一.创建项目 在cmd中输入: scrapy startproject kugouScrap ...

最新文章

  1. Java并发编程高级篇(八):在执行器中取消任务
  2. 《当程序员的那些狗日日子》(十五)首次接单
  3. 实例——在编程过程中进行单元测试
  4. 第五十三篇、OC利用AFN上传视频到服务器
  5. linux不自动创建sda1,linux下头挂载新硬盘(转)
  6. 使用Hibernate和Spring构建Java Web应用程序
  7. 机器学习从入门到精通50讲(二)-千万级流量压力测试
  8. Android教程之android平台水波效果!提供源码!
  9. 查看php项目tp版本,tp5.1如何查看版本号
  10. python基础 - 字符串与列表的基本操作方法
  11. 发卡网源码附企业发卡网源码搭建安装教程
  12. android将照片压缩并显示,android拍照选择图库后将照片剪裁压缩显示到imageview上 -电脑资料...
  13. 群晖日历同步到android,用群晖calander日历做华为手机、ipad、mac三方通讯录和日历同步 2020-12-28...
  14. Swagger官网与官方文档
  15. 计算机硬件技术心得,计算机硬件技术基础学习心得.doc
  16. 用友u8服务器优化,用友U8erp软件运行的性能优化方案图文教程
  17. 国内外技术论坛的区别
  18. 班尼机器人维修方法_工业机器人常见故障和修理方法
  19. Linux下安装tuned以使用tuned-adm命令优化Linux系统性能
  20. mcjava盗版联机_使用N2N组建虚拟局域网联机游戏(我的世界 Java版)

热门文章

  1. pi六轴算法_PIMars六轴压电平台系统.PDF
  2. goroutine中使用recover,解决协程中出现panic,导致程序崩溃的问题。recover panic 协程的错误处理
  3. 禅道怎么启动mysql_解决禅道(ZenTao)Mysql启动不了的有关问题_mysql
  4. 路由表、静态路由、RIP
  5. ct文件用什么打开(ce修改器怎么打开ct文件)
  6. Python--获取电脑配置信息--完整代码及过程
  7. [春秋云镜]CVE-2020-19960,CVE-2020-19961
  8. 主成分分析法 (PCA) 用于数据可视化实验 -- Matlab版
  9. 产品总监(经理)应该具备的能力
  10. 关于 DellEMC 安装系统时找不到系统硬盘的问题