I have an image.
I want to obtain a 3x3 window (neighbouring pixels) for every pixel in the image.
I have this Python code:
for x in range(2,
I think the following does what you are after. The loop is only over the 9 elements. I'm sure there is a way of vectorizing it, but it's probably not worth the effort.
import numpy
im = numpy.random.randint(0,50,(5,7))
# idx_2d contains the indices of each position in the array
idx_2d = numpy.mgrid[0:im.shape[0],0:im.shape[1]]
# We break that into 2 sub arrays
x_idx = idx_2d[1]
y_idx = idx_2d[0]
# The mask is used to ignore the edge values (or indeed any values).
mask = numpy.ones(im.shape, dtype='bool')
mask[0, :] = False
mask[:, 0] = False
mask[im.shape[0] - 1, :] = False
mask[:, im.shape[1] - 1] = False
# We create and fill an array that contains the lookup for every
# possible 3x3 array.
idx_array = numpy.zeros((im[mask].size, 3, 3), dtype='int64')
# Compute the flattened indices for each position in the 3x3 grid
for n in range(0, 3):
for m in range(0, 3):
# Compute the flattened indices for each position in the
# 3x3 grid
idx = (x_idx + (n-1)) + (y_idx + (m-1)) * im.shape[1]
# mask it, and write it to the big array
idx_array[:, m, n] = idx[mask]
# sub_images contains every valid 3x3 sub image
sub_images = im.ravel()[idx_array]
# Finally, we can flatten and sort each sub array quickly
sorted_sub_images = numpy.sort(sub_images.reshape((idx[mask].size, 9)))