Вы можете использовать расширенную индексацию и трансляцию здесь.
Предположим, у вас есть изображение:
ycbcr = np.array([
[['Y00', 'U00', 'V00'], ['Y01', 'U01', 'V01'], ['Y02', 'U02', 'V02']],
[['Y10', 'U10', 'V10'], ['Y11', 'U11', 'V11'], ['Y12', 'U12', 'V12']],
[['Y20', 'U20', 'V20'], ['Y21', 'U21', 'V21'], ['Y22', 'U22', 'V22']],
], dtype=str)
Работа с трехмерным массивом будет громоздкой, поэтому давайте переведем ее в 1D:
ycbcr = ycbcr.reshape(27)
Затем я выделю массив для потока YUYV:
yuyv = np.array([' ' for _ in range(18)]) # ' ' is basically because
# I use strings in this example. You'd probably want to use arrays of uint8
Первый шаг самый простой - мы берем каждое третье значение ycbcr (компоненты Y) и размещаем их на четных позициях yuyv:
yuyv[::2] = ycbcr[::3]
Тогда мы продолжим с другими байтами. U00
должен перейти из положения 1 в положение 1, V00
от 2 до 3, U01
и V01
опущены, U02
- от 7 до 5, V02
- от 8 до 7, U03
опущен и так далее:
yuyv[1::4] = ycbcr[1::6] # Moving U, every sixth byte starting from position 1
yuyv[3::4] = ycbcr[2::6][:-1] # Moving V, dropping last element of V
Таким образом, вы получите следующее yuyv
, как показано на рисунке:
array(['Y00', 'U00', 'Y01', 'V00', 'Y02', 'U02', 'Y10', 'V02', 'Y11',
'U11', 'Y12', 'V11', 'Y20', 'U20', 'Y21', 'V20', 'Y22', 'U22'],
dtype='<U3')
Если вы хотите следовать совету @alkanen, такой подход также возможен, вам просто нужно сэмплировать байты U и V в двух массивах и взять среднее значение. Возможно, это будет выглядеть так: (не проверено)
u_even = ycbcr[1::6]
u_odd = ycbcr[4::6]
u = (u_even + u_odd) / 2
yuyv[1::4] = u
Также встретятся более сложные пограничные случаи.