Для начала, вы можете преобразовать изображение непосредственно в массив numpy и использовать векторизованные операции, чтобы сделать то, что вы хотите:
def get_ycbcr_vectorized(img: Image.Image):
R,G,B = np.array(img).transpose(2,0,1)[:3] # ignore alpha if present
Y = 0.299 * R + 0.587 * G + 0.114 * B
Cb = 128 - 0.168736 * R - 0.331264 * G + 0.5 * B
Cr = 128 + 0.5 * R - 0.418688 * G - 0.081312 * B
return np.array([Y,Cb,Cr]).transpose(1,2,0)
print(np.array_equal(get_ycbcr_arr(img), get_ycbcr_vectorized(img))) # True
Однако вы уверены, что непосредственное преобразование в 'YCbCr'
будетсильно отличается?Я проверил преобразование, определенное в приведенной выше функции:
import matplotlib.pyplot as plt
def aux():
# generate every integer R/G/B combination
R,G,B = np.ogrid[:256,:256,:256]
Y = 0.299 * R + 0.587 * G + 0.114 * B
Cb = 128 - 0.168736 * R - 0.331264 * G + 0.5 * B
Cr = 128 + 0.5 * R - 0.418688 * G - 0.081312 * B
# plot the maximum error along one of the RGB channels
for arr,label in zip([Y,Cb,Cr], ['Y', 'Cb', 'Cr']):
plt.figure()
plt.imshow((arr - arr.round()).max(-1))
plt.xlabel('R')
plt.ylabel('G')
plt.title(f'max_B ({label} - {label}.round())')
plt.colorbar()
aux()
plt.show()
Результаты показывают, что самая большая абсолютная ошибка равна 0,5, хотя эти ошибки происходят во всех пикселях:
Y error"> Cb error"> Cr error">
Так что, да, это может быть большой относительный относительный ошибка, но это не обязательно огромная проблема.
В случае, если достаточно встроенного преобразования:
arr = np.array(img.convert('YCbCr'))
- это все, что вам нужно.