我想制作给定二维数组的多个副本,并将它们存储为3D numpy数组的通道。目前,我有以下内容:将2D numpy阵列有效地复制为3D numpy阵列的通道?
finalOut=np.zeros((800,400,3))
output_frame=np.random.randn(800,400)
for i in range(finalOut.shape[-1]):
finalOut[:,:,i]=output_frame
这是可能的最快方式吗?
我想制作给定二维数组的多个副本,并将它们存储为3D numpy数组的通道。目前,我有以下内容:将2D numpy阵列有效地复制为3D numpy阵列的通道?
finalOut=np.zeros((800,400,3))
output_frame=np.random.randn(800,400)
for i in range(finalOut.shape[-1]):
finalOut[:,:,i]=output_frame
这是可能的最快方式吗?
def gks(frame):
finalOut=np.zeros((800,400,3))
for i in range(finalOut.shape[-1]):
finalOut[:,:,i]=frame
return finalOut
对于这个尺寸的代码只是作为tile
解决好:
In [52]: frame = np.random.randn(800,400)
In [61]: np.allclose(gks(frame), np.tile(frame[:,:,None],[1,1,3]))
Out[61]: True
In [62]: timeit np.tile(frame[:,:,None],[1,1,3]).shape
100 loops, best of 3: 9.36 ms per loop
In [63]: timeit gks(frame).shape
100 loops, best of 3: 9.36 ms per loop
的np.tile
代码使用repeat
(编译)进行复印,和reshape
前后适用于正确的形状(S)。
使用广播有多种方式,但它们似乎没有更快。
In [70]: timeit (frame[:,:,None]+np.zeros(3)).shape
100 loops, best of 3: 11.6 ms per loop
您的环路运行良好,因为与整个数组大小相比,大小3很小。
这里的东西更快:
def spl(frame):
finalOut=np.zeros((800,400,3))
finalOut[...]=frame[...,None]
return finalOut
In [105]: timeit spl(frame)
100 loops, best of 3: 5.54 ms per loop
我还在犹豫表明这一点,因为我认为这将是创建视图,而不是复印件。但初步测试表明它正在复制。
看看使用np.tile
。
>>> a = np.array([[1, 2, 3],
[4, 5, 6]])
>>> np.tile(a, (3, 1, 1))
array([[[1, 2, 3],
[4, 5, 6]],
[[1, 2, 3],
[4, 5, 6]],
[[1, 2, 3],
[4, 5, 6]]])
当然,这使渠道在第0轴,所以你可能要移动,使用np.transpose
算账:
>>> b = np.tile(a, (3, 1, 1))
>>> np.transpose(b, (1, 2, 0))
array([[[1, 1, 1],
[2, 2, 2],
[3, 3, 3]],
[[4, 4, 4],
[5, 5, 5],
[6, 6, 6]]])
>>> np.transpose(b, (1, 2, 0)).shape
(2, 3, 3)
测试
>>> d = np.transpose(b, (1, 2, 0))
>>> c = np.zeros((2, 3, 3))
>>> for i in range(3): c[:, :, i] = a[:, :]
>>> np.allclose(c, d)
True
最快的选择是经常使用numpy broadcasting,它允许你创建一个新的轴,直到必要时才使用它。例如:
>>> b = a[:, :, np.newaxis]
>>> b.shape
(2, 3, 1)
>>> b = b * np.array([1, 0, 0]) # Set G and B channels to 0.
>>> b
array([[[1, 0, 0],
[2, 0, 0],
[3, 0, 0]],
[[4, 0, 0],
[5, 0, 0],
[6, 0, 0]]])
然后,新的三维阵列是连构造直到操作是在通道进行。但是这需要一些时间来适应......
您也可以使用np.dstack
:
import numpy as np
def copy_dstack(frame):
return np.dstack((frame,)*3)
def copy_for(frame):
arr = np.zeros(shape=frame.shape + (3,))
for i in range(arr.shape[-1]):
arr[:, :, i] = frame
return arr
def copy_tile(frame):
return np.tile(frame[:, :, None], [1, 1, 3])
def copy_broadcasting(frame):
arr = np.zeros(shape=frame.shape + (3,))
arr[...] = frame[..., None]
return arr
根据我的测试由@hpaulj和@Praveen提出的方法是比你慢,而我的给你一个微不足道的速度增益:
In [244]: frame = np.random.randn(800, 400)
In [245]: %timeit copy_dstack(frame)
100 loops, best of 3: 4.07 ms per loop
In [246]: %timeit copy_for(frame)
100 loops, best of 3: 4.1 ms per loop
In [247]: %timeit copy_tile(frame)
100 loops, best of 3: 6.8 ms per loop
In [248]: %timeit copy_broadcasting(frame)
100 loops, best of 3: 6.71 ms per loop
我也检查了所有的方法产生相同的结果:
In [249]: np.allclose(copy_dstack(frame), copy_for(frame))
Out[249]: True
In [250]: np.allclose(copy_for(frame), copy_tile(frame))
Out[250]: True
In [251]: np.allclose(copy_tile(frame), copy_broadcasting(frame))
Out[251]: True
Loop'for i in range(fin alOut。形状[-1]):' - 最后尺寸的大小,而不是尺寸的数量(它们恰好都是3)。 – hpaulj
谢谢hpaulj。更正! – GKS