2017-09-01 61 views
3

的每個二維切片我有3D numpy的陣列,例如,像這樣:填寫在隨機的地方塊上以3D陣列

array([[[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11], 
     [12, 13, 14, 15]], 

     [[16, 17, 18, 19], 
     [20, 21, 22, 23], 
     [24, 25, 26, 27], 
     [28, 29, 30, 31]]]) 

有沒有辦法來索引它,我選擇這樣的方式,例如,第一個平面中的2x2元素的右上角,以及第二個平面中的中心2x2元素子陣列?所以,我可以再歸零的元素2,3,6,7,21,22,25,26:

array([[[ 0, 1, 0, 0], 
     [ 4, 5, 0, 0], 
     [ 8, 9, 10, 11], 
     [12, 13, 14, 15]], 

     [[16, 17, 18, 19], 
     [20, 0, 0, 23], 
     [24, 0, 0, 27], 
     [28, 29, 30, 31]]]) 

我有一批圖像,我需要歸零的固定的小窗口大小,但在批次中的每個圖像的不同(隨機)位置。第一個維度是圖像的數量。

像這樣: 一個[:,X:X + 2,Y:Y + 2] = 0

其中x和y是具有對的每個第一尺寸不同的值的向量。

+0

@Abdou如前所述 - 「基本上我需要將固定大小的塊清零,但是對於我的數組中的每個平面,在不同的(隨機)位置。所以,不會有一個具體的輸出,但是OP是否可以列出其中一個可能的輸出。 – Divakar

+0

我更新了這個問題,希望更清楚我正在嘗試做什麼。 – MichaelSB

+0

@Divakar,*提取*和*歸零*是兩個不同的東西。這就是爲什麼我要求獲得預期產出。 – Abdou

回答

1

方法1: Here'e一種方法化的開展基於linear-indexing -

def random_block_fill_lidx(a, N, fillval=0): 
    # a is input array 
    # N is blocksize 

    # Store shape info 
    m,n,r = a.shape 

    # Get all possible starting linear indices for each 2D slice 
    possible_start_lidx = (np.arange(n-N+1)[:,None]*r + range(r-N+1)).ravel() 

    # Get random start indices from all possible ones for all 2D slices 
    start_lidx = np.random.choice(possible_start_lidx, m) 

    # Get linear indices for the block of (N,N) 
    offset_arr = (a.shape[-1]*np.arange(N)[:,None] + range(N)).ravel() 

    # Add in those random start indices with the offset array 
    idx = start_lidx[:,None] + offset_arr 

    # On a 2D view of the input array, use advance-indexing to set fillval. 
    a.reshape(m,-1)[np.arange(m)[:,None], idx] = fillval 
    return a 

方法2:下面是使用advanced-indexing另外,可能更有效的一個(對大型2D片) -

def random_block_fill_adv(a, N, fillval=0): 
    # a is input array 
    # N is blocksize 

    # Store shape info 
    m,n,r = a.shape 

    # Generate random start indices for second and third axes keeping proper 
    # distance from the boundaries for the block to be accomodated within. 
    idx0 = np.random.randint(0,n-N+1,m) 
    idx1 = np.random.randint(0,r-N+1,m) 

    # Setup indices for advanced-indexing. 

    # First axis indices would be simply the range array to select one per elem. 
    # We need to extend this to 3D so that the latter dim indices could be aligned. 
    dim0 = np.arange(m)[:,None,None] 

    # Second axis indices would idx0 with broadcasted additon of blocksized 
    # range array to cover all block indices along this axis. Repeat for third. 
    dim1 = idx0[:,None,None] + np.arange(N)[:,None] 
    dim2 = idx1[:,None,None] + range(N) 
    a[dim0, dim1, dim2] = fillval 
    return a 

方法3:隨着老信賴環 -

def random_block_fill_loopy(a, N, fillval=0): 
    # a is input array 
    # N is blocksize 

    # Store shape info 
    m,n,r = a.shape 

    # Generate random start indices for second and third axes keeping proper 
    # distance from the boundaries for the block to be accomodated within. 
    idx0 = np.random.randint(0,n-N+1,m) 
    idx1 = np.random.randint(0,r-N+1,m) 

    # Iterate through first and use slicing to assign fillval. 
    for i in range(m): 
     a[i, idx0[i]:idx0[i]+N, idx1[i]:idx1[i]+N] = fillval   
    return a 

採樣運行 -

In [357]: a = np.arange(2*4*7).reshape(2,4,7) 

In [358]: a 
Out[358]: 
array([[[ 0, 1, 2, 3, 4, 5, 6], 
     [ 7, 8, 9, 10, 11, 12, 13], 
     [14, 15, 16, 17, 18, 19, 20], 
     [21, 22, 23, 24, 25, 26, 27]], 

     [[28, 29, 30, 31, 32, 33, 34], 
     [35, 36, 37, 38, 39, 40, 41], 
     [42, 43, 44, 45, 46, 47, 48], 
     [49, 50, 51, 52, 53, 54, 55]]]) 

In [359]: random_block_fill_adv(a, N=3, fillval=0) 
Out[359]: 
array([[[ 0, 0, 0, 0, 4, 5, 6], 
     [ 7, 0, 0, 0, 11, 12, 13], 
     [14, 0, 0, 0, 18, 19, 20], 
     [21, 22, 23, 24, 25, 26, 27]], 

     [[28, 29, 30, 31, 32, 33, 34], 
     [35, 36, 37, 38, 0, 0, 0], 
     [42, 43, 44, 45, 0, 0, 0], 
     [49, 50, 51, 52, 0, 0, 0]]]) 

有趣的東西:正在就地灌裝,如果我們繼續運行random_block_fill_adv(a, N=3, fillval=0),我們將最終結束了所有的零a。因此,也驗證了代碼。


運行測試

In [579]: a = np.random.randint(0,9,(10000,4,4)) 

In [580]: %timeit random_block_fill_lidx(a, N=2, fillval=0) 
    ...: %timeit random_block_fill_adv(a, N=2, fillval=0) 
    ...: %timeit random_block_fill_loopy(a, N=2, fillval=0) 
    ...: 
1000 loops, best of 3: 545 µs per loop 
1000 loops, best of 3: 891 µs per loop 
100 loops, best of 3: 10.6 ms per loop 

In [581]: a = np.random.randint(0,9,(1000,40,40)) 

In [582]: %timeit random_block_fill_lidx(a, N=10, fillval=0) 
    ...: %timeit random_block_fill_adv(a, N=10, fillval=0) 
    ...: %timeit random_block_fill_loopy(a, N=10, fillval=0) 
    ...: 
1000 loops, best of 3: 739 µs per loop 
1000 loops, best of 3: 671 µs per loop 
1000 loops, best of 3: 1.27 ms per loop 

因此,要選擇哪一個取決於第一軸長度和塊大小。