0

I have a numpy array representing an image (but for now assume the image only has a single channel).

i = np.arange(5*5*1).reshape((5, 5))
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]])

I also have a rather large list of pre-computed slices of this array in the format [start_axis_0, end_axis_0, start_axis_1, end_axis_1] (for now just assume I have two)

p = [[0, 2, 0, 2], [0, 2, 1, 3]]

This represents the two corresponding patches from i

i[0:2, 0:2]
array([[0, 1],
       [5, 6]])
i[0:2, 1:3]
array([[1, 2],
       [6, 7]])

To calculate these patches I am currently iterating over p and "applying" the slices.

for pp in p:
    print(i[pp[0]:pp[1], pp[2]:pp[3]])
[[0 1]
 [5 6]]
[[1 2]
 [6 7]]

I know that there is some way that I can "directly apply" all of the slices at once using something like i[(Ellipsis, *p)] but I don't think my p definition is correct.

How can I get the slices defined in p from i in the current data structure of p? The is where p is represented as [start_axis_0, end_axis_0, start_axis_1, end_axis_1]. Specifically, in the case that i has an actual third dimension, i.e. i.shape = (5, 5, 3).


EDIT: The result I would like is

np.array([[[0,1],[5,6]],[[1,2],[6,7]]])

Also, all slices in p are guaranteed to be the same shape. So the result will not be a jagged array.

KDecker
  • 6,928
  • 8
  • 40
  • 81
  • What exactly do you mean by "get the slices"? Do you want a list such that each element of the list is one of these slices? – Ben Grossmann Oct 03 '22 at 00:58
  • @BenGrossmann by "get the slices" I mean get the subset of `i` that represents the slice in `p`. So yes, essentially a `list` or `array`. In the example in the post I'd want the result `r = np.array([[[0,1],[5,6]], [[1,2],[6,7]]])` – KDecker Oct 03 '22 at 01:12

1 Answers1

2

If all slices have a fixed shape you can try this:

import numpy as np

a = np.arange(5*5*1).reshape((5, 5))
p = [[0, 2, 0, 2], [0, 2, 1, 3]]
slice_shape = (2, 2)

# since the slice shape is fixed, only the coordinates of
# the upper left corner of each slice are needed 
idx = tuple(zip(*[(t[0], t[2]) for t in p]))

result = np.lib.stride_tricks.sliding_window_view(a, slice_shape)[idx]
print(result)

It gives:

[[[0 1]
  [5 6]]

 [[1 2]
  [6 7]]]
bb1
  • 7,174
  • 2
  • 8
  • 23