PLY(Polygon File Format,多边形文件格式)是一种用于存储三维模型的文件格式,特别适合于点云数据。它支持多种几何元素类型,包括顶点(vertices)、面片(faces)、线段(edges)等,并且可以携带额外的数据属性,如颜色、法线向量和纹理坐标等。
在点云应用中,PLY格式常用来存储大量的三维空间中的离散点,每个点通常包含三个坐标值(X, Y, Z),表示其在三维空间中的位置。除此之外,每一点还可以附带额外信息,例如:
颜色:每个点可以有RGB或RGBA(红绿蓝/透明度)颜色信息,这对于可视化和分析彩色点云非常有用。
强度:激光雷达扫描产生的点云可能带有回波强度信息。
法线:描述每个点所在表面的法线方向,这对进行表面处理、光照计算等非常重要。
其他用户定义属性:可以根据需要添加自定义数据字段,比如时间戳、分类标签等。
一个简单的PLY文件结构通常包含以下部分:
Header:包含了文件的格式声明、元素数量以及每个元素的属性列表。
Vertices Section:对于点云数据,这一部分会列出所有顶点的信息,每行代表一个点及其属性。
Other Elements (Optional):如果文件还包括了面片或其他几何元素,则会有对应的元素列表。
点云数据格式是用于存储和交换三维空间中离散点集合的数据结构。以下是一些常见的点云文件格式:
- LAS (LASer): 二进制格式,专门为激光雷达(LiDAR)数据设计,支持颜色、分类和其他元数据的存储。
- LAZ (LASzip): 是LAS格式的压缩版本,提供高效的空间存储。
- ASCII LAS: 类似于LAS,但以文本形式存储,便于人类阅读但占用空间较大。
- PLY (Polygon File Format): 可以存储点云数据以及其他几何体如多边形等,支持ASCII和二进制两种格式。
- PTS/PTX (Trimble formats): PTS主要用于存储GPS/GNSS静态测量数据,而PTX是Trimble公司的一种点云格式,可包含多个扫描视图的坐标系注册信息。
- PCD (Point Cloud Data): PCL库(Point Cloud Library)使用的格式,既可以是ASCII也可以是二进制格式,支持多种点云属性。
- XYZ: 简单的ASCII格式,每行代表一个点,通常包含X, Y, Z坐标,可能还包括颜色或强度信息。
- BIN: 二进制格式,不同的软件可能会有不同的BIN格式定义,不统一标准。
- NPY (.npy): Numpy数组格式,能够存储任意类型和维度的数据,包括三维点云的坐标数据,在Python环境下使用广泛。
- ASC 或者其他文本格式:类似于XYZ格式,每个点的坐标值以文本形式排列在文件中。
选择哪种格式取决于数据来源、应用需求以及兼容性考虑,例如文件大小、读写速度、是否需要额外的元数据存储等。
例如:
ply
format ascii 1.0 # 表明是ASCII编码的PLY文件,版本为1.0
element vertex 100 # 定义元素vertex,表示有100个顶点
property float x # 每个顶点有一个float类型的x坐标
property float y # 每个顶点有一个float类型的y坐标
property float z # 每个顶点有一个float类型的z坐标
property uchar red # 可选的,每个顶点有一个uchar类型的红色分量
property uchar green # 可选的,每个顶点有一个uchar类型的绿色分量
property uchar blue # 可选的,每个顶点有一个uchar类型的蓝色分量
element face 0 # 如果没有面片,face的数量为0
property list uchar int vertex_indices # 面片元素的定义(在此可忽略)
end_header
# 紧接着是数据部分,按照header中定义的顺序列出顶点数据
0.0 0.0 0.0 255 255 255
1.0 0.0 0.0 0 0 255
1、直接创建ply文件写入
这里是使用生成一个ASCII格式的PLY文件,包含了点的XYZ坐标以及可选的颜色信息。如果你的点云没有颜色信息,只需要调用create_ply_file(points)即可。
注意:对于大型点云数据集,通常会考虑使用二进制PLY格式以减小文件大小和提高读写效率。上述例子仅针对ASCII PLY格式,转换到二进制格式需要修改写入部分,并使用struct.pack()进行数据打包。
import struct
def create_ply_file(points, filename='output.ply', color=None):
"""
创建一个包含给定点云的PLY文件。
points: 三维点坐标列表,如 [[x1, y1, z1], [x2, y2, z2], ...]
filename: 输出PLY文件名
color: 可选参数,如果提供了颜色信息,则应为与点一一对应的RGB值列表,如 [[r1, g1, b1], [r2, g2, b2], ...]
"""
num_points = len(points)
with open(filename, 'w') as f:
# 写入PLY文件头
f.write("ply\n")
f.write("format ascii 1.0\n")
f.write("element vertex %d\n" % num_points)
f.write("property float x\n")
f.write("property float y\n")
f.write("property float z\n")
if color is not None:
assert len(color) == num_points
f.write("property uchar red\n")
f.write("property uchar green\n")
f.write("property uchar blue\n")
f.write("end_header\n")
# 写入点云数据
for i in range(num_points):
f.write("%f %f %f" % (points[i][0], points[i][1], points[i][2]))
if color is not None:
r, g, b = [int(c * 255) for c in color[i]]
f.write(" %d %d %d" % (r, g, b))
f.write("\n")
# 示例使用
points = [
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
# 更多点...
]
color = [
[1.0, 0.0, 0.0], # 红色
[0.0, 1.0, 0.0], # 绿色
# 更多彩色点...
]
create_ply_file(points, color=color)
2、使用plyfile库写入
plyfile 是一个用于读写 PLY(Polygon File Format)文件的 Python 库。它支持两种格式:
- ASCII 格式(ascall 或者称为文本格式):在写入时,如果指定或默认以ASCII格式写入,数据将以可读的文本形式存储在文件中。
- 二进制格式(binary_little_endian 或 binary_big_endian):根据系统的字节序,可以写入小端或大端二进制格式的 PLY 文件,这种格式的数据是以二进制编码存储的,不直接可读但通常占用空间较小且加载速度更快。
在使用 plyfile 库时,你可以通过设置相应的参数来选择写入何种格式。例如,在写入文件时明确指定 format='ascii' 来写入ASCII格式,或者 format='binary_little_endian' 来写入小端二进制格式。如果不指定,默认的行为可能会依据库的具体实现而定,但一些库倾向于ASCII格式作为默认写入格式。
import numpy as np
from plyfile import PlyData, PlyElement
# 假设你已经有了一个numpy数组来表示点云,每行是一个点的(x, y, z)坐标
points = np.array([
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
# 更多点...
])
# 使用plyfile库写ply文件
def write_ply_file_by_plyfile(point_list, point_cloud_file):
print("Writting PLY file".center(120, "="))
points = [(point_list[i,0], point_list[i,1], point_list[i,2]) for i in range(point_list.shape[0])]
points = np.array(points, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')])
color = [(255, 255, 255)]*point_list.shape[0]
color = np.array(color,dtype=[('red', 'uint8'), ('green', 'uint8'), ('blue', 'uint8')])
# 定义PLY元素格式:这里我们只定义了一个名为vertex的元素,包含x、y、z属性
vertex_element = PlyElement.describe(points, name='vertex', comments=['x','y','z'])
color = PlyElement.describe(color, name="color", comments=['red','green','blue'])
# 创建PlyData对象并写入PLY文件
# 设置text=False并指定字节序为little_endian, 使用二进制格式会是的文件存储更小,但是里面的信息就不是文本了。如果不想要二进制存储,只需要将text设置为True就好了。
ply_data = PlyData([vertex_element,color], text=False, byte_order='<')
ply_data.write(point_cloud_file)
print("Finished!\n")
注意我们输入element.describe的data一定是一维的数据,也就是代码中的points和color都得是一维的数据,但是实际上他们的形状是(N, 3),但经过上述处理之后我们再看他们的shape就都是一维的了。原因应该是在numpy的array中元组只算一个元素,而如果是中括号的话,就是二维数组了。








网友评论