It sounds like you have an array of pixels with shape (10, 10), and want to slide a window of shape (2, 5) across the array, performing an operation at each position.
NumPy has operations to help with this (see here:
https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.sliding_window_view.html), however the documentation says sliding_window_view is generic and thus nonoptimal for your case. They suggest using scipy.ndimage operations instead, which I have shown examples of below. https://docs.scipy.org/doc/scipy/reference/reference/generated/scipy.ndimage.generic_filter.html
To start, I have imported the packages and defined a 10x10 array and 2x5 filter size.
>>> import numpy as np
>>> from scipy.ndimage import generic_filter
>>> selectedROI = np.array(range(100)).reshape((10, 10))
>>> selectedROI
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],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
>>> filter_size = (2, 5)
Any function can be applied in sliding-window fashion with generic_filter (np.average used here). Variables a,b,c,d were chosen because generic_filter produces values for all positions in your input array, including positions where the window does not fall entirely within the input array. For an explanation of the "or None" in the slicing, see here:
numpy negative indexing a[:-0]
>>> a = filter_size[0]//2
>>> b = (1 - filter_size[0]%2) - (filter_size[0]//2)
>>> c = filter_size[1]//2
>>> d = (1 - filter_size[1]%2) - (filter_size[1]//2)
>>> generic_filter(selectedROI, np.average, filter_size)[a:b or None, c:d or None]
array([[ 7, 8, 9, 10, 11, 12],
[17, 18, 19, 20, 21, 22],
[27, 28, 29, 30, 31, 32],
[37, 38, 39, 40, 41, 42],
[47, 48, 49, 50, 51, 52],
[57, 58, 59, 60, 61, 62],
[67, 68, 69, 70, 71, 72],
[77, 78, 79, 80, 81, 82],
[87, 88, 89, 90, 91, 92]])
You can use other functions, such as np.min and np.max for your use case, or write your own custom functions as shown here: How do I use scipy.ndimage.filters.gereric_filter?
>>> generic_filter(selectedROI, np.min, filter_size)[a:b or None, c:d or None]
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55],
[60, 61, 62, 63, 64, 65],
[70, 71, 72, 73, 74, 75],
[80, 81, 82, 83, 84, 85]])
>>> generic_filter(selectedROI, np.max, filter_size)[a:b or None, c:d or None]
array([[14, 15, 16, 17, 18, 19],
[24, 25, 26, 27, 28, 29],
[34, 35, 36, 37, 38, 39],
[44, 45, 46, 47, 48, 49],
[54, 55, 56, 57, 58, 59],
[64, 65, 66, 67, 68, 69],
[74, 75, 76, 77, 78, 79],
[84, 85, 86, 87, 88, 89],
[94, 95, 96, 97, 98, 99]])
These examples used 2D arrays for clarity, but the operations should extend to 3D pixel arrays.