web-dev-qa-db-fra.com

Comment sélectionner tous les pixels non noirs dans un tableau NumPy?

J'essaie d'obtenir une liste des pixels d'une image qui diffère d'une couleur spécifique à l'aide de NumPy.

Par exemple, pendant le traitement de l'image suivante: 

 enter image description here

J'ai réussi à obtenir une liste de tous les pixels noirs en utilisant:

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

Mais quand j'essaie de faire:

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

J'obtiens un résultat assez étrange:

 enter image description here

Il semblerait que NumPy ait renvoyé uniquement les indices où R, G et B ne sont pas 0

Voici un exemple minimal de ce que j'essaie de faire:

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)
4
ofir dubi

Vous devez utiliser np.any au lieu de np.all pour le second cas de sélection de tous les pixels sauf les pixels noirs: 

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

Ou obtenez simplement un complément de pixels noirs en inversant un tableau booléen par ~

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

Exemple de travail: 

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


Si quelqu'un utilise matplotlib pour tracer les résultats et obtenir une image ou des avertissements complètement noirs, consultez l'article suivant: La conversion de tous les pixels non noirs en une seule couleur ne produit pas le résultat attendu

5
Georgy

Nécessité: Besoin d'une matrice avec cette forme = (any, any, 3)

Solution:

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)

Solution 2:

obtenir un intervalle de couleur spécifique, par exemple RED:

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

Solution 3 - VÉRITABLE  

Si la précédente ne fonctionne pas, il existe une solution qui fonctionne à 100%

Transformer du canal RVB au HSV. Faire un masque 2D à partir d'une image 3D. Le masque 2D contiendra la valeur de teinte. La comparaison des teintes est plus facile que RGB, car Hue est égal à 1 valeur alors que RGB est vectoriel avec 3 valeurs. Après avoir obtenu une matrice 2D avec des valeurs de teinte, procédez comme ci-dessus:

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

Vous pouvez en faire autant pour Saturation et Valeur.

0
Martin