2
import numpy as np
arr = np.array(range(60)).reshape(6,10)

arr

> 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, 56, 57, 58, 59]])

What I need:

select_random_windows(arr, number_of windows= 3, window_size=3)



>  array([[[ 1,  2,  3],
>            [11, 12, 13],
>            [21, 22, 23]],
>            
>            [37, 38, 39],
>            [47, 48, 49],
>            [57, 58, 59]],
>           
>            [31, 32, 33],
>            [41, 42, 43],
>            [51, 52, 53]]])

In this hypothetical case I'm selecting 3 windows of 3x3 within the main array (arr).

My actual array is a raster and I basically need a bunch (on the thousands) of little 3x3 windows.

Any help or even a hint will be much appreciated.

I actually haven't found any practical solution yet...since many many hours

THX!

Mario Fajardo
  • 620
  • 4
  • 8

2 Answers2

3

We can leverage np.lib.stride_tricks.as_strided based scikit-image's view_as_windows to get sliding windows. More info on use of as_strided based view_as_windows.

from skimage.util.shape import view_as_windows

def select_random_windows(arr, number_of_windows, window_size):
    # Get sliding windows
    w = view_as_windows(arr,window_size)

    # Store shape info
    m,n =  w.shape[:2]

    # Get random row, col indices for indexing into windows array
    lidx = np.random.choice(m*n,number_of_windows,replace=False)
    r,c = np.unravel_index(lidx,(m,n))
    # If duplicate windows are allowed, use replace=True or np.random.randint

    # Finally index into windows and return output
    return w[r,c]

Sample run -

In [209]: arr
Out[209]: 
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, 56, 57, 58, 59]])

In [210]: np.random.seed(0)

In [211]: select_random_windows(arr, number_of_windows=3, window_size=(2,4))
Out[211]: 
array([[[41, 42, 43, 44],
        [51, 52, 53, 54]],

       [[26, 27, 28, 29],
        [36, 37, 38, 39]],

       [[22, 23, 24, 25],
        [32, 33, 34, 35]]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Eventhough it worked (you got the kudos thx!) ..Just worried about some warning after assigning the resulting array : FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result. indexing_strides = arr_in[slices].strides – Mario Fajardo Oct 04 '18 at 08:44
  • 1
    @MarioFajardo That's a scikit-image specific thing. Try updating it or you can just ignore that warning. – Divakar Oct 04 '18 at 08:46
  • Champion..Thank you very much – Mario Fajardo Oct 04 '18 at 08:46
0

You can try [numpy.random.choice()][1]. It takes a 1D or an ndarray and creates a single element or an ndarray by sampling the elements from the given ndarray. You also have an option of providing the size of the array you want as the output.

Rahul Bohare
  • 762
  • 2
  • 11
  • 31