Python将网格off格式转换为ply格式


背景

在做ldif论文复现时候,需要先用occpancy网络的数据,其中用mesh-fusion生成的水密网格是off格式。而ldif中shapenet复现需要ply格式。

前期在csdn和google搜索,没有特别清楚的问题解答

一、off文件格式

在这里插入图片描述

二、ply文件格式

参考:ply文件格式

参考:PLY格式介绍与读取
PLY是一种电脑档案格式,全名为多边形档案(Polygon File Format)或 斯坦福三角形档案(Stanford TriangleFormat)。
格式组成:
头:声明数据格式,规定和点和面片的数据内容
点:点的数据内容(坐标x,y,z 颜色r,g,b等)
线:线的数据内容(组成线的点序号索引,颜色等)
面片:面片的数据内容(组成面的点序号索引,颜色等)

举个栗子,一个描述8个顶点,6个面的立方体的PLY文件如下:

ply
format ascii 1.0           { ascii/binary, format version number }
comment made by Greg Turk  { comments keyword specified, like all lines }
comment this file is a cube
element vertex 8           { define "vertex" element, 8 of them in file }
property float x           { vertex contains float "x" coordinate }
property float y           { y coordinate is also a vertex property }
property float z           { z coordinate, too }
element face 6             { there are 6 "face" elements in the file }
property list uchar int vertex_index { "vertex_indices" is a list of ints }
end_header                 { delimits the end of the header }
0 0 0                      { start of vertex list }
0 0 1
0 1 1
0 1 0
1 0 0
1 0 1
1 1 1
1 1 0
4 0 1 2 3                  { start of face list }
4 7 6 5 4
4 0 4 5 1
4 1 5 6 2
4 2 6 7 3
4 3 7 4 0

三、读取单个off文件并写ply文件

1.引入库igl和plyfile

安装库:

pip install igl

引入库

import igl
import meshplot as mp

2.读入数据(三角网格面)

v, f = igl.read_triangle_mesh("data/bunny.off")
# mp.plot(v, f, shading={"wireframe": True})

在这里插入图片描述

2.写入数据

法一:直接写文件

尝试用numpy将数组写入遇到问题,savetxt会覆盖上次写入内容。
于是换了一种思路,直接文件中逐行写入

# Function to create point cloud file
import os
def create_output(input_filename):
    vertices, faces = igl.read_triangle_mesh(input_filename)
    fname = os.path.splitext(input_filename)[0]
    out_filename = os.path.join(fname+ '.ply')#在同一文件夹下做的转换,如果想放其他地方可以更改
    f=open(out_filename,"a")
    f.write('ply\n')
    f.write('format ascii 1.0\n')
    f.write('comment by YZF\n')
    f.write('comment PCL generated\n')
    f.write('element vertex {}\n'.format(len(vertices)))
    f.write('property float x\n')
    f.write('property float y\n')
    f.write('property float z\n')
    f.write('element face {}\n'.format(len(faces)))
    f.write('property list uchar int vertex_index\n')
    f.write('end_header\n')
    for i in range(len(vertices)):
        x, y, z = vertices[i]
        f.write('{} {} {}\n'.format(x, y, z))
    for j in range(len(faces)):
        a, b, c = faces[j]
        f.write('{} {} {} {}\n'.format(3, a, b, c))    
    f.close    
create_output("data/bunny.off")

法二:用plyfile写入成功

安装库

pip install plyfile
from plyfile import PlyData,PlyElement
def write_ply(save_path,points,faces,text=True):
    """
    save_path : path to save: '/yy/XX.ply'
    pt: point_cloud: size (N,3)
    """
    points_data = [(points[i,0], points[i,1], points[i,2]) for i in range(points.shape[0])]
    vertex = np.array(points_data, dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4')])
    face = np.array([(faces[i],255,255,255) for i in range(faces.shape[0])] , 
            dtype=[('vertex_indices', 'i4', (3,)),
                              ('red', 'u1'), ('green', 'u1'),
                              ('blue', 'u1')])
    el = PlyElement.describe(vertex, 'vertex')
    el2 = PlyElement.describe(face, 'face')
    plydata = PlyData([el,el2])
    # 全部写入
    plydata.write(save_path)

v, f = igl.read_triangle_mesh("data/bunny.off")
write_ply("data/xx.ply",v,f,text=True)

保存为ply文件,用windows打开成功
在这里插入图片描述

PS:开始我是只想保存网格的点和面,不存颜色信息。之后没有成功,于是就都设成一种颜色 (faces[i],255,255,255),成功保存

四、读取ply文件

>>> plydata = PlyData.read('tet.ply')
or
>>> with open('tet.ply', 'rb') as f:
...     plydata = PlyData.read(f)

>>> plydata.elements[0].name
'vertex'
>>> plydata.elements[0].data[0]
(0.0, 0.0, 0.0)
>>> plydata.elements[0].data['x']
array([ 0.,  0.,  1.,  1.], dtype=float32)
>>> plydata['face'].data['vertex_indices'][0]
array([0, 1, 2], dtype=int32)

https://pypi.org/project/plyfile/
https://github.com/dranjan/python-plyfile/blob/master/test/test_plyfile.py


五、同一文件夹下所有off文件都转成ply文件

参考:文件操作

# 同一文件夹下所有off文件都转成ply文件
import os
path = 'data'
with os.scandir(path) as entries:
    for entry in entries:
        if entry.is_file():
            if os.path.splitext(entry)[1]=='.off':
                 convert_output(os.path.join(path,entry.name))

自用的py文件

import os
import igl

def convert_output(input_filename,out_filename):
    vertices, faces = igl.read_triangle_mesh(input_filename)
    f=open(out_filename,"a")
    f.write('ply\n')
    f.write('format ascii 1.0\n')
    f.write('comment by YZF\n')
    f.write('comment PCL generated\n')
    f.write('element vertex {}\n'.format(len(vertices)))
    f.write('property float x\n')
    f.write('property float y\n')
    f.write('property float z\n')
    f.write('element face {}\n'.format(len(faces)))
    f.write('property list uchar int vertex_index\n')
    f.write('end_header\n')
    for i in range(len(vertices)):
        x, y, z = vertices[i]
        f.write('{} {} {}\n'.format(x, y, z))
    for j in range(len(faces)):
        a, b, c = faces[j]
        f.write('{} {} {} {}\n'.format(3, a, b, c))    
    f.close

#~/occupancy_networks/data/ShapeNet.build
basepath = os.getcwd()
with os.scandir(basepath) as entries1:
    for entry1 in entries1:
        if entry1.is_dir():
            # 创建如02691156ply的文件夹
            new_filepath = os.mkdir(os.path.join(basepath,entry1.name+'ply'))
            # 进入需要转换的文件夹
            now_path = os.path.join(basepath,entry1.name,'4_watertight_scaled')
            with os.scandir(now_path) as entries:
                for entry in entries:
                    if entry.is_file():
                        if os.path.splitext(entry)[1]=='.off':
                            # 这里entry.name是相对路径
                            input_filename = os.path.join(now_path,entry.name)
                            fname = os.path.splitext(entry.name)[0]
                            out_filename = os.path.join(new_filepath,fname+ '.ply')
                            convert_output(input_filename,out_filename)                  

总结

本文仅简单介绍了ply文件的写入。对于几何处理方面,比如igl、pymesh、plyfile等等库提供了大量能使我们快速便捷地处理网格数据的方法。

猜你喜欢

转载自blog.csdn.net/weixin_42785537/article/details/116194223