从数组到网格 PLY 文件

huangapple go评论70阅读模式
英文:

From array to mesh PLY file

问题

我有一个包含XYZ坐标的NumPy数组,表示一个点云。我想要使用plyfile创建一个PLY网格文件的列表以创建一个PLY网格文件。

vertex = [[52.45258174, 78.63234647, -0.90487998],
          [52.46268174, 78.68184647, 1.09133402],
          [52.48928449, 78.7930997, -0.90905187],
          [52.49938449, 78.84259974, 1.08716213],
          [52.5921233, 78.92200466, -0.91276864],
          [52.6022233, 78.97150466, 1.08344536]]

PLY_vertices = PlyElement.describe(np.array(vertex, dtype=[('x', 'f4'), ('y', 'f4'), ('z', 'f4')]), 'vertex')

ValueError: 仅支持一维数组
英文:

I have a numpy array containing XYZ coordinates representing a point cloud. I would like to create a mesh ply file using plyfile in a list in order to create a PLY mesh file.

 vertex = [[52.45258174 78.63234647 -0.90487998]
           [52.46268174 78.68184647 1.09133402]
           [52.48928449 78.7930997 -0.90905187]
           [52.49938449 78.84259974 1.08716213]
           [52.5921233 78.92200466 -0.91276864]
           [52.6022233 78.97150466 1.08344536]]

PLY_vertices = PlyElement.describe(np.array(vertex, dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4')]), 'vertex')

ValueError: only one-dimensional arrays are supported

答案1

得分: 2

以下是翻译好的代码部分:

# 如果一个zip对象可以满足需求
zip(arr1.flatten(), arr2.flatten(), arr3.flatten())

# 如果你需要一个ndarray
np.array(list(zip(arr1.flatten(), arr2.flatten(), arr3.flatten())))

首先将数组展平,然后创建所需的元组。

但是请注意,如果性能是一个问题,你应该考虑使用3xN或Nx3坐标数组来工作。

类似这样:

# 3xN数组
np.vstack((arr1.flatten(), arr2.flatten(), arr3.flatten()))

# Nx3数组
np.column_stack((arr1.flatten(), arr2.flatten(), arr3.flatten()))
英文:

Something like this should do the trick:

# If a zip object is okay
zip(arr1.flatten(), arr2.flatten(), arr3.flatten())

# If you want an ndarray
np.array(list(zip(arr1.flatten(), arr2.flatten(), arr3.flatten())))

It first flattens the arrays and then creates the required tuples.

However keep in mind that you should consider working with a 3xN or Nx3 coordinate array instead if performance is an issue.

something like:

# 3xN array
np.vstack((arr1.flatten(), arr2.flatten(), arr3.flatten()))

# Nx3 array
np.column_stack((arr1.flatten(), arr2.flatten(), arr3.flatten()))

答案2

得分: 1

https://pypi.org/project/plyfile/

展示了一些示例数组

vertex = numpy.array([(0, 0, 0),
                     (0, 1, 1),
                     (1, 0, 1),
                     (1, 1, 0)],
                     dtype=[('x', 'f4'), ('y', 'f4'),
                            ('z', 'f4')])
face = numpy.array([([0, 1, 2], 255, 255, 255),
                  ([0, 2, 3], 255,   0,   0),
                  ([0, 1, 3],   0, 255,   0),
                  ([1, 2, 3],   0,   0, 255)],
               dtype=[('vertex_indices', 'i4', (3,)),
                      ('red', 'u1'), ('green', 'u1'),
                      ('blue', 'u1')])

这些看起来可能像元组数组,但它们实际上是“结构化数组”。 dtype 部分很重要。

我们可以进一步探讨构建方法,但首先您需要提供上下文。

要创建结构化数组,数据必须是元组列表。

您的示例 - 一个二维数组:

vertex = np.array([[52.45258174, 78.63234647, -0.90487998],
           [52.46268174, 78.68184647, 1.09133402],
           [52.48928449, 78.7930997, -0.90905187],
           [52.49938449, 78.84259974, 1.08716213],
           [52.5921233, 78.92200466, -0.91276864],
           [52.6022233, 78.97150466, 1.08344536]])

将其转换为元组列表:

tups = [tuple(i) for i in vertex.tolist()]

现在创建结构化数组:

M = np.array(tups, dtype)

有一个可以执行此操作的实用函数:

import numpy.lib.recfunctions as rf
M = rf.unstructured_to_structured(vertex, dtype)

探索face结构:

face = np.array([([0, 1, 2], 255, 255, 255),
              ([0, 2, 3], 255,   0,   0),
              ([0, 1, 3],   0, 255,   0),
              ([1, 2, 3],   0,   0, 255)],
           dtype=[('vertex_indices', 'i4', (3,)),
                  ('red', 'u1'), ('green', 'u1'),
                  ('blue', 'u1')])

由于(3,),第一个字段返回一个二维数组:

face['vertex_indices']

rf函数可以处理这种嵌套dtype:

arr = rf.structured_to_unstructured(face)

因此,如果创建具有足够列数的二维数组,可以创建结构化数组,类似于face

rf.unstructured_to_structured(arr, face.dtype)

有时,通过创建具有所需大小和dtype的“零”数组,并逐个填充字段值,会更容易。rf函数中的许多函数采用了这种方法。通常,数组的记录比字段多得多,因此通过字段迭代来迭代不会损失太多速度。

M =  np.zeros(3, dtype=face.dtype)
M['vertex_indices'] = np.arange(9).reshape(3,3)
英文:

https://pypi.org/project/plyfile/

Shows some sample arrays

vertex = numpy.array([(0, 0, 0),
                     (0, 1, 1),
                     (1, 0, 1),
                     (1, 1, 0)],
                     dtype=[('x', 'f4'), ('y', 'f4'),
                        ('z', 'f4')])
face = numpy.array([([0, 1, 2], 255, 255, 255),
                  ([0, 2, 3], 255,   0,   0),
                  ([0, 1, 3],   0, 255,   0),
                  ([1, 2, 3],   0,   0, 255)],
               dtype=[('vertex_indices', 'i4', (3,)),
                       ('red', 'u1'), ('green', 'u1'),
                      ('blue', 'u1')])

Those might look like arrays of tuples, but those are actually structured arrays. The dtype part is impotant.

We can get into construction methods, but first you need to provide the context.

edit

To make a structured array, the data has to be list of tuples.

Your sample - a 2d array:

In [221]: vertex = np.array([[52.45258174, 78.63234647, -0.90487998],
     ...:            [52.46268174, 78.68184647, 1.09133402],
     ...:            [52.48928449, 78.7930997, -0.90905187],
     ...:            [52.49938449, 78.84259974, 1.08716213],
     ...:            [52.5921233, 78.92200466, -0.91276864],
     ...:            [52.6022233, 78.97150466, 1.08344536]])
     ...: 
     ...: dtype=[('x', 'f4'), ('y', 'f4'),('z', 'f4')]

In [222]: vertex
Out[222]: 
array([[52.45258174, 78.63234647, -0.90487998],
       [52.46268174, 78.68184647,  1.09133402],
       [52.48928449, 78.7930997 , -0.90905187],
       [52.49938449, 78.84259974,  1.08716213],
       [52.5921233 , 78.92200466, -0.91276864],
       [52.6022233 , 78.97150466,  1.08344536]])

convert it to a list of tuples:

In [223]: tups = [tuple(i) for i in vertex.tolist()]    
In [224]: tups
Out[224]: 
[(52.45258174, 78.63234647, -0.90487998),
 (52.46268174, 78.68184647, 1.09133402),
 (52.48928449, 78.7930997, -0.90905187),
 (52.49938449, 78.84259974, 1.08716213),
 (52.5921233, 78.92200466, -0.91276864),
 (52.6022233, 78.97150466, 1.08344536)]

Now make the structured array:

In [225]: M = np.array(tups, dtype)    
In [226]: M
Out[226]: 
array([(52.452583, 78.63235 , -0.90488   ),
       (52.46268 , 78.68185 ,  1.091334  ),
       (52.489285, 78.7931  , -0.9090519 ),
       (52.499386, 78.8426  ,  1.0871621 ),
       (52.592125, 78.922005, -0.91276866),
       (52.602222, 78.971504,  1.0834453 )],
      dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4')])    
In [227]: M.shape, M.dtype
Out[227]: ((6,), dtype([('x', '<f4'), ('y', '<f4'), ('z', '<f4')]))

There is also a utility function that can do this:

In [232]: import numpy.lib.recfunctions as rf    
In [233]: M = rf.unstructured_to_structured(vertex, dtype)

2nd edit

Exploring the face structure:

In [236]: face = np.array([([0, 1, 2], 255, 255, 255),
     ...:                   ([0, 2, 3], 255,   0,   0),
     ...:                   ([0, 1, 3],   0, 255,   0),
     ...:                   ([1, 2, 3],   0,   0, 255)],
     ...:                dtype=[('vertex_indices', 'i4', (3,)),
     ...:                        ('red', 'u1'), ('green', 'u1'),
     ...:                       ('blue', 'u1')])

In [237]: face
Out[237]: 
array([([0, 1, 2], 255, 255, 255), ([0, 2, 3], 255,   0,   0),
       ([0, 1, 3],   0, 255,   0), ([1, 2, 3],   0,   0, 255)],
      dtype=[('vertex_indices', '<i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

Because of (3,), the first field returns a 2d array:

In [238]: face['vertex_indices']
Out[238]: 
array([[0, 1, 2],
       [0, 2, 3],
       [0, 1, 3],
       [1, 2, 3]])

The rf functions can handle this nested dtype:

In [239]: arr = rf.structured_to_unstructured(face)

In [240]: arr
Out[240]: 
array([[  0,   1,   2, 255, 255, 255],
       [  0,   2,   3, 255,   0,   0],
       [  0,   1,   3,   0, 255,   0],
       [  1,   2,   3,   0,   0, 255]])

So if you make a 2d array with enough columns, you can create as face style of structured array:

In [241]: rf.unstructured_to_structured(arr, face.dtype)
Out[241]: 
array([([0, 1, 2], 255, 255, 255), ([0, 2, 3], 255,   0,   0),
       ([0, 1, 3],   0, 255,   0), ([1, 2, 3],   0,   0, 255)],
      dtype=[('vertex_indices', '<i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

Again, I'm just working from these few examples I pulled from the docs. I haven't studied the ply format in any depth.

Sometimes it's easier to create a 'zeros' array with desired size and dtype, and fill in field values individually. Many of the rf functions take this approach. Usually an array has many more records than fields, so we don't loose much speed by iterating on fields.

In [242]: M =  np.zeros(3, dtype=face.dtype)
In [243]: M
Out[243]: 
array([([0, 0, 0], 0, 0, 0), ([0, 0, 0], 0, 0, 0), ([0, 0, 0], 0, 0, 0)],
      dtype=[('vertex_indices', '<i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

In [244]: M['vertex_indices'] = np.arange(9).reshape(3,3)
In [245]: M
Out[245]: 
array([([0, 1, 2], 0, 0, 0), ([3, 4, 5], 0, 0, 0), ([6, 7, 8], 0, 0, 0)],
      dtype=[('vertex_indices', '<i4', (3,)), ('red', 'u1'), ('green', 'u1'), ('blue', 'u1')])

huangapple
  • 本文由 发表于 2023年6月16日 02:59:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76484752.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定