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]])
添加回答
舉報