How to replace all RGB values in an Numpy Image Arrray based on an Target Pixel

Viewed 1035

I have an Image in an Numpy Array. I will replace an specific Color with Black and all others in White. For loops are to slow and my numpy condition ist not working.

All pixels that matches an array --> [121, 112, 131] must complete replace with another array --> [0, 0, 0]

All other with --> [255, 255, 255]

My results ends up with overseen pixels that matches with the First Channel [True, False, False]

Sorry for bad spelling, i hope my code ist better to understand.

My example result:

import numpy as np
from scipy import misc

file = misc.face()
img = np.array(file)

target_color = [121, 112, 131]
true_color = [0, 0, 0]
false_color = [255, 255, 255]

true_mask = np.all(img == target_color, axis=2)
false_mask = np.all(img != target_color, axis=2)

img[true_mask] = true_color
img[false_mask] = false_color

print(img)

Output:

array([[[  0,   0,   0],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       ...,

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [121, 157,  96],
        [255, 255, 255],
        [255, 255, 255]],

       [[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], dtype=uint8)

Problem:

There are Pixels left when the First Channel is equal to the target Color.

Target Pixel: [121, 112, 131]
Overseen Pixel: [121, 157,  96]
1 Answers

Your image shape is (768, 1024, 3). You want to make a mask of where it is equal to a 3-element array. You have found that a correct way to do this is

mask = np.all(img == target_color, axis=2)

This works because the shapes are broadcast from the rightmost dimension. You do not need to compute img != target to get the inverse mask:

false_mask = ~mask

But you won't need to do that. You can create the output array:

img = np.full_like(img, [255, 255, 255])

And you can set the masked elements:

img[mask, :] = [0, 0, 0]

The index : is important because you need to tell it to take everything along the third dimension, while the mask takes care of the first two.

Related