Trimming outside a numpy array

Given a 2d matrix, for example:

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

how can I select a window NxNaround this element so that the window is filled with an arbitrary (for example, average) value if it goes beyond the original array?

Example:

neighbors(A, x=0, y=0, N=3)

will give

array([[ 2.5,  2.5,  2.5],
       [ 2.5,    0,    1],
       [ 2.5,    4,    5]])
+4
source share
3 answers

You can pad your array. Filling will expand your array with the desired boundary conditions (see Parameter modefor all possible options):

>>> A = np.array([[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11],
                  [12, 13, 14, 15]])
>>> N = 5 # 5x5 windows
>>> B = np.pad(A, N//2, mode='reflect')
>>> B
array([[10,  9,  8,  9, 10, 11, 10,  9],
       [ 6,  5,  4,  5,  6,  7,  6,  5],
       [ 2,  1,  0,  1,  2,  3,  2,  1],
       [ 6,  5,  4,  5,  6,  7,  6,  5],
       [10,  9,  8,  9, 10, 11, 10,  9],
       [14, 13, 12, 13, 14, 15, 14, 13],
       [10,  9,  8,  9, 10, 11, 10,  9],
       [ 6,  5,  4,  5,  6,  7,  6,  5]])

As you can see, the original array is in the center of the matrix, supplemented by two rows and two columns ( N//2 = 5//2 = 2both from the left / right, and the bottom / top). Padded items are reflected.

, :

>>> x = 1; y = 1 # corresponds to number 5 in the original array
>>> B[y:y+N, x:x+N]
array([[ 5,  4,  5,  6,  7],
       [ 1,  0,  1,  2,  3],
       [ 5,  4,  5,  6,  7],
       [ 9,  8,  9, 10, 11],
       [13, 12, 13, 14, 15]])

, , .

+5

, :

def neighbors(arr, x, y, N):
    left = max(0, x - N)
    right = min(arr.shape[0], x + N)
    top = max(0, y - N)
    bottom = min(arr.shape[1], y + N)

    window = arr[left:right+1,top:bottom+1]
    fillval = window.mean()

    result = np.empty((2*N+1, 2*N+1))
    result[:] = fillval

    ll = N - x
    tt = N - y
    result[ll+left:ll+right+1,tt+top:tt+bottom+1] = window

    return result
+2

Here is one way with np.lib.padand np.ix_-

Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
Acut[np.isnan(Acut)] = np.nanmean(Acut)

Run Example -

In [76]: A
Out[76]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

In [77]: x=1; y=0; N = 3

In [78]: Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
    ...: Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
    ...: Acut[np.isnan(Acut)] = np.nanmean(Acut)
    ...: 

In [79]: Acut
Out[79]: 
array([[ 4.5,  0. ,  1. ],
       [ 4.5,  4. ,  5. ],
       [ 4.5,  8. ,  9. ]])
+2
source

Source: https://habr.com/ru/post/1607616/


All Articles