Изображение Python RGB для YUYV - PullRequest
0 голосов
/ 31 августа 2018

Я хочу преобразовать растровое изображение в формат YUV422 (YUYV). Я гуглю насчет формата YUYV и пытаюсь написать этот код.

path = "C:/Users/hogan/Desktop/red.bmp"
image = Image.open(path).convert("YCbCr")  # YUV
image = np.asarray(image)
width, height, YUYV = image.shape[1], image.shape[0], 4
array = np.empty((height * width * 3), dtype="uint8")
Y, U, V = 0, 1, 2
count = 0
for i in range(len(image)):
    for j in range(len(image[i])):
        for k in range(len(image[i][j])):
            if (count % 4 == 0):
                array[count] = image[i][j][Y]
            if (count % 4 == 1):
                array[count] = image[i][j][U]
            if (count % 4 == 2):
                array[count] = image[i][j][Y]
            if (count % 4 == 3):
                array[count] = image[i][j][V]
            count = count + 1
array.astype('uint8').tofile("C:/Users/hogan/Desktop/tmpdir/1.raw")

Я прочитал это изображение и знаю, что мой код неверен, но не знаю, как это сделать правильно. enter image description here Например : Красный цвет (255,0,0) в YUV равен (76,84,255), если у меня много пикселей, я не знаю, какие «U» и «V» следует отбросить.

Если использовать мой код для преобразования 480 * 640 (Ш * В), это будет 960 * 480.

1 Ответ

0 голосов
/ 31 августа 2018

Вы можете использовать расширенную индексацию и трансляцию здесь.

Предположим, у вас есть изображение:

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

Также встретятся более сложные пограничные случаи.

...