文章目录
背景
在做ldif论文复现时候,需要先用occpancy网络的数据,其中用mesh-fusion生成的水密网格是off格式。而ldif中shapenet复现需要ply格式。
前期在csdn和google搜索,没有特别清楚的问题解答
一、off文件格式
二、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)