2

I have an array of True/False values which I want to use as a repeating mask over another array of a different shape.

import numpy as np

mask = np.array([[ True, True],
                 [False, True]])

array = np.random.randint(10, size=(64, 64))

I want to apply this mask in a sliding window, similar to the where function on the array. Currently, I use np.kron to simply repeat the mask to match the dimensions of the array:

layout = np.ones((array.shape[0]//mask.shape[0], array.shape[1]//mask.shape[1]), dtype=bool)
mask = np.kron(layout, mask)
result = np.where(mask, array, 255) # example usage

Is there any elegant way to do this same operation, without repeating the mask into the same shape as array? I was hoping there would be some kind of sliding window technique or convolution/correlation.

Minn
  • 5,688
  • 2
  • 15
  • 42

2 Answers2

2

Use broadcasting with reshape so you wouldn't need extra memory for the repeated mask:

x, y = array.shape[0]// mask.shape[0], array.shape[1] // mask.shape[1]

result1 = np.where(mask[None, :, None], 
                  array.reshape(x, mask.shape[0], y, mask.shape[1]), 
                  255).reshape(array.shape)
Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
  • Woah, I have no idea how this works, but it seems to do what I was looking for. Guess I need to learn a lot more about shapes. Thank you :) – Minn Oct 25 '21 at 19:01
1

You could try with np.tile:

np.where(np.tile(mask, (a//m for a,m in zip(array.shape, mask.shape))), array, 255)
not_speshal
  • 22,093
  • 2
  • 15
  • 30
  • This seems to do the same as my solution with np.kron but a bit more efficiently, not exactly what I was looking for but still good to know. – Minn Oct 25 '21 at 19:05