Artem Shalagin
Artem Shalagin

Reputation: 157

Numpy condition on a vector rather than an element

I have a numpy array that represents an image, it's dimensions are (w, h, 4), 4 is for RGBA. Now I want to replace all white pixels with transparent pixels. I wish I could do something like np.where(pic == np.array([255, 255, 255, 255]), np.array([0, 0, 0, 0]), pic) but this exact code obviously doesn't work: pic == something compares every element of pic with something so I'll just get a (w, h, 4) array of False-s. What is the canonical way to conditionally replace not just an element but a whole vector in a numpy array?

Upvotes: 0

Views: 378

Answers (2)

Sina Meftah
Sina Meftah

Reputation: 131

pic[np.all(pic[: , : , : ] == 255, axis=-1), :] = 0

Instead of 0 you can also give it an array like np.arange(pic.shape[-1])

Instead of the fourth : you can give whatever number of the last dimension you want, since you wanted to replace all the elements along the last axis, I inserted :. If for example you wanted to only change transparency at those points you could've written:

pic[np.all(pic[: , : , : ] == 255, axis=-1), 4] = 0

So by this one you've practically only made those white points transparent, instead of making them a transparent black.

Upvotes: 1

swag2198
swag2198

Reputation: 2696

You can simply use np.all() like this:

old = [255, 255, 255, 255]
new = [0, 0, 0, 0]

# pic is your (w, h, 4) shaped array
pic[np.all(pic == old, axis = -1)] = new

Here pic == old still gives you a (w, h, 4) dimensional boolean numpy array, but ANDing along the innermost axis (-1) reduces it to (w, h) shape where each [i, j] location is True or False based on whether the original RGBA value was equal to old.

Upvotes: 1

Related Questions