为一个双参数函数(点数据云)构建一个网格,并使用Python将其保存为.ply文件



我正在尝试为一个双参数函数(点数据云(构建一个网格,并使用Python将其保存为.ply文件。

输入:3D空间中的百万个数据点(x,y,z(其中z可以被视为数学函数的值z=f(x,y(

  1. 如何构建表示该点云的3D绘图表面的网格
  2. 并将其导出为3D模型

所需输出:.PLY包含网格的文件。

对于步骤2,我有以下功能:

def savePoly(filename, arrayOfXYZ):
xyz = np.array(arrayOfXYZ)
x_points = xyz[:, 0]
y_points = xyz[:, 1]
z_points = xyz[:, 2]
# Write header of .ply file
fid = open(filename, 'wb')
fid.write(bytes('plyn', 'utf-8'))
fid.write(bytes('format binary_little_endian 1.0n', 'utf-8'))
fid.write(bytes('element vertex %dn' % x_points.shape[0], 'utf-8'))
fid.write(bytes('property float xn', 'utf-8'))
fid.write(bytes('property float yn', 'utf-8'))
fid.write(bytes('property float zn', 'utf-8'))
fid.write(bytes('property uchar redn', 'utf-8'))
fid.write(bytes('property uchar greenn', 'utf-8'))
fid.write(bytes('property uchar bluen', 'utf-8'))
fid.write(bytes('end_headern', 'utf-8'))
rgb_points = np.ones(x_points.shape).astype(np.uint8) * 255
# Write 3D points to .ply file
for i in range(x_points.shape[0]):
fid.write(bytearray(struct.pack("fffccc",
x_points[i],
y_points[i],
z_points[i],
rgb_points[i].tobytes(),
rgb_points[i].tobytes(),
rgb_points[i].tobytes()
)))
fid.close()
print(fid)

但这只保存顶点,而不保存曲面。

以下代码将三角形保存到.ply,但我不确定什么是tris如何首先构建三角形:

"""
plyfun
@author:wronk
Write surface to a .ply (Stanford 3D mesh file) in a way that preserves
vertex order in the MNE sense. Extendable for colors or other vertex/face properties.
.ply format: https://en.wikipedia.org/wiki/PLY_(file_format)
"""
import mne
import numpy as np
from os import path as op
import os
from os import environ

def write_surf2ply(rr, tris, save_path):
out_file = open(save_path, 'w')
head_strs = ['plyn', 'format ascii 1.0n']
ele_1 = ['element vertex ' + str(len(rr)) + 'n',
'property float xn',
'property float yn',
'property float zn']
ele_2 = ['element face ' + str(len(tris)) + 'n',
'property list uchar int vertex_indexn']
tail_strs = ['end_headern']
# Write Header
out_file.writelines(head_strs)
out_file.writelines(ele_1)
out_file.writelines(ele_2)
out_file.writelines(tail_strs)
##############
# Write output
##############
# First, write vertex positions
for vert in rr:
out_file.write(str(vert[0]) + ' ')
out_file.write(str(vert[1]) + ' ')
out_file.write(str(vert[2]) + 'n')
# Second, write faces using vertex indices
for face in tris:
out_file.write(str(3) + ' ')
out_file.write(str(face[0]) + ' ')
out_file.write(str(face[1]) + ' ')
out_file.write(str(face[2]) + 'n')
out_file.close()

if __name__ == '__main__':
struct_dir = op.join(environ['SUBJECTS_DIR'])
subject = 'AKCLEE_139'
surf_fname = op.join(struct_dir, subject, 'surf', 'lh.pial')
save_path = op.join('/media/Toshiba/Blender/Brains', subject,
'lh.pial_reindex.ply')
rr, tris = mne.read_surface(surf_fname)
write_surf2ply(rr, tris, save_path)

对于步骤1:

下面的文章生成网格,但(a(它是一个通用的点数据云,而z=f(x,y(在这里就足够了,(b(它假设输入中有一个法线数组:https://towardsdatascience.com/5-step-guide-to-generate-3d-meshes-from-point-clouds-with-python-36bad397d8ba它仍然需要建造。

综上所述:

有没有一种简单的方法可以使用Python为巨大的点云数据构建网格,其中z坐标是(x,y(的函数,并将该网格导出到.ply文件?

解决方案:

  1. 导入
import numpy as np
import scipy.spatial
import pandas as pd
  1. 加载带有点云数据的csv文件:
df = pd.read_csv("data.csv")
print(df.columns)
x = df['column 0']
y = df['column 1']
z = df['column z values']
  1. 如有必要,对数据进行归一化,以确保网格正确位于轴原点:
x0 = x[0]
y0 = y[0]
z0 = z[0]
pointslist = []
for i in range(len(x)):
xi = (x[i] - x0) / 100
yi = (y[i] - y0) / 4
zi = (z[i] - z0) / 8
pointslist.append([xi, yi, zi]) # array of triplets 
xyz = np.array(pointslist)
  1. 由于z=f(x,y(我们不需要使用通用三角测量,并且可以对2D数据点集使用Delaunay算法
# xyz = np.random.random((12, 3))  # arbitrary 3D data set
# xyz = np.array([[0, 0,1], [0, 1,1], [1, 0.5,0], [1, 0,0]]) # smaller data set for testing 
# print(data)
mesh = scipy.spatial.Delaunay(xyz[:, :2])  # take the first two dimensions
# print(mesh.points)
# print(mesh.convex_hull)
# print(mesh.vertex_to_simplex)
#
# x = xyz[:, 0]
# y = xyz[:, 1]
# z = xyz[:, 2]
  1. 网格准备就绪,三角形作为顶点索引存储在网格中。simplices。使用以下函数将所有内容保存到.PLY-文件:
writeSurface2PLY(xyz, mesh.simplices, "output.ply")
def writeSurface2PLY(vertices, meshanglesAsVertexIndices, save_path):
out_file = open(save_path, 'w')
head_strs = ['plyn', 'format ascii 1.0n']
ele_1 = ['element vertex ' + str(len(vertices)) + 'n',
'property float xn',
'property float yn',
'property float zn']
ele_2 = ['element face ' + str(len(meshanglesAsVertexIndices)) + 'n',
'property list uchar int vertex_indexn']
tail_strs = ['end_headern']
# Write Header
out_file.writelines(head_strs)
out_file.writelines(ele_1)
out_file.writelines(ele_2)
out_file.writelines(tail_strs)
##############
# Write output
##############
# First, write vertex positions
for vert in vertices:
out_file.write(str(vert[0]) + ' ')
out_file.write(str(vert[1]) + ' ')
out_file.write(str(vert[2]) + 'n')
# Second, write faces using vertex indices
for face in meshanglesAsVertexIndices:
out_file.write(str(3) + ' ')
out_file.write(str(face[0]) + ' ')
out_file.write(str(face[1]) + ' ')
out_file.write(str(face[2]) + 'n')
out_file.close()

相关内容

最新更新