我想製作給定二維數組的多個副本,並將它們存儲爲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