My input is a PIL.Image.Image
with mode RGB
or RGBA
, and I need to fill a numpy.ndarray
with 3 float values calculated from the RGB values of each pixel. The output array should be indexable by the pixel coordinates. I have found the following way to do it:
import numpy as np
from PIL import Image
def generate_ycbcr(img: Image.Image):
for r, g, b in img.getdata():
yield 0.299 * r + 0.587 * g + 0.114 * b
yield 128 - 0.168736 * r - 0.331264 * g + 0.5 * b
yield 128 + 0.5 * r - 0.418688 * g - 0.081312 * b
def get_ycbcr_arr(img: Image.Image):
width, height = img.size
arr = np.fromiter(generate_ycbcr(img), float, height * width * 3)
return arr.reshape(height, width, 3)
It works, but I suspect there is a better and/or faster way. Please tell me if there is one, but also if there is not.
N.B.: I know I can convert()
the image to YCbCr
, and then fill a numpy.array
from that, but the conversion is rounded to integer values, which is not what I need.