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:
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:
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)
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.
To select an element from Numpy Array , we can use [] operator i.e. It will return the element at given index only.
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.
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.
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()
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()
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With