Can I use the reshape + transpose trick to create tiling with overlap?

Viewed 143

I have a very large array that I would like tile with overlap. For example, if the array looks like

a b c d e
f g h i j
k l m n o
p q r s t
u v w x y

I want to break it up into 3 x 3 tiles, where each tile overlaps its neighbor by 1 on each side:

a b c    c d e
f g h    h i j
k l m    m n o

k l m    m n o
p q r    r s t
u v w    w x y

The "reshape and transpose trick" (described in https://www.kaggle.com/c/hubmap-kidney-segmentation/discussion/202171) is an approach for tiling a large array in Python (and other languages) that allows abutting (not overlapping) tiles to be extracted and represented without having to copy the underlying data array.

What I'm wondering is: Can this trick be used if we want to tiles to overlap, as shown above? If so, how?

1 Answers

I don't think this can be done through reshaping alone, but it can be done using the lower-level numpy.lib.stride_tricks.as_strided function, carefully setting the shape and strides parameters:

>>> x = np.arange(25).reshape(5, 5)

>>> x
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]])

>>> y = np.lib.stride_tricks.as_strided(x, shape=(2, 2, 3, 3),
...                                     strides=(80, 16, 40, 8))

>>> y
array([[[[ 0,  1,  2],
         [ 5,  6,  7],
         [10, 11, 12]],

        [[ 2,  3,  4],
         [ 7,  8,  9],
         [12, 13, 14]]],


       [[[10, 11, 12],
         [15, 16, 17],
         [20, 21, 22]],

        [[12, 13, 14],
         [17, 18, 19],
         [22, 23, 24]]]])

The second array is split into overlapping tiles, and you can confirm that the two arrays share the same memory:

>>> np.byte_bounds(x) == np.byte_bounds(y)
True
Related