2014-05-01 2 views
4

Мне часто приходится складывать 2d массивы numpy (tiff images). Для этого я сначала добавлю их в список и использую np.dstack. Это, по-видимому, самый быстрый способ получить 3D-массивы, складывающие изображения. Но есть ли более быстрый/эффективный с точки зрения памяти способ?стек изображений как numpy массив быстрее (чем preallocation)?

from time import time 
import numpy as np 

# Create 100 images of the same dimention 256x512 (8-bit). 
# In reality, each image comes from a different file 
img = np.random.randint(0,255,(256, 512, 100)) 

t0 = time() 
temp = [] 
for n in range(100): 
    temp.append(img[:,:,n]) 
stacked = np.dstack(temp) 
#stacked = np.array(temp) # much slower 3.5 s for 100 

print time()-t0 # 0.58 s for 100 frames 
print stacked.shape 

# dstack in each loop is slower 
t0 = time() 
temp = img[:,:,0] 
for n in range(1, 100): 
    temp = np.dstack((temp, img[:,:,n])) 
print time()-t0 # 3.13 s for 100 frames 
print temp.shape 

# counter-intuitive but preallocation is slightly slower 
stacked = np.empty((256, 512, 100)) 
t0 = time() 
for n in range(100): 
    stacked[:,:,n] = img[:,:,n] 
print time()-t0 # 0.651 s for 100 frames 
print stacked.shape 

# (Edit) As in the accepted answer, re-arranging axis to mainly use 
# the first axis to access data improved the speed significantly. 
img = np.random.randint(0,255,(100, 256, 512)) 

stacked = np.empty((100, 256, 512)) 
t0 = time() 
for n in range(100): 
    stacked[n,:,:] = img[n,:,:] 
print time()-t0 # 0.08 s for 100 frames 
print stacked.shape 
+0

Вы можете избежать вызова 'dstack' гарантируя, что все массивы в 'temp', если это условие выполнено, вы можете просто вызвать' stacked = np.concatenate (temp, axis = 2) ', что может сэкономить небольшое количество времени в служебных данных python. Если вы показываете больше кода, может быть лучший способ сделать это, но, как показано, верхний код практически оптимален. – Daniel

+0

Массивы в temp все 2D, и я хочу объединиться, чтобы получить 3D-массив. Таким образом, np.concatenate (temp, axis = 2) вызовет ошибку: ось 2 выходит за пределы [0, 2). np.concatenate (temp, axis = 1) создаст 2D-массив (256x51200). – otterb

+0

Я пропустил критическую часть моего комментария, он должен был прочитать «... все массивы в« temp »являются 3D, если это условие выполнено». Следует отметить, что эта экономия тривиальна, за исключением очень больших размеров temp, вероятно, порядка ~ 2us на массив. – Daniel

ответ

3

После некоторых совместных усилий с otterb, мы пришли к выводу, что предварительное выделение из массива является путь. По-видимому, узким местом для убийства производительности был макет массива с номером изображения (n), который является самым быстро меняющимся индексом. Если мы п первого индекс массива (который будет по умолчанию упорядочения «C»: первый индекс изменяет медленный, последний индекс изменяется быстро), мы получаем лучшую производительность:

from time import time 
import numpy as np 

# Create 100 images of the same dimention 256x512 (8-bit). 
# In reality, each image comes from a different file 
img = np.random.randint(0,255,(100, 256, 512)) 

# counter-intuitive but preallocation is slightly slower 
stacked = np.empty((100, 256, 512)) 
t0 = time() 
for n in range(100): 
    stacked[n] = img[n] 
print time()-t0 
print stacked.shape 
+0

Спасибо! Я также думал, что preallocation должен быть самым быстрым, но как-то он был немного медленнее. Я обновил свой вопрос, чтобы включить preallocation. Любая идея почему? – otterb

+0

Привет, это очень интересно, я бы поспорил, что это быстрее. Скажите, можете ли вы попробовать, если это имеет значение, когда вы ставите индекс времени как первый (идея состоит в том, что доступ к кускам можно получить легче). Угадайте, почему это может быть медленнее, поскольку индексирование массивов имеет некоторые накладные расходы, что позволяет, например, отрицательные числа. С помощью cython вы можете избавиться от этих ... – Magellan88

+0

Вы имеете в виду stacked [n,:,:] вместо stacked [:,:, n]? Хорошая идея. Я попробую, когда у меня будет доступ к тому же компьютеру, который я использовал для профилирования. – otterb

Смежные вопросы