Given an array of 2, 9x9 images with 2 channels shaped like this:
img1 = img1 = np.arange(162).reshape(9,9,2).copy()
img2 = img1 * 2
batch = np.array([img1, img2])
I need to slice each image into 3x3x2 (stride=3) regions and then locate and replace max elements of each slice. For the example above these elements are:
(:, 2, 2, :)
(:, 2, 5, :)
(:, 2, 8, :)
(:, 5, 2, :)
(:, 5, 5, :)
(:, 5, 8, :)
(:, 8, 2, :)
(:, 8, 5, :)
(:, 8, 8, :)
So far my solution is this:
batch_size, _, _, channels = batch.shape
region_size = 3
# For the (0, 0) region
region_slice = (slice(batch_size), slice(region_size), slice(region_size), slice(channels))
region = batch[region_slice]
new_values = np.arange(batch_size * channels)
# Flatten each channel of an image
region_3d = region.reshape(batch_size, region_size ** 2, channels)
region_3d_argmax = region_3d.argmax(axis=1)
region_argmax = (
np.repeat(np.arange(batch_size), channels),
*np.unravel_index(region_3d_argmax.ravel(), (region_size, region_size)),
np.tile(np.arange(channels), batch_size)
)
# Find indices of max element for each channel
region_3d_argmax = region_3d.argmax(axis=1)
# Manually unravel indices
region_argmax = (
np.repeat(np.arange(batch_size), channels),
*np.unravel_index(region_3d_argmax.ravel(), (region_size, region_size)),
np.tile(np.arange(channels), batch_size)
)
batch[region_slice][region_argmax] = new_values
There are two problems with this code:
- Reshaping
region
may return a copy instead of view - Manual unraveling
What is the better way to perform this operation?