Python: converta a imagem de RGB para espaço de cores YDbDr
Tentando converter a imagem do espaço de cores RGB para o espaço de cores YDbDr de acordo com a fórmula:
Y = 0.299R + 0.587G + 0.114B
Db = -0.45R - 0.883G +1.333B
Dr = -1.333R + 1.116G + 0.217B
Com o código a seguir, estou tentando mostrar apenas o canal Y, que deve ser uma imagem em tons de cinza, mas continuo recebendo a imagem toda em azul:
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)
Ao imprimir a matriz de resultados, vejo os números corretos de acordo com a fórmula e a forma correta da matriz.
Qual é o meu erro? Como obter a imagem do canal Y, ou seja, imagem em tons de cinza?
Respostas
Ao processar imagens com Python, você realmente deve tentar evitar:
tratando imagens como listas e acrescentando milhões e milhões de pixels, cada um dos quais cria um objeto totalmente novo e ocupa espaço para administrar
processamento de imagens com
forloops, que são muito lentos
A melhor maneira de lidar com ambos é por meio do uso de Numpyoutras bibliotecas ou técnicas de código vetorizado. É por isso que OpenCV , wand, scikit-imageimagens abertas e punho como matrizes Numpy.
Então, você basicamente deseja fazer um produto escalar dos canais de cores com um conjunto de 3 pesos:
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)
É isso aí.