英文:
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')])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论