Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select all non-black pixels in a NumPy array?

I am trying to get a list of an image's pixels that are different from a specific color using NumPy.

For example, while processig the following image:

enter image description here

I've managed to get a list of all black pixels using:

np.where(np.all(mask == [0,0,0], axis=-1))

But when I try to do:

np.where(np.all(mask != [0,0,0], axis=-1))

I get a pretty strange result:

enter image description here

It looks like NumPy has returned only the indices were R, G, and B are non-0

Here is a minimal example of what I'm trying to do:

import numpy as np
import cv2

# Read mask
mask = cv2.imread("path/to/img")
excluded_color = [0,0,0]

# Try to get indices of pixel with different colors
indices_list = np.where(np.all(mask != excluded_color, axis=-1))

# For some reason, the list doesn't contain all different colors
print("excluded indices are", indices_list)

# Visualization
mask[indices_list] = [255,255,255]

cv2.imshow(mask)
cv2.waitKey(0)
like image 911
ofir dubi Avatar asked Oct 10 '18 07:10

ofir dubi


People also ask

How do you clear an entire NumPy array?

Using the NumPy function np. delete() , you can delete any row and column from the NumPy array ndarray . Specify the axis (dimension) and position (row number, column number, etc.). It is also possible to select multiple rows and columns using a slice or a list.

How do I select an array in NumPy?

To select an element from Numpy Array , we can use [] operator i.e. It will return the element at given index only.

How is NumPy array different from normal array?

There are several important differences between NumPy arrays and the standard Python sequences: NumPy arrays have a fixed size at creation, unlike Python lists (which can grow dynamically). Changing the size of an ndarray will create a new array and delete the original.

How do I get the size of an array in NumPy?

len() is the Python built-in function that returns the number of elements in a list or the number of characters in a string. For numpy. ndarray , len() returns the size of the first dimension. Equivalent to shape[0] and also equal to size only for one-dimensional arrays.


1 Answers

You should use np.any instead of np.all for the second case of selecting all but black pixels:

np.any(image != [0, 0, 0], axis=-1)

Or simply get a complement of black pixels by inverting a boolean array by ~:

black_pixels_mask = np.all(image == [0, 0, 0], axis=-1)
non_black_pixels_mask = ~black_pixels_mask

Working example:

import numpy as np
import matplotlib.pyplot as plt


image = plt.imread('example.png')
plt.imshow(image)
plt.show()

enter image description here

image_copy = image.copy()

black_pixels_mask = np.all(image == [0, 0, 0], axis=-1)

non_black_pixels_mask = np.any(image != [0, 0, 0], axis=-1)  
# or non_black_pixels_mask = ~black_pixels_mask

image_copy[black_pixels_mask] = [255, 255, 255]
image_copy[non_black_pixels_mask] = [0, 0, 0]

plt.imshow(image_copy)
plt.show()

enter image description here


In case if someone is using matplotlib to plot the results and gets completely black image or warnings, see this post: Converting all non-black pixels into one colour doesn't produce expected output

like image 140
Georgy Avatar answered Oct 17 '22 02:10

Georgy