#c #image #image-processing #video #yuv
Вопрос:
У меня есть массив байтов с именем buf
, который содержит один видеокадр в формате YUV I420, полученный из буфера кадров. Для каждого видеокадра у меня также есть следующая информация:
Size (e.g. 320x180)
Stride Y (e.g. 384)
Stride U (e.g. 384)
Stride V (e.g. 384)
Plane offset Y (e.g. 0)
Plane offset U (e.g. 69120)
Plane offset V (e.g. 69312)
Объединение нескольких видеокадров в файле и передача их с информацией о размере в декодер необработанного видео в VLC или FFmpeg просто приводит к искажению цветов, поэтому я думаю, что байты buf
следует упорядочить, используя приведенную выше информацию, для получения воспроизводимого вывода, но я совершенно новичок в работе с видео, поэтому это может быть неправильно.
I в каком порядке информация о размере, шаге и смещении должна быть объединена с байтами, buf
чтобы создать поток байтов, который можно было бы воспроизводить в видеоплеере в необработанном виде?
Пример:
Комментарии:
1. можете ли вы опубликовать/загрузить некоторые примеры данных (полный кадр)? смещения плоскости выглядят неправильно. между U и V есть только 192, что не может быть правильным. то, что шаги несколько больше ширины, для меня означает, что есть обивка.
2. @ChristophRackwitz Конечно, я добавил ссылку на полный кадр. Я должен признать, что это выглядит странно, когда я смотрю на это в шестнадцатеричном редакторе, но это то, что я получаю от буфера кадров?
3. imgur.com/a/x4Ik5Gq это файл yuv, интерпретируемый как один поток в оттенках серого, шириной 384. полезные данные шириной 352 пикселя. данные выглядят странно сдвинутыми. Я пока не могу рассуждать на эту тему. кроме того, строки U и V, по-видимому, чередуются . если бы это было U, а затем V, мы бы увидели две плоские картинки, сложенные стопкой, а не картинки рядом. если бы они чередовались для каждого образца, мы бы увидели одну картинку с некоторой текстурой. странный формат. откуда берутся данные?
4. это говорит о том, что этот формат может быть вызван
M420
. в любом случае, странно, но поддается расшифровке.5. появляется ли второе изображение на imgur.com/a/x4Ik5Gq выглядите разумно, правильные ли цвета? полезные данные действительно 320×180
Ответ №1:
Расположение данных кажется странным, но, используя заданные смещения и шаги, это можно расшифровать как YUV.
Сначала есть 384 * 180 байт luma.
Ниже приведены строки цветности, каждая длиной 192 байта… но линии U и V меняются по очереди! Это объясняется странными смещениями. U смещение указывает точно на после люмы. Смещение V составляет еще 192 байта… и чтение перескочило бы на 384 байта.
Вот код, который извлекает эти плоскости и собирает их как I420 для декодирования с помощью cvtColor
:
#!/usr/bin/env python3
import numpy as np
import cv2 as cv
def extract(data, offset, stride, width, height):
data = data[offset:] # skip to...
data = data[:height * stride] # get `height` lines
data.shape = (height, stride)
return data[:, :width] # drop overscan/padding
width, height = 320, 180
Yoffset = 0
Uoffset = 69120 # 384*180
Voffset = 69312 # 384*180 192
Ystride = 384
Ustride = 384
Vstride = 384
data = np.fromfile("69518644-example-01.yuv", dtype=np.uint8)
Y = extract(data, Yoffset, Ystride, width, height)
U = extract(data, Uoffset, Ustride, width // 2, height // 2)
V = extract(data, Voffset, Vstride, width // 2, height // 2)
# construct I420: Y,U,V planes in order
i420 = np.concatenate([Y.flat, U.flat, V.flat])
i420.shape = (height * 3 // 2, width)
result = cv.cvtColor(i420, cv.COLOR_YUV2BGR_I420)
cv.namedWindow("result", cv.WINDOW_NORMAL)
cv.resizeWindow("result", width * 4, height * 4)
cv.imshow("result", result)
cv.waitKey()
cv.destroyAllWindows()