Python: convertir l'image de l'espace colorimétrique RVB en YDbDr

Nov 18 2020

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

1 MarkSetchell Nov 22 2020 at 13:19

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.