美文网首页
python写入ply文件

python写入ply文件

作者: 小黄不头秃 | 来源:发表于2024-02-19 21:39 被阅读0次

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 库。它支持两种格式:

  1. ASCII 格式(ascall 或者称为文本格式):在写入时,如果指定或默认以ASCII格式写入,数据将以可读的文本形式存储在文件中。
  2. 二进制格式(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中元组只算一个元素,而如果是中括号的话,就是二维数组了。

相关文章

网友评论

      本文标题:python写入ply文件

      本文链接:https://www.haomeiwen.com/subject/dklmadtx.html