Начнём с того, что "цвет" это очень субъективное понятие. В природе есть световые волны разной частоты. Исследования показали, что определённый диапазон частот (видимый свет) воспринимается человеческим глазом. Но воспринимается не каждая волна по отдельности, а их совокупность. Причём есть три основных частоты, "смешивая" которые можно получить
почти все воспринимаемые человеком цвета. Если эти частоты излучаются отдельно (например лазером), то воспринимаются они как красный, зелёный и синий цвета. Отсюда родилась RGB модель. Она очень удобна для технической реализации в устройствах, которые свет излучают (мониторы и проекторы). Т.к. там из одной точки можно "посветить" тремя цветами разной
интенсивности и таким образом, используя только 3 основных цвета получать почти весь видимый спектр.
Надо понимать разницу между светом
излучаемым и
отражаемым.
Если на белую стену посветить тремя прожекторами то получится вот такая штука:
На пересечении красного, зелёного и синего пятна мы получаем области, которые излучают сразу два цвета: зелёный+синий=cyan, синий+красный=magenta, красный+зелёный=yellow.
Но представим ситуацию, когда мы не можем излучать свет самостоятельно. Это случай журналов и картин. В природе естественным является белый свет: смесь из волн разной частоты, но примерно одинаковой энергии. Когда этот свет попадет на поверхность покрытую определённым веществом, волны одних частот от неё отражаются, волны других частот поглощаются веществом. Тогда можно взять три основных вещества (краски), которые по отдельности отражают только цвета cyan, magenta и yellow, и смешивая их в определённой пропорции получить почти все существующие цвета. Если нанести три пятна на белую бумагу и посветить на них белым светом, то будут они выглядеть так:
Например, смешивая cyan (голубой: поглощает красный, отражает зелёный и синий) и magenta (розовый: поглощает зелёный, отражает красный и синий) мы получаем поверхность, которая поглащает красный и зелёный и, соответственно, отражает только синий. Отсюда появилась цветовая схема CMYK, которая используется при печати. "K" означает четвёртую, чёрную, краску. Её используют по техническим соображениям.
Но вернёмся к "компьютерным" цветовым моделям. RGB удобна для воспроизведения цветов на мониторе или проекторе. Однако для передачи и кодирования сигнала она мало пригодна по нескольким причинам:
1) ЭЛТ мониторы имеют нелинейную зависимость между подаваемым напряжением и интенсивностью свечения фосфора. Это значит, что точность кодирования и устойчивость к шуму не одинакова для разных цветов.
2) Считается, что человеческий глаз больше замечает изменения яркости, чем цвета. RGB модель не позволяет это учесть.
3) Когда появилось цветное телевидение, необходимо было сохранить совместимость с чёрно-белыми телевизорами.
Поэтому для передачи цветного сигнала была разработана модель YUV, которая использовала один компонент (Y) для передачи яркости (чёрно-белое телевидение) и два дополнительных компонента (UV) для передачи цвета. В цифровом кодировании сигнала схожая модель зовётся
YCbCr.
Да, пару слов нужно сказать ещё об одной модели.
Это теоретическая модель XYZ, созданная CIE (Commission Internationale de l'Eclairage) на основе исследований человеческого цветовосприятия. Эта модель вмещает все видимые человеку цвета. Она разработана таким образом, что два компонента представляют цвет, а третий — яркость (Y). Для иллюстраций используют модель xyY, получающуюся из XYZ простыми преобразованиями. При это трёхмерными изображениями обычно не заморачиваются и компонент яркости отбрасывается. Получается такое изображение (эта xy плоскость отмечена на предыдущем изображении синим срезом):
На краю, обведённом чёрным, находятся монохроматические цвета. Соответствующая им длина волны подписана синим. Эта диаграмма имеет одно замечательное свойство: если выбрать на ней три основных цвета (
праймари), то внутри получившегося треугольника окажутся все цвета, которые можно представить при помощи этих праймари. Вообще, это распространяется на любой n-угольник. Отсюда и родилась RGB-модель.
Но праймари можно выбрать различным образом. Как правило, выбор диктуется некими практическими соображениями. Например наличием в производстве соответствующего люминофора.
И вот тут начинаются проблемы...
В зависимости от выбора праймари мы получаем разные
цветовые пространства.
CIE RGB:
Это пространство основано на трёх монохроматических цветах. E — точка белого.
sRGB:
Стандарт, созданный HP и Microsoft в 1996 году. Данный стандарт применяется повсеместно: компьютерные мониторы, интернет, принтеры... Кроме 3-х праймари и точки белого, он определяет ещё и кривую гамма-коррекции. Она устанавливает связь между реальной интенсивностью цвета и сохраняемым его значением. Это требовалось из-за нелинейной зависимости свечения люминофора на экране ЭЛТ монитора от подаваемого напряжения. ЭЛТ мониторов уже нет, а гамма-коррекция осталась.
Ещё несколько цветовых пространств:
ITU-R Recommendation BT.709 совпадет с sRGB.
ITU-R BT.601 совпадает с ITU-R BT.470-2.
Вообще, большинство используемых пространств похожи или на BT.709, или на BT.601.
Так вот. Чтобы преобразовать сигнал из YCbCr в RGB нужно знать, какое цветовое пространства использовалось при получении YCbCr. Для MPEG-1 это всегда BT.601. Для MPEG-2 значение устанавливается в заголовке, по умолчанию — BT.709. Для MPEG-4 по умолчанию BT.601 для SD и BT.709 для HD.
Казалось бы, в чём сложности? Внимание, сюрприз! В отличии от общедоступных стандартов MPEG, спецификация DVD-Video стоит $5000, и каждый подписчик обязуется не разглашать полученную информацию. В итоге, выводы о том, какая матрица должна использоваться для DVD, делаются по косвенным признакам. Например по тому, что коммерческие продукты предполагают именно BT.601.
Учитывая, что многие приложения склонны игнорировать флаги в заголовке, при кодировании вполне разумно использовать BT.601 для SD и BT.709 для HD. Для конвертации можно воспользоваться плагином ColorMatrix для Avisynth.
Есть несколько способов контроля цветового пространства преобразования YCbCr -> RGB при воспроизведении: настройки рендерера, выполнение преобразования в RGB через ffdshow, скрипты Avisynth, шейдеры в MPC-HC и т.д.
Ещё одна особенность YCbCr -> RGB преобразования состоит в том, что на каждый из трёх компонентов YCbCr выделено по 8 бит (т.е. значения 0-255). Однако не всегда они используются полностью. Стандарты BT.601 и BT.709 используют значения 16-235 для яркости и 16-240 для цветности. Традиция эта идёт от аналогового телевидения. В "компьютерных" же стандартах (JPEG, MJPEG, Fraps) используются диапазоны 0-255 и 1-255 соответственно. Кроме того, для значений RGB компьютерные мониторы используют диапазон 0-255, в то время как телевизоры и проекторы 16-235. Дефолтные рендереры в Windows (VMR7, VMR9, EVR) в некоторых случаях неправильно преобразовывают диапазон (для SD видео, как правило).
В отличии от неверного цветового пространства, неправильно выставленные уровни легко заметить: чёрный цвет становится тёмно-серым, а белый светло-серым. Исправить также можно несколькими способами: в настройках некоторых рендереров, делая RGB преобразование через ffdshow, шейдерами в MPC-HC, отдельным фильтром в ffdshow или даже настройками в драйверах видеокарты.
Как уже упоминалось, считается, что человек сильнее воспринимает изменения яркости, чем изменения цветности. Так как YCbCr кодирует яркость (Y) и цветность (CbCr) отдельно, то эта особенность человеческого восприятия активно используется кодеками.
Называется это
Chroma subsampling.
Расмотрим 2 строки по 4 пикселя в каждой.
В стандартном варианте мы имеем по 4 значения Y для каждой строки, и по 4 значения CbCr для каждой из двух строк. Это описывается соотношением 4:4:4. В общем виде записывается как J:a:b, где J — количество Y-сэмплов в каждой из строк, a — количество CbCr сэмплов в первой строке, b — количество CbCr сэмплов во второй строке.
На иллюстрации указано по два соседних блока (2 строки по 8 пикселей). Белые и серые квадратики символизируют пиксели, для каждого из которых отдельно задаётся своё значение Y (яркость), красные и синие прямоугольники — группы пикселей имеющие общее, усреднённое, значение CbCr (цветность). Для кодирования видео применяется, как правило 4:2:0 (возможно в x264 появится поддержка 4:4:4). Т.е. блок из четырёх пикселей имеет один усреднённый цвет. При это каждый из этих пикселей имеет разную яркость.
Что это нам даёт? Существенное уменьшение в размере (на блок 2*4=8 пикселей вместо 3*8=24 байт приходится 8+2*2=12 байт — в два раза меньше, 1.5 байта на пиксель). С другой стороны, преобразовывая обратно в RGB мы можем получить артефакты. Заметны они становятся либо на видео низкого разрешения с текстом (в этом случае перед кодированием стоит сделать апскейл), либо при переходах между некоторыми цветами (чёрный-красный, зелёный-маджента), либо на специальных тестовых изображениях. Для того, чтобы избежать артефактов при воспроизведении нужно либо использовать качественный рендерер (Haali, madVR), либо выполнять преобразование в RGB програмно, через ffdshow.
RGB преобразование через ffdshow несколько медленнее, чем через рендерер. Если использовать опцию "высококачественного преобразования", то значительно медленнее. Чтобы ffdshow выполнял преобразования самостоятельно, нужно на закладке "Вывод" оставить галки только напротив RGB форматов. Параметры преобразования настраиваются на закладке "RGB преобразование".
YCbCr -> RGB является преобразованием с потерями. Происходит это как из-за ошибок Chroma upsampling, так и из-за округлений при преобразовании.
Учитывая, что большинство кодеков использует YCbCr, RGB преобразования при кодировании можно и нужно избегать. К слову, для изменения цветового пространства при кодировании, RGB преобразование тоже не требуется.