Какой формат YUV это? Действительно YUV420SP? - PullRequest
0 голосов
/ 22 февраля 2020

Ниже приведен вывод RGB предполагаемого буфера YUV420SP. Без преобразования, я просто отображаю YUV420SP, как если бы это был RGB, просто чтобы увидеть некоторые шаблоны.

Изображение находится в одном unsigned char* буфере размером width*height*3. Так что, если это действительно YUV420SP, то я должен иметь Y в качестве черно-белого изображения, а затем с чередованием UV. Я думаю, что я должен видеть Y как черно-белое изображение, но почему оно повторяется 3 раза в моем изображении? И я должен видеть что-нибудь в ультрафиолетовой части?

Конечно, я пытался преобразовать этот буфер в RGB. Я использовал https://github.com/andrechen/yuv2rgb/blob/master/yuv2rgb.h#L70, но получаю только полностью черное изображение.

enter image description here

Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Формат выглядит как I420 формат (также называемый YV12 ).

I420 - это формат YUV 4: 2: 0 с полностью упорядоченным упорядоченным форматом.
В YUV420 цветовой канал Y - это яркость (яркость) каждого пикселя.
U и V - это цветность (цветные) каналы.
Разрешение по U и V составляет половину Y по обеим осям (с понижением в 0,5 раза по каждой оси).

Иллюстрация I420:

Предположим, unsigned char* src является указателем на буфер кадра, а разрешение составляет 640x480:

src ->               YYYYYY  
                     YYYYYY  
                     YYYYYY  
                     YYYYYY  
src + 640*480     -> UUU  
                     UUU  
src + (320*240)*5 -> VVV  
                     VVV  

Я использовал Код MATLAB для восстановления изображения RGB из изображения, которое вы опубликовали.

Вот результат:
enter image description here


Код MATLAB (только для справки):

I = imread('Test.png');
R = I(:,:,1);G = I(:,:,2);B = I(:,:,3);

T = zeros(size(R,1), size(R,2)*3, 'uint8');
T(:, 1:3:end) = R;T(:, 2:3:end) = G;T(:, 3:3:end) = B;
T = T';T = T(:);

Y = T(1:640*480);
U = T(640*480+1:640*480+640*480/4);
V = T(640*480+640*480/4+1:640*480+(640*480/4)*2);

Y = (reshape(Y, [640, 480]))';
U = (reshape(U, [320, 240]))';
V = (reshape(V, [320, 240]))';

U = imresize(U, 2);
V = imresize(V, 2);
YUV = cat(3, Y, U, V);
RGB = ycbcr2rgb(YUV);
1 голос
/ 23 февраля 2020

Ранее я делал несколько рендеров YUV.

Буфер YUV 420 должен содержать width*height байтов для Y, за которыми следует (width*height)/4) байтов для U. И еще (width*height)/4) байтов для V. Следовательно, если ваш байтовый буфер YUV должен содержать (width*height*3)/2 байтов в размере.

Просто чтобы увидеть шаблон серой шкалы в том виде, как вы его описываете, вам необходимо преобразовать байты "Y" в 24-битный RGB например:

Примерно так:

unsigned char* YUV_BYTES = < some buffer of size (width*height*3)/2 with bytes copied in>
unsigned char* RGB_BYTES = < some buffer of size width*height*3 >

const unsigned char* dst = RGB_BYTES;
for (unsigned int r = 0; r < height; r++)
{
    unsigned int row_offset = r*width;
    for (unsigned int c = 0; c < width; c++)
    {
        *dst[0] = YUV[row_offset + c];  // R
        *dst[1] = YUV[row_offset + c];  // G
        *dst[2] = YUV[row_offset + c];  // B
        dst += 3;
    }
}

Я думаю, что есть также неявное предположение о том, что ширина и высота изображений YUV всегда делятся на 4. Ваш рендерер может нарисовать это изображение вверх ногами в зависимости от вашей графической библиотеки и платформы.

...