You can achieve this with a combination of np.reshape and np.swapaxes like this -
def extract_blocks(a, blocksize): M,N = a.shape b0, b1 = blocksize return a.reshape(M//b0,b0,N//b1,b1).swapaxes(1,2).reshape(-1,b0,b1)
Examples of examples
Let us use a sample input array, for example:
In [94]: a Out[94]: array([[2, 2, 6, 1, 3, 6], [1, 0, 1, 0, 0, 3], [4, 0, 0, 4, 1, 7], [3, 2, 4, 7, 2, 4], [8, 0, 7, 3, 4, 6], [1, 5, 6, 2, 1, 8]])
Now let me use some block sizes for testing. Let two cases be used with blocks from (2,3) and (3,3) .
Case No. 1:
In [95]: extract_blocks(a, (2,3)) # Blocksize : (2,3) Out[95]: array([[[2, 2, 6], [1, 0, 1]], [[1, 3, 6], [0, 0, 3]], [[4, 0, 0], [3, 2, 4]], [[4, 1, 7], [7, 2, 4]], [[8, 0, 7], [1, 5, 6]], [[3, 4, 6], [2, 1, 8]]])
Case No. 2:
In [96]: extract_blocks(a, (3,3)) # Blocksize : (3,3) Out[96]: array([[[2, 2, 6], [1, 0, 1], [4, 0, 0]], [[1, 3, 6], [0, 0, 3], [4, 1, 7]], [[3, 2, 4], [8, 0, 7], [1, 5, 6]], [[7, 2, 4], [3, 4, 6], [2, 1, 8]]])