Python: convertir l'image de l'espace colorimétrique RVB en YDbDr
Essayer de convertir l'image de l'espace colorimétrique RVB en espace colorimétrique YDbDr selon la formule:
Y = 0.299R + 0.587G + 0.114B
Db = -0.45R - 0.883G +1.333B
Dr = -1.333R + 1.116G + 0.217B
Avec le code suivant, j'essaie d'afficher uniquement le canal Y qui devrait être une image en niveaux de gris, mais je continue à obtenir l'image tout en bleu:
import numpy as np
from PIL import Image
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("./pics/Slike_modela/Test/Proba/1_Color.png")
new_img = []
for row in img:
new_row = []
for pixel in row:
Y = 0.299*pixel[2]+0.587*pixel[1]+0.114*pixel[0]
Db = -0.45*pixel[2]-0.883*pixel[1]+1.333*pixel[0]
Dr = -1.333*pixel[2]+1.116*pixel[1]+0.217*pixel[0]
new_pixel = [Y, Db, Dr]
new_row.append(new_pixel)
new_img.append(new_row)
new_img_arr = np.array(new_img)
new_img_arr_y = new_img_arr.copy()
new_img_arr_y[:,:,1] = 0
new_img_arr_y[:,:,2] = 0
print (new_img_arr_y)
cv2.imshow("y image", new_img_arr_y)
key = cv2.waitKey(0)
Lors de l'impression du tableau de résultats, je vois les nombres corrects selon la formule et la forme correcte du tableau.
Quelle est mon erreur? Comment obtenir l'image du canal Y, c'est-à-dire l'image en niveaux de gris?
Réponses
Lors du traitement d'images avec Python, vous devriez vraiment, vraiment essayer d'éviter:
traiter les images comme des listes et ajouter des millions et des millions de pixels, dont chacun crée un tout nouvel objet et prend de l'espace à administrer
traitement des images avec des
forboucles, qui sont très lentes
La meilleure façon de traiter ces deux problèmes est d'utiliser Numpyou d'autres bibliothèques ou techniques de code vectorisé. Voilà pourquoi OpenCV , wand, scikit-imageimages ouvertes et poignée sous forme de tableaux NumPy.
Donc, vous voulez essentiellement faire un produit scalaire des canaux de couleur avec un ensemble de 3 poids:
import cv2
import numpy as np
# Load image
im = cv2.imread('paddington.png', cv2.IMREAD_COLOR)
# Calculate Y using Numpy "dot()"
Y = np.dot(im[...,:3], [0.114, 0.587, 0.299]).astype(np.uint8)
C'est ça.