有没有办法使用 numpy 生成索引列表
Is there a way to generate a list of indices using numpy
例如,我可以使用 numpy 生成索引的重复模式吗?
0, 1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14, 15
或
0,1,2,1,2,3,4,5,6,5,6,7
我可以使用 numpy 中的方法生成范围内的这些列表吗?
目前我正在使用 python 中的列表来执行此操作,但我很好奇是否可以使用 numpy 来加快速度。
我不确定除了 numpy.arange 之外还有什么方法可以研究。
为了进一步说明,我正在以各种模式在 opengl 中生成三角形索引。
所以对于圆圈中的三角形,我有一些这样的代码。
for fan_set in range(0, len(self.vertices) / vertex_length, triangle_count):
for i in range(fan_set + 1, fan_set + 8):
self.indices.append(fan_set)
self.indices.append(i)
self.indices.append(i + 1)
我不确定我是否完全理解你的意思,但以下是我用来为 3D 点生成唯一索引的方法;
def indexate(points):
"""
Convert a numpy array of points into a list of indices and an array of
unique points.
Arguments:
points: A numpy array of shape (N, 3).
Returns:
An array of indices and an (M, 3) array of unique points.
"""
pd = {}
indices = [pd.setdefault(tuple(p), len(pd)) for p in points]
pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])
unique = np.array([i[1] for i in pt])
return np.array(indices, np.uint16), unique
您可以在 github 上找到 this code in my stltools 包。
它是这样工作的;
In [1]: import numpy as np
In [2]: points = np.array([[1,0,0], [0,0,1], [1,0,0], [0,1,0]])
In [3]: pd = {}
In [4]: indices = [pd.setdefault(tuple(p), len(pd)) for p in points]
In [5]: indices
Out[5]: [0, 1, 0, 2]
In [6]: pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])
In [7]: pt
Out[7]: [(0, (1, 0, 0)), (1, (0, 0, 1)), (2, (0, 1, 0))]
In [8]: unique = np.array([i[1] for i in pt])
In [9]: unique
Out[9]:
array([[1, 0, 0],
[0, 0, 1],
[0, 1, 0]])
关键点(如果你会原谅双关语的话)是使用点的元组(因为元组是不可变的,因此是可散列的)作为字典中的键 setdefault
方法,而 dict
的长度就是值。实际上,该值是第一次看到此 确切 点。
我不是 100% 确定这就是你想要的,我认为你可以使用一对 range
值并增加 n
3 倍(每组之间的差距)来实现这一点,然后使用 numpy.concatenate
连接最终数组,如下所示:
import numpy as np
def gen_list(n):
return np.concatenate([np.array(range(i, i+3) + range(i+1, i+4)) + i*3
for i in xrange(n)])
用法:
gen_list(2)
Out[16]: array([0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7])
gen_list(3)
Out[17]:
array([ 0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7, 8, 9, 10, 9, 10,
11])
list(gen_list(2))
Out[18]: [0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7]
在我的示例中,我只使用 n
作为您要生成的组数,您可以更改它以满足您的三角形要求。
您的第一个示例可以通过 numpy 方法生成为:
In [860]: np.concatenate((np.zeros((3,1),int),np.arange(1,16).reshape(3,5)),axis=1).ravel()
Out[860]:
array([ 0, 1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14,
15])
那是因为我看到了这个 2d 重复模式
array([[ 0, 1, 2, 3, 4, 5],
[ 0, 6, 7, 8, 9, 10],
[ 0, 11, 12, 13, 14, 15]])
第二个模式可以由这个二维数组的ravel
生成(通过广播2个数组生成):
In [863]: np.array([0,1,4,5])[:,None]+np.arange(3)
Out[863]:
array([[0, 1, 2],
[1, 2, 3],
[4, 5, 6],
[5, 6, 7]])
我可以生成第一个模式,但在第二个模式上有变化(0 的初始列破坏了模式)
I=np.array([0,5,10])[:,None]+np.arange(0,6)
I[:,0]=0
我认为你的双循环可以表示为列表推导式
In [872]: np.array([ [k,i,i+1] for k in range(0,1,1) for i in range(k+1,k+8)]).ravel()
Out[872]: array([0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8])
或者没有解开:
array([[0, 1, 2],
[0, 2, 3],
[0, 3, 4],
[0, 4, 5],
[0, 5, 6],
[0, 6, 7],
[0, 7, 8]])
虽然我不知道是什么参数产生了你的例子。
例如,我可以使用 numpy 生成索引的重复模式吗?
0, 1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14, 15
或
0,1,2,1,2,3,4,5,6,5,6,7
我可以使用 numpy 中的方法生成范围内的这些列表吗?
目前我正在使用 python 中的列表来执行此操作,但我很好奇是否可以使用 numpy 来加快速度。
我不确定除了 numpy.arange 之外还有什么方法可以研究。
为了进一步说明,我正在以各种模式在 opengl 中生成三角形索引。
所以对于圆圈中的三角形,我有一些这样的代码。
for fan_set in range(0, len(self.vertices) / vertex_length, triangle_count):
for i in range(fan_set + 1, fan_set + 8):
self.indices.append(fan_set)
self.indices.append(i)
self.indices.append(i + 1)
我不确定我是否完全理解你的意思,但以下是我用来为 3D 点生成唯一索引的方法;
def indexate(points):
"""
Convert a numpy array of points into a list of indices and an array of
unique points.
Arguments:
points: A numpy array of shape (N, 3).
Returns:
An array of indices and an (M, 3) array of unique points.
"""
pd = {}
indices = [pd.setdefault(tuple(p), len(pd)) for p in points]
pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])
unique = np.array([i[1] for i in pt])
return np.array(indices, np.uint16), unique
您可以在 github 上找到 this code in my stltools 包。
它是这样工作的;
In [1]: import numpy as np
In [2]: points = np.array([[1,0,0], [0,0,1], [1,0,0], [0,1,0]])
In [3]: pd = {}
In [4]: indices = [pd.setdefault(tuple(p), len(pd)) for p in points]
In [5]: indices
Out[5]: [0, 1, 0, 2]
In [6]: pt = sorted([(v, k) for k, v in pd.items()], key=lambda x: x[0])
In [7]: pt
Out[7]: [(0, (1, 0, 0)), (1, (0, 0, 1)), (2, (0, 1, 0))]
In [8]: unique = np.array([i[1] for i in pt])
In [9]: unique
Out[9]:
array([[1, 0, 0],
[0, 0, 1],
[0, 1, 0]])
关键点(如果你会原谅双关语的话)是使用点的元组(因为元组是不可变的,因此是可散列的)作为字典中的键 setdefault
方法,而 dict
的长度就是值。实际上,该值是第一次看到此 确切 点。
我不是 100% 确定这就是你想要的,我认为你可以使用一对 range
值并增加 n
3 倍(每组之间的差距)来实现这一点,然后使用 numpy.concatenate
连接最终数组,如下所示:
import numpy as np
def gen_list(n):
return np.concatenate([np.array(range(i, i+3) + range(i+1, i+4)) + i*3
for i in xrange(n)])
用法:
gen_list(2)
Out[16]: array([0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7])
gen_list(3)
Out[17]:
array([ 0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7, 8, 9, 10, 9, 10,
11])
list(gen_list(2))
Out[18]: [0, 1, 2, 1, 2, 3, 4, 5, 6, 5, 6, 7]
在我的示例中,我只使用 n
作为您要生成的组数,您可以更改它以满足您的三角形要求。
您的第一个示例可以通过 numpy 方法生成为:
In [860]: np.concatenate((np.zeros((3,1),int),np.arange(1,16).reshape(3,5)),axis=1).ravel()
Out[860]:
array([ 0, 1, 2, 3, 4, 5, 0, 6, 7, 8, 9, 10, 0, 11, 12, 13, 14,
15])
那是因为我看到了这个 2d 重复模式
array([[ 0, 1, 2, 3, 4, 5],
[ 0, 6, 7, 8, 9, 10],
[ 0, 11, 12, 13, 14, 15]])
第二个模式可以由这个二维数组的ravel
生成(通过广播2个数组生成):
In [863]: np.array([0,1,4,5])[:,None]+np.arange(3)
Out[863]:
array([[0, 1, 2],
[1, 2, 3],
[4, 5, 6],
[5, 6, 7]])
我可以生成第一个模式,但在第二个模式上有变化(0 的初始列破坏了模式)
I=np.array([0,5,10])[:,None]+np.arange(0,6)
I[:,0]=0
我认为你的双循环可以表示为列表推导式
In [872]: np.array([ [k,i,i+1] for k in range(0,1,1) for i in range(k+1,k+8)]).ravel()
Out[872]: array([0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8])
或者没有解开:
array([[0, 1, 2],
[0, 2, 3],
[0, 3, 4],
[0, 4, 5],
[0, 5, 6],
[0, 6, 7],
[0, 7, 8]])
虽然我不知道是什么参数产生了你的例子。