BT.601 / T.871: преобразование в и из RGB (16 бит) - PullRequest
1 голос
/ 31 октября 2019

Я пытаюсь понять смысл T.871 для преобразования между RGB и YCbCr для 16-битных входов. Уравнения тривиальны для 8-битного сигнала. Если мы проверим T.871 § 7, стр. 4, то получим:

Y  = Min( Max( 0, Round( 255 * E'Y ) ), 255 )
Cb = Min( Max( 0, Round( 255 * E'Cb + 128 ) ), 255 )
Cb = Min( Max( 0, Round( 255 * E'Cr + 128 ) ), 255 )

[...]

Y  = Min(Max( 0, Round(   0.299 * R + 0.587 * G + 0.114 * B)), 255 )
Cb = Min(Max( 0, Round(( -0.299 * R - 0.587 * G + 0.886 * B)/1.772 + 128 )), 255 )
Cr = Min(Max( 0, Round((  0.701 * R - 0.587 * G - 0.114 * B)/1.402 + 128 )), 255 )

, которые с точностью до четвертого десятичного знака могутбыть аппроксимированным:

Y  = Min(Max( 0, Round(  0.299  * R + 0.587  * G + 0.114  * B)), 255 )
Cb = Min(Max( 0, Round( -0.1687 * R - 0.3313 * G + 0.5    * B + 128 )), 255 )
Cr = Min(Max( 0, Round(  0.5    * R - 0.4187 * G - 0.0813 * B + 128 )), 255 )

Я могу проверить уравнение E'Y, E'Cb & E'Cr в разделе BT.601 § 2.5.5 2.5.1 Построение яркости [. ..]:

E'Y = 0.299 * E'R + 0.587 * E'G + 0.114 * E'B

И раздел §2.5.2 Построение перенормированных цветоразностных сигналов [...]:

E'Cr = ( 0.701 * E'R - 0.587 * E'G - 0.114 * E'B) / 1.402
E'Cb = (-0.299 * E'R - 0.587 * E'G + 0.886 * E'B) / 1.772

Итак, моя (наивная) интерпретация для 16-битного сигнала проста:

 Y  = Min(Max( 0, Round(   0.299 * R + 0.587 * G + 0.114 * B)), 65535 )
 Cb = Min(Max( 0, Round(( -0.299 * R - 0.587 * G + 0.886 * B)/1.772 + 32768 )), 65535 )
 Cr = Min(Max( 0, Round((  0.701 * R - 0.587 * G - 0.114 * B)/1.402 + 32768 )), 65535 ) 

Я попробовал быстрый C-код, чтобы проверить это, но, похоже, приведенные выше уравнения не верны.

Итак, мой вопрос: каковы уравнения для преобразования 16-битного сигнала RGB в YCbCr?

Ссылки:


Обновление: я написал:

Я попробовал быстрый C-код, чтобы проверить это, но этокажется, что приведенные выше уравнения не верны.

Чтобы проверить преобразование, я инкапсулировал сгенерированный поток битов в файл DICOM (используя gdcmimg), а затем преобразовал файл DICOM в PPM, используя DCMTK:

$ dcmj2pnm ybr16.dcm ybr16.ppm

Поскольку мой файл шаблона DICOM был объявлен с 16-битным выделенным битом, но только 12-битный хранимый dcmj2pnm отбросил бы старшие биты всего, что превышает 12-битное максимальное значение, что в конечном итоге превратилось бы в зеленоватый фон.

Итак, подведем итог: уравнения верны, моего теста не было.

1 Ответ

1 голос
/ 31 октября 2019

Ваше 16-битное преобразование правильно .

  • Для точного сравнения я удалил round - все значения были сохранены в типе double (только для целей тестирования).
  • Самая важная и запутанная вещь при сравнении Cb, Cr в 8 битах и ​​16 битах - это смещение :
    Вам необходимо вычесть смещение перед масштабированием (или делением на 256):

Предположим, у вас есть Cb8 и Cb16, и вы хотите проверить, что соотношение равно 256,
Первое, что вам нужно сделать, это вычесть 128 изCb8 и вычтите 32768 из Cb16.
Операция вычитания подобна центрированию значений вокруг нуля.

Пример:

Pb8 = Cb8 - 128
Pb16 = Cb16 - 32768

Теперь вы можете сравнить соотношение между Pb8 и Pb16:

Pb16 == Pb8*256

Я использовал следующий код MATLAB (проще, чемC):

R = 50;G = 100;B = 150; %Initialize RGB to arbitrary values.

%8 bits conversion
Y  = min(max( 0, (   0.299 * R + 0.587 * G + 0.114 * B)), 255 );
Cb = min(max( 0, (( -0.299 * R - 0.587 * G + 0.886 * B)/1.772 + 128 )), 255 );
Cr = min(max( 0, ((  0.701 * R - 0.587 * G - 0.114 * B)/1.402 + 128 )), 255 );

%Convert RGB to 16 bits.
scale = 256; %Assume conversion from 8 to 16 bits is scale by 256 (not scale by 65535/255).
R = R*scale;
G = G*scale;
B = B*scale;

%16 bits conversion
Y2  = min(max( 0, (   0.299 * R + 0.587 * G + 0.114 * B)), 65535 );
Cb2 = min(max( 0, (( -0.299 * R - 0.587 * G + 0.886 * B)/1.772 + 32768 )), 65535 );
Cr2 = min(max( 0, ((  0.701 * R - 0.587 * G - 0.114 * B)/1.402 + 32768 )), 65535 );

Ydiff = Y*scale - Y2
Cb_diff = (Cb - 128)*scale - (Cb2 - 32768)
Cr_diff = (Cr - 128)*scale - (Cr2 - 32768)

Результат:

Ydiff = 0
Cb_diff = 0
Cr_diff = 0

Я предполагаю, что следующие уравнения применяются Cr и Cb без смещения (то, что я назвал Pb иPr).

E'Cr = ( 0.701 * E'R - 0.587 * E'G - 0.114 * E'B) / 1.402
E'Cb = (-0.299 * E'R - 0.587 * E'G + 0.886 * E'B) / 1.772

Для 8 бит:

Cr = E'Cr + 128
Cb = E'Cb + 128

Для 16 бит:

Cr = E'Cr + 32768
Cb = E'Cb + 32768
...