¿Cómo seleccionar todos los píxeles no negros en una matriz NumPy?

Estoy tratando de obtener una lista de píxeles de una imagen que sean diferentes de un color específico usando NumPy.

Por ejemplo, mientras se procesa la siguiente imagen:

introduzca la descripción de la imagen aquí

He logrado obtener una lista de todos los píxeles negros utilizando:

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

Pero cuando trato de hacer:

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

Me sale un resultado bastante extraño:

introduzca la descripción de la imagen aquí

Parece que NumPy ha devuelto solo los índices que fueron R, G y B no son 0

Aquí hay un ejemplo mínimo de lo que estoy tratando de hacer:

 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) 

Debe usar np.any lugar de np.all para el segundo caso de selección de todos los píxeles excepto los negros:

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

O simplemente obtenga un complemento de píxeles negros invirtiendo una matriz booleana mediante ~ :

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

Ejemplo de trabajo:

 import numpy as np import matplotlib.pyplot as plt image = plt.imread('example.png') plt.imshow(image) plt.show() 

introduzca la descripción de la imagen aquí

 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() 

introduzca la descripción de la imagen aquí


En caso de que alguien esté usando matplotlib para trazar los resultados y obtenga una imagen o advertencias completamente en negro, vea este post: Convertir todos los píxeles no negros en un solo color no produce el resultado esperado

Necesidad: necesita matriz con esta forma = (cualquiera, cualquier, 3)

Solución:

 COLOR = (255,0,0) indices = np.where(np.all(mask == COLOR, axis=-1)) indexes = zip(indices[0], indices[1]) for i in indexes: print(i) 

Solución 2:

Obtener intervalo de color específico, por ejemplo ROJO:

 COLOR1 = [250,0,0] COLOR2 = [260,0,0] # doesnt matter its over limit indices1 = np.where(np.all(mask >= COLOR1, axis=-1)) indexes1 = zip(indices[0], indices[1]) indices2 = np.where(np.all(mask <= COLOR2, axis=-1)) indexes2 = zip(indices[0], indices[1]) # You now want indexes that are in both indexes1 and indexes2 

Solución 3 - PROBADO QUE ESTÁ TRABAJANDO

Si el anterior no funciona, entonces hay una solución que funciona al 100%.

Transformación de canal RGB a HSV. Hacer máscara 2D desde imagen 3D. La máscara 2D contendrá el valor de tono. Comparar Hues es más fácil que RGB ya que Hue es 1 valor mientras que RGB es vector con 3 valores. Una vez que tenga la matriz 2D con valores de Tono, haga como en el ejemplo anterior:

 HUE1 = 0.5 HUE2 = 0.7 indices1 = np.where(HUEmask >= HUE1) indexes1 = zip(indices[0], indices[1]) indices2 = np.where(HUEmask <= HUE2) indexes2 = zip(indices[0], indices[1]) 

Puedes hacer lo mismo para Saturación y Valor.