-1

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:

Purpose

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.

egjlmn1
  • 324
  • 3
  • 11

2 Answers2

1

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]])
ddejohn
  • 8,775
  • 3
  • 17
  • 30
  • Thanks, the max() won't work for me but the reduce will. I there a way to include it inside an array? What I actually have is an array, lets say n imgs, that each element in this array is the array of mask I talked about. So the shape is `(n,masksAmount,imgSize,imgSize)` and I want to turn it into `(n,imgSize,imgSize)`. Is there a way to do it? (Of course without list comprehension or something inefficient like this) – egjlmn1 Mar 25 '22 at 16:15
  • I'm not super clear on what you mean. If your example data is not accurate, please edit your original question with more representative sample data. – ddejohn Mar 25 '22 at 17:19
0

Here is a snippet code in pytorch. This code assumes that you want to merge multiple instance masks into one image while preserving the unique instances of the different objects in the different masks.

import torch
import torch.nn.functional as F
from PIL import Image

def merge_masks_with_instances(masks, instance_ids):
    # Create an empty tensor to store the merged masks
    merged_mask = torch.zeros_like(masks[0])

    # Iterate over each mask and its corresponding instance ID
    for instance_id, mask in zip(instance_ids, masks):
        # Apply the instance mask to the current mask
        instance_mask = torch.where(mask > 0, instance_id, torch.tensor(0))
        merged_mask = torch.max(merged_mask, instance_mask)

    return merged_mask

# Example usage
# Assuming you have three instance masks stored as tensors: mask1, mask2, mask3
mask1 = torch.tensor([[0, 1, 0], [1, 1, 0], [0, 0, 0]])
mask2 = torch.tensor([[0, 0, 1], [0, 1, 1], [1, 0, 0]])
mask3 = torch.tensor([[1, 0, 0], [0, 1, 0], [0, 1, 1]])

# Assuming you have a tensor representing the instance IDs
instance_ids = torch.tensor([1, 2, 3])

# Combine the instance masks into one merged mask
merged_mask = merge_masks_with_instances([mask1, mask2, mask3], instance_ids)

# Convert the merged mask tensor to a PIL image
merged_image = Image.fromarray((merged_mask * 255).byte().numpy(), mode='L')
merged_image.show()
rocksyne
  • 1,264
  • 15
  • 17