I have an array of 2d masks that looks something like this:
[
#mask0
[[0.3,0.3],
[0,0]],
#mask1
[[0.4,0],
[0.4,0.4]]
]
And I want to merge the masks one after another, where every mask overrides the mask before it, (I don't want the sum of all masks). By override, I mean that if the value of the second mask wasn't 0, it will set the new value, otherwise keep what it was from the previous masks. So for this example, the result will be
[[0.4,0.3],
[0.4,0.4]]]
Of course, In my case I don't have only 2 masks 2x2, I have multiple masks in a larger scale, this was just to demonstrate.
The masks represent circles in some grayscale value and I want to paste them one on top of another. Like this:
How can I achieve this using NumPy with a clean and efficient code? And if there is a different way to approach this I'd love to hear it too.
CodePudding user response:
If you have a 3D array of masks arranged along the first axis, you can reduce along the first axis and merge your masks with np.where
:
In [2]: import functools
In [3]: functools.reduce(lambda m0, m1: np.where(m1 == 0, m0, m1), masks)
Out[3]:
array([[0.4, 0.3],
[0.4, 0.4]])
CodePudding user response:
If you have multiple images and you want apply on each image, you can use apply_along_axis
like below:
from functools import reduce
images = np.random.rand(10, 4, 64, 64) # (n,masksAmount,imgSize,imgSize)
print(images.shape)
def apply_mask(image):
image = reduce(lambda m0, m1: np.where(m1 == 0, m0, m1), image)
return image
images = np.apply_along_axis(apply_mask, 1, images) # (n,imgSize,imgSize)
print(images.shape)
Output:
(10, 4, 64, 64) # shape
(10, 64, 64) # shape
Example
image = np.array([[[0.3, 0.3], [0, 0]], [[0.4, 0], [0.4, 0.4]]])
images = np.repeat(image[None,...],4,0)
print(images.shape)
images = np.apply_along_axis(apply_mask, 1, images)
print(images.shape)
print(images)
Output:
(4, 2, 2, 2) # (n,masksAmount,imgSize,imgSize)
(4, 2, 2) # (n,imgSize,imgSize)
# images =>
[[[0.4 0.3]
[0.4 0.4]]
[[0.4 0.3]
[0.4 0.4]]
[[0.4 0.3]
[0.4 0.4]]
[[0.4 0.3]
[0.4 0.4]]]