J'ai essayé ce code:
import cv2
image = cv2.imread("sample.jpg")
pixel = image[200, 550]
print pixel
Mais je reçois une erreur en tant que:
'Non-type' pas d'erreur d'attribut getitem
Cette erreur est affichée après l'exécution de la troisième ligne de code.
Il existe deux causes possibles de cette erreur:
Pour résoudre ce problème, vous devez vous assurer que le nom du fichier est correctement orthographié (faites une vérification sensible à la casse) et que le fichier image se trouve dans le répertoire de travail actuel (vous avez le choix entre deux options: vous pouvez modifier le répertoire de travail actuel dans votre = IDE ou spécifiez le chemin complet du fichier).
Ensuite, pour calculer la "couleur moyenne", vous devez décider ce que vous entendez par là. Dans une image en niveaux de gris, il s’agit simplement de la moyenne des niveaux de gris, mais avec les couleurs, la "moyenne" n’existe pas. En effet, les couleurs sont généralement représentées par des vecteurs tridimensionnels alors que les niveaux de gris sont des scalaires. Cela convient aux scalaires moyens mais cela n’a aucun sens de faire des vecteurs moyens.
Séparer l’image en ses composantes chromatiques et prendre la moyenne de chaque composante est une solution envisageable. Cependant, cette approche peut donner une couleur sans signification. Ce que vous pourriez vraiment souhaiter, c’est une couleur dominante plutôt qu’une couleur moyenne.
Passons lentement en revue le code. Nous commençons par importer les modules nécessaires et en lisant l'image:
import cv2
import numpy as np
from skimage import io
img = io.imread('https://i.stack.imgur.com/DNM65.png')[:, :, :-1]
On peut ensuite calculer la moyenne de chaque canal chromatique selon une méthode analogue à celle proposée par @Ruan B .:
average = img.mean(axis=0).mean(axis=0)
Ensuite, nous appliquons k-means clustering pour créer une palette avec les couleurs les plus représentatives de l'image (dans cet exemple de jouet n_colors
était réglé sur 5
).
pixels = np.float32(img.reshape(-1, 3))
n_colors = 5
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, .1)
flags = cv2.KMEANS_RANDOM_CENTERS
_, labels, palette = cv2.kmeans(pixels, n_colors, None, criteria, 10, flags)
_, counts = np.unique(labels, return_counts=True)
Et enfin, la couleur dominante est la couleur de palette qui apparaît le plus souvent sur l’image quantifiée:
dominant = palette[np.argmax(counts)]
Pour illustrer les différences entre les deux approches, j'ai utilisé l'exemple d'image suivant:
Les valeurs obtenues pour la couleur moyenne, c’est-à-dire une couleur dont les composantes sont les moyennes des trois canaux chromatiques, et la couleur dominante calculée par le regroupement en k-moyennes sont assez différentes:
In [30]: average
Out[30]: array([91.63179156, 69.30190754, 58.11971896])
In [31]: dominant
Out[31]: array([179.3999 , 27.341282, 2.294441], dtype=float32)
Voyons à quoi ressemblent ces couleurs pour mieux comprendre les différences entre les deux approches. Sur la partie gauche de la figure ci-dessous, la couleur moyenne est affichée. Il apparaît clairement que la couleur moyenne calculée ne décrit pas correctement le contenu en couleurs de l'image d'origine. En fait, il n'y a pas un seul pixel avec cette couleur dans l'image d'origine. La partie droite de la figure montre les cinq couleurs les plus représentatives triées de haut en bas par ordre décroissant d’importance (fréquence d’occurrence). Cette palette indique clairement que la couleur dominante est le rouge, ce qui concorde avec le fait que la plus grande région de couleur uniforme de l'image d'origine correspond à la pièce Lego rouge.
C'est le code utilisé pour générer la figure ci-dessus:
import matplotlib.pyplot as plt
avg_patch = np.ones(shape=img.shape, dtype=np.uint8)*np.uint8(average)
indices = np.argsort(counts)[::-1]
freqs = np.cumsum(np.hstack([[0], counts[indices]/counts.sum()]))
rows = np.int_(img.shape[0]*freqs)
dom_patch = np.zeros(shape=img.shape, dtype=np.uint8)
for i in range(len(rows) - 1):
dom_patch[rows[i]:rows[i + 1], :, :] += np.uint8(palette[indices[i]])
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(12,6))
ax0.imshow(avg_patch)
ax0.set_title('Average color')
ax0.axis('off')
ax1.imshow(dom_patch)
ax1.set_title('Dominant colors')
ax1.axis('off')
plt.show(fig)
En résumé, bien que le calcul de la couleur moyenne - comme proposé dans la réponse de @Ruan B. - soit techniquement correct d'un point de vue mathématique, le résultat obtenu peut ne pas représenter correctement le contenu en couleur de l'image. Une approche plus judicieuse consiste à déterminer la couleur dominante par quantification vectorielle (clustering).
J'ai pu obtenir la couleur moyenne en utilisant les éléments suivants:
import cv2
import numpy
myimg = cv2.imread('image.jpg')
avg_color_per_row = numpy.average(myimg, axis=0)
avg_color = numpy.average(avg_color_per_row, axis=0)
print(avg_color)
Résultat:
[ 197.53434769 217.88439451 209.63799938]