Вы можете использовать малоизвестные приемы шага, чтобы создать представление вашего изображения, состоящего из блоков.Это очень быстро и не требует дополнительной памяти (пример немного подробный):
import numpy as np
#img = np.array(Image.open(filename), dtype='uint8')
w, h = 5, 4 # width, height of image
bw, bh = 2, 3 # width, height of blocks
img = np.random.randint(2, size=(h, w)) # create a random binary image
# build a blocky view of the image data
sz = img.itemsize # size in bytes of the elements in img
shape = (h-bh+1, w-bw+1, bh, bw) # the shape of the new array: two indices for the blocks,
# two indices for the content of each block
strides = (w*sz, sz, w*sz, sz) # information about how to map indices to image data
blocks = np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
# now we can access the blocks
print img
[[1 1 0 0 0]
[0 1 1 0 0]
[0 0 1 0 1]
[1 0 1 0 0]]
print blocks[0,0]
[[1 1]
[0 1]
[0 0]]
print blocks[1,2]
[[1 0]
[1 0]
[1 0]]