You need a window view:
from numpy.lib.stride_tricks import as_strided arr = np.arange(1, 25).reshape(4, 6) % 10 sub_shape = (3, 3) view_shape = tuple(np.subtract(arr.shape, sub_shape) + 1) + sub_shape arr_view = as_strided(arr, view_shape, arr.strides * 2 arr_view = arr_view.reshape((-1,) + sub_shape) >>> arr_view array([[[[1, 2, 3], [7, 8, 9], [3, 4, 5]], [[2, 3, 4], [8, 9, 0], [4, 5, 6]], ... [[9, 0, 1], [5, 6, 7], [1, 2, 3]], [[0, 1, 2], [6, 7, 8], [2, 3, 4]]]])
A good part of this is that you are not copying any data, you are simply accessing the data in your original array differently. For large arrays, this can lead to huge memory savings.