Python 将图像堆叠为numpy阵列是否比预分配更快?
我经常需要堆叠2d numpy阵列(tiff图像)。为此,我首先将它们附加到一个列表中,并使用np.dstack。这似乎是获得3D阵列堆叠图像的最快方法。但是,有没有更快/内存效率更高的方法Python 将图像堆叠为numpy阵列是否比预分配更快?,python,arrays,image,numpy,Python,Arrays,Image,Numpy,我经常需要堆叠2d numpy阵列(tiff图像)。为此,我首先将它们附加到一个列表中,并使用np.dstack。这似乎是获得3D阵列堆叠图像的最快方法。但是,有没有更快/内存效率更高的方法 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
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
在与otterb共同努力后,我们得出结论,阵列的预分配是可行的。显然,性能瓶颈是阵列布局,图像编号(n)是变化最快的索引。如果我们将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
通过保证
temp
中的所有数组都满足此条件,可以避免调用dstack
。如果满足此条件,只需调用stacked=np.concatenate(temp,axis=2)
,这可能会节省python开销中的少量时间。如果显示更多代码,可能有更好的方法,但如图所示,最上面的代码几乎是最佳的。temp中的数组都是二维的,我想连接起来得到一个三维数组。因此,np.concatenate(temp,axis=2)将产生一个错误:axis 2超出界限[0,2]。np.concatenate(temp,axis=1)将创建一个2D数组(256x51200)。我遗漏了我的评论的一个关键部分,它应该是这样写的:“…如果满足此条件,temp
中的所有数组都是3D的…”。应该注意的是,除了非常大的临时大小外,这种节省是微不足道的,可能每个阵列约为2 US。谢谢!我还认为预分配应该是最快的,但不知怎的,它稍微慢了一些。我更新了我的问题,将预分配包括在内。知道为什么吗?嗨,这确实非常有趣,我敢打赌它是fas比如说,当你把时间索引作为第一个索引时,你能试试看它是否有什么不同吗(这个想法是你写的块可以更容易地访问)。猜测一下为什么它可能会慢一些,因为数组的索引有一些开销,例如允许负数。有了cython,你可以去掉这些…你的意思是堆叠的[n,:,:]而不是堆叠[:,:,n]好主意。当我有机会使用我用来评测的那台电脑时,我会试试。是的!我按照你的建议重新排列了轴。现在速度明显快了。我已经接受了你的答案,但是,你可以修改你的答案来澄清第一个轴吗?嗨,奥特布,谢谢你的努力。真的很高兴它能工作。我必须说我也学到了一些从这件事。我把答案的形式,应该是有益于其他人,以及反映你的贡献。你愿意提供你得到的性能,以便我们可以把它也放在那里?