2017-02-21 150 views
1

我想制作给定二维数组的多个副本,并将它们存储为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 

这是可能的最快方式吗?

+0

Loop'for i in range(fin alOut。形状[-1]):' - 最后尺寸的大小,而不是尺寸的数量(它们恰好都是3)。 – hpaulj

+0

谢谢hpaulj。更正! – GKS

回答

2
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 

我还在犹豫表明这一点,因为我认为这将是创建视图,而不是复印件。但初步测试表明它正在复制。

+0

我同意没有太多的速度增益范围 – GKS

+0

我发现一个更快的,我认为 – hpaulj

+0

谢谢hpaulj,它总体上看起来更快,但我得到的非常微不足道的速度增益。 – GKS

1

看看使用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]]]) 

然后,新的三维阵列是连构造直到操作是在通道进行。但是这需要一些时间来适应......

+0

不知道是否np.rollaxis(b,0,3)输出是我想要的。虽然形状现在是适当的,但是当我从我的方法和方法中减去最终输出时,绝对差异是巨大的 – GKS

+0

@GKS我编辑了我的答案以替代使用转置,并且我添加了一个测试以向您显示有用。这有帮助吗? – Praveen

+0

但它确实有帮助,但它仍然不会更快。非常感谢 – GKS

1

您也可以使用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