2

I'm trying to mark regions of an image array (224x224) to be ignored based on the value of a segmentation network's class mask (16x16). Previous processing means that unwanted regions will be labelled as -1. I want to be able to set the value of all regions of the image where the class mask reports -1 to some nonsense value (say, 999), but maintain the shape of the array (224x224). A concise example of what I mean is below, using a 4x4 image and 2x2 mask.

# prefilter
image = 1 2 3 4
        5 6 7 8
        9 1 2 3
        4 5 6 7

mask  = -1 4
        -1 5

# postfilter

image_filtered = 999 999 3 4
                 999 999 7 8
                 999 999 2 3
                 999 999 6 7

Is there an efficient way to do this modification?
3
  • Will the mask always be an integer multiple of the image? ie. image = 14x14, mask =7x7, not image =15x15, mask =6x6 Commented Jan 13, 2022 at 17:33
  • @LoneSurvivr Yes. I can control the size of the mask, but want to keep it roughly close to the network output (13x16), to reduce the possible error from upscaling. Commented Jan 13, 2022 at 17:43
  • Is the area masked always going to be a rectangle, or will it be freeform? Commented Jan 13, 2022 at 20:01

1 Answer 1

3

Here's some code I got to work. It does require the mask and the image to have the same aspect ratio, and be integer multiples of each others sizes.

import numpy as np

image = np.array([[1,2,3,4],
                  [5,6,7,8],
                  [9,1,2,3],
                  [4,5,6,7]])

mask = np.array([[-1,4],
                 [-1,5]])

def mask_image(image, mask, masked_value):
    
    scale_factor = image.shape[0]//mask.shape[0] # how much the mask needs to be scaled up by to match the image's size
    
    resized_mask = np.kron(mask, np.ones((scale_factor,scale_factor))) # resize the mask (magic)

    return(np.where((resized_mask==-1),masked_value,image)) # where the mask==-1, return the masked value, else return the value of the original array.
    
print(mask_image(image, mask, 999))

I used np.kron to resize an array after seeing this answer.

This function is extremely fast, it took ~2 sec to mask a 1920x1080 image with a 1920x1080 mask.

EDIT: Use what @Jérôme Richard said in their comment.

Sign up to request clarification or add additional context in comments.

2 Comments

~2 sec is not really "extremely fast". Did you mean something else? On my machine it takes 45 ms in this case which is quite good. Consider using resized_mask = mask.repeat(scale_factor,axis=0).repeat(scale_factor,axis=1) instead of a cryptic slow Kronecker product. This is about 3 times faster on the same 1920x1080 use-case (15 ms).
You're right, I edited my answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.