2017-09-01 64 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 

因此,要选择哪一个取决于第一轴长度和块大小。