2 回答

TA贡献1883条经验 获得超3个赞
循环没有任何问题,但将列表附加到列表非常慢。为了避免这种情况,您可以为数据分配一个足够大的数组并在之后缩小它(或将数据复制到具有您需要的确切大小的数组中),或者您可以使用std:vector.
在这个答案中我使用,Numba因为我在高性能 Cython 编码方面没有经验,但 Cython 实现应该是直接的。Numba 也有一个有限的列表和元组内部表示,但我不知道 Cython 中是否可用。
例子
import numpy as np
import numba as nb
@nb.njit()
def get_image_data_arr(image_data):
array_text = np.empty((image_data.shape[0]*image_data.shape[1],2),dtype=np.int64)
ii=0
for y in range(image_data.shape[0]):
for x in range(image_data.shape[1]):
if image_data[y, x] < 210:
array_text[ii,0]=x
array_text[ii,1]=y
ii+=1
return array_text[:ii,:]
@nb.njit()
def get_image_data(image_data):
list_text = []
for y in range(image_data.shape[0]):
for x in range(image_data.shape[1]):
if image_data[y, x] < 210:
#appending lists
list_text.append([x, y])
#appending tuples
#list_text.append((x, y))
return list_text
时间安排
所有时间都没有编译开销(第一次调用函数被排除在时间之外)。
#Create some data
image_data=np.random.rand(1683*1240).reshape(1683,1240)*255
image_data=image_data.astype(np.uint8)
get_image_data (Pure Python) : 3.4s
get_image_data (naive Numba, appending lists) : 1.1s
get_image_data (naive Numba, appending tuples) : 0.3s
get_image_data_arr: : 0.012s
np.argwhere(image_data<210) : 0.035s

TA贡献1874条经验 获得超12个赞
我建议使用 Numpy 的argwhere()函数如下:
import numpy as np
# Create a starting image
im = np.arange(0,255,16).reshape(4,4)
看起来像这样:
array([[ 0, 16, 32, 48],
[ 64, 80, 96, 112],
[128, 144, 160, 176],
[192, 208, 224, 240]])
现在找到所有小于 210 的元素的坐标:
np.argwhere(im<210)
看起来像这样:
array([[0, 0],
[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 1],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[3, 0],
[3, 1]])
添加回答
举报