【问题标题】:Build a mesh for a two-argument function (point data cloud) and save it as .ply file using Python为双参数函数(点数据云)构建网格并使用 Python 将其保存为 .ply 文件
【发布时间】:2021-02-22 09:46:20
【问题描述】:

我正在尝试为双参数函数(点数据云)构建网格并使用 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('ply\n', 'utf-8'))
    fid.write(bytes('format binary_little_endian 1.0\n', 'utf-8'))
    fid.write(bytes('element vertex %d\n' % x_points.shape[0], 'utf-8'))
    fid.write(bytes('property float x\n', 'utf-8'))
    fid.write(bytes('property float y\n', 'utf-8'))
    fid.write(bytes('property float z\n', 'utf-8'))
    fid.write(bytes('property uchar red\n', 'utf-8'))
    fid.write(bytes('property uchar green\n', 'utf-8'))
    fid.write(bytes('property uchar blue\n', 'utf-8'))
    fid.write(bytes('end_header\n', '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 = ['ply\n', 'format ascii 1.0\n']
    ele_1 = ['element vertex ' + str(len(rr)) + '\n',
             'property float x\n',
             'property float y\n',
             'property float z\n']
    ele_2 = ['element face ' + str(len(tris)) + '\n',
             'property list uchar int vertex_index\n']
    tail_strs = ['end_header\n']

    # 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 文件?

【问题讨论】:

    标签: python 3d mesh point-clouds ply-file-format


    【解决方案1】:

    解决方案:

    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) 我们不需要使用通用三角剖分,并且可以将 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. 网格已准备就绪,三角形作为顶点索引存储在 mesh.simplices 中。使用以下函数将所有内容保存到 .PLY-文件:
    writeSurface2PLY(xyz, mesh.simplices, "output.ply")
    
    def writeSurface2PLY(vertices, meshanglesAsVertexIndices, save_path):
        out_file = open(save_path, 'w')
    
        head_strs = ['ply\n', 'format ascii 1.0\n']
        ele_1 = ['element vertex ' + str(len(vertices)) + '\n',
                 'property float x\n',
                 'property float y\n',
                 'property float z\n']
        ele_2 = ['element face ' + str(len(meshanglesAsVertexIndices)) + '\n',
                 'property list uchar int vertex_index\n']
        tail_strs = ['end_header\n']
    
        # 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()
    

    【讨论】:

      猜你喜欢
      • 2015-02-12
      • 2021-10-25
      • 1970-01-01
      • 2021-05-30
      • 2021-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      相关资源
      最近更新 更多