Содержание статьи +
- TL;DR
- Почему это важно
- Три разные ошибки под одной вывеской
- Субдискретизация цветности: экономия, которая и порождает растекание
- Цветовой сдвиг: неправильный рецепт, а не неправильный битрейт
- Почему ваша метрика качества слепа к цвету
- Как реально измерить цвет
- Разбор на числах: число, которое молчит
- Где здесь Фора Софт
- Ключевые выводы
- Что почитать дальше
TL;DR
Цветовое растекание (color bleeding) – это размазывание цвета за пределы края, которому он принадлежит; чаще всего потому, что видео хранит цвет вчетверо грубее, чем яркость (приём называется субдискретизацией цветности, chroma subsampling – это вездесущий формат 4:2:0), и это размывает насыщенные края и делает цветной текст нечётким. Цветовой сдвиг (color shift) – другая ошибка: весь кадр уезжает по оттенку, потому что файл декодировали с неправильным «рецептом» цвета (матрицей BT.601, BT.709 или BT.2020), и красный темнеет, а зелёный становится ярче. Ловушка для любого, кто измеряет качество, в том, что две метрики, которым доверяют большинство команд – PSNR и VMAF, – обычно смотрят только на яркость: стандартный VMAF (v0) извлекает feature только из luma и, по собственным словам Netflix, «не осведомлён о цветовых артефактах», а PSNR рутинно считают только по Y, поэтому клип может показать «отлично», пока цвет на нём заметно растекается. Чтобы реально увидеть цветовую ошибку, нужна осознающая цвет мера: покомпонентный chroma PSNR, перцептивная метрика цветоразличия вроде ΔE-ITP (ITU-R BT.2124) или CIEDE2000, новая цветовая feature VMAF v1 или – истина в последней инстанции – человек, смотрящий на насыщенные края.
Почему это важно
Цветовые артефакты – это та порча, которую ваше итоговое число качества вероятнее всего пропустит, потому что число посчитано по одной яркости. Можно отгрузить файл с безупречным средним VMAF и красными буквами, которые растекаются на голубом фоне настолько, что выглядит сломанным, – потому что оценка ни разу не измерила цветовые каналы, где живёт повреждение. Эта статья – для видеоинженера, стриминг- или энкодинг-лида, QA-инженера, который видел цветную бахрому на насыщенных краях, замечал, как уезжают тона кожи после транскода, или как текст на цветной панели становится кашей, и хочет точно знать, что происходит в цветовых каналах, почему его объективная метрика промолчала и какие измерения это реально ловят. Сделаете правильно – и перестанете доверять luma-числу сертификацию цвета, на который оно ни разу не смотрело.
Три разные ошибки под одной вывеской
«Цветовой артефакт» – это корзина, в которой лежат как минимум три разные проблемы с тремя разными причинами. Разделить их по именам – первый шаг к измерению, потому что каждая проявляется (или прячется) в метрике по-своему.
Цветовое растекание (color bleeding) – это цвет, выходящий за свою границу. Представьте красный текст на голубой панели: красный будто просачивается на пиксель-два в голубой, край выглядит мягким и обтрёпанным, а мелкая цветная деталь теряет резкость. Это локальная ошибка, худшая именно там, где встречаются два сильно разных цвета. Главная причина – субдискретизация цветности, которую разберём ниже.
Цветовой сдвиг (color shift) – это уезд цвета всего кадра в одну сторону: тона кожи слишком розовые или зелёные, ровный общий налёт. Это глобальная ошибка, и обычно она вообще не связана с тем, сколько бит вы потратили. Она возникает из-за декодирования цвета неправильной матрицей преобразования или из-за потери метаданных, которые говорят, какую матрицу использовать.
Квантование цветности и бэндинг – это цветовая версия бэндинга, знакомого вам по каналу яркости: когда цветовые плоскости жмут сильно, плавные цветовые градиенты распадаются на ступени, а насыщенные области идут пятнами. Это цветовой близнец яркостного артефакта, и он хуже всего в глубоких насыщенных зонах.
Все три – ошибки именно цветовой информации, а не яркостной; и этот единственный факт объясняет, почему стандартные метрики качества, измеряющие в основном яркость, так плохо их видят.
Субдискретизация цветности: экономия, которая и порождает растекание
Чтобы понять растекание, надо понять приём, которым экономит почти каждое видео. Человеческий глаз различает мелкую деталь в яркости куда лучше, чем в цвете – примерно втрое лучше (Winkler et al., 2001, в Vision Models and Applications to Image and Video Processing). Видео это эксплуатирует: каждый пиксель делится на яркостную часть, luma (пишут Y′), и две цветоразностные части, chroma (Cb и Cr), и затем хранит chroma в меньшем разрешении, чем luma. Эта намеренная урезка и есть субдискретизация цветности.
Степень субдискретизации записывают трёхчисловым отношением J:a:b, описывающим область 4 пикселя в ширину и 2 в высоту (Poynton, «Chroma Subsampling Notation», 2008). Первое число – опорная ширина (всегда 4); второе – сколько цветовых отсчётов в верхней строке; третье – сколько их меняется в нижней. Три значения покрывают почти всё, что встретится:
- 4:4:4 – полное цветовое разрешение. Каждый пиксель хранит свой цвет. Субдискретизации нет.
- 4:2:2 – цвет дискретизован вдвое грубее по горизонтали. Часто в профессиональном захвате и мезонинных форматах.
- 4:2:0 – цвет дискретизован вдвое грубее и по горизонтали, и по вертикали, так что один цветовой отсчёт покрывает блок 2×2 из четырёх яркостных пикселей. Это формат H.264, HEVC, AV1, JPEG, DVD, Blu-ray и практически всего потребительского стриминга (ITU-T H.273; Wikipedia, «Chroma subsampling»).
Вот арифметика, которая делает сделку наглядной. Возьмём один кадр 1920×1080, 8 бит на отсчёт. При 4:4:4 вы храните три полноразмерные плоскости: 1920 × 1080 × 3 = 6 220 800 байт, около 6,2 МБ. При 4:2:0 яркостная плоскость не меняется, но каждая цветовая урезается вчетверо, так что вы храните 1920 × 1080 × (1 + ¼ + ¼) = 1920 × 1080 × 1,5 = 3 110 400 байт, около 3,1 МБ. Вы вдвое урезали сырые данные ещё до запуска кодека – и на большинстве контента почти никто не видит разницы. Поэтому 4:2:0 и победил.
Загвоздка – в слове «большинство». На насыщенных, резких цветовых краях – красный текст на голубом, тонкая цветная линия, логотип, элементы интерфейса – цветовая острота глаза достаточно высока, чтобы заметить, а 4:2:0 выбрасывает ровно ту цветовую деталь, которая этим краям нужна. Поскольку один цветовой отсчёт теперь обслуживает блок 2×2, цвет не может поворачивать так же резко, как яркость. Яркостный край остаётся чётким; цветовой вынужден разгоняться через два пикселя. Они больше не совпадают, и это рассогласование вы и видите как цветовое растекание.
Есть и более тонкая, вторичная версия, о которой стоит знать, потому что она удивляет тех, кто думает «затронут только цвет». В гамма-кодированном сигнале вроде Y′CbCr цветовая ошибка фактически просачивается в видимую яркость: там, где насыщенный цвет встречает ненасыщенный, субдискретизация вызывает заметную потерю яркости прямо на границе – тёмную бахрому, – а не только размазывание цвета (Chan, «Toward Better Chroma Subsampling», SMPTE Motion Imaging Journal, 2008). Rec. 2020 определяет режим «постоянной яркости» (constant luminance) специально, чтобы этого избежать, но им почти никто не пользуется. Так что растекание может ещё и затемнить край, а не только размазать.
Цветовой сдвиг: неправильный рецепт, а не неправильный битрейт
Растекание – про то, сколько цветовой детали вы сохранили. Сдвиг – про правильную интерпретацию того цвета, что вы сохранили; и он может испортить файл, сжатый идеально.
Когда видео хранит цвет как luma плюс chroma, ему нужен рецепт обратного преобразования в красный, зелёный и синий, которые реально излучает экран. Этот рецепт – набор весов, задающих вклад каждого из R, G, B в яркость, – фиксирован стандартом, и для трёх эпох видео есть три распространённых:
- BT.601 для стандартной чёткости: яркость = 0,299·R + 0,587·G + 0,114·B.
- BT.709 для HD: яркость = 0,2126·R + 0,7152·G + 0,0722·B.
- BT.2020 для ultra-HD / широкого охвата: яркость = 0,2627·R + 0,6780·G + 0,0593·B.
Эти веса различаются, так что если файл закодировали рецептом BT.709, а плеер декодирует рецептом BT.601 – потому что метаданные «это BT.709» потеряли при транскоде или плеер просто предположил не то, – цвета выходят неправильными. Классическая подпись: красный темнеет, зелёный становится слишком ярким, ровный налёт по всему кадру (множество багрепортов по цветовой матрице во FFmpeg/OpenCV, 2020–2024). Лечение – не больше бит, а правильная сигнализация. Метаданные, которые её несут – colour primaries, transfer function и matrix coefficients, – стандартизированы как кодовые точки в ITU-T H.273 (2016), и правильно проставить эти три тега сквозь весь конвейер – это и есть то, что предотвращает сдвиг.
Статья – про сторону измерения, поэтому граница важна: как цветовые пространства, primaries и transfer-функции определяются и выбираются на стадии кодирования – это территория статьи о цветовых пространствах в разделе Video Encoding. Здесь важно лишь то, что цветовой сдвиг – реальный, частый цветовой артефакт, что это ошибка метаданных, а не битрейта, и – что критично для следующего раздела – что full-reference-метрика, сравнивающая правильно размеченный референс с неправильно декодированной копией, может его поймать, а может и нет, в зависимости от того, смотрит ли метрика вообще на цветовые каналы.
Почему ваша метрика качества слепа к цвету
Вот сердце статьи со стороны измерения. Две объективные метрики, на которые опирается большинство команд – PSNR и VMAF, – в своей повседневной форме только яркостные. Они оценивают канал яркости и почти полностью игнорируют цветовые каналы. Цветовые артефакты живут ровно в тех каналах, которые эти метрики пропускают.
Начнём с PSNR. Число, которое сравнивает сжатый кадр с оригиналом попиксельно, называется PSNR (Peak Signal-to-Noise Ratio, в децибелах), и в принципе его можно посчитать по любому каналу. Но на практике «PSNR» клипа почти всегда сообщают как Y-PSNR – только канал яркости. Инструменты считают все три (фильтр psnr во FFmpeg печатает psnr_y, psnr_u и psnr_v отдельно), но цветовые числа рутинно выбрасывают из отчётов, дашбордов и решений по лестнице битрейтов. Если вы смотрите только на Y-PSNR, клип, у которого яркость цела, а цвет растёкся или уехал, показывает вообще никакой ошибки.
Теперь VMAF – метрика, которой здесь вероятнее всего доверятся. VMAF (Video Multimethod Assessment Fusion, шкала 0–100) – слитная перцептивная метрика Netflix, и стандартная, повсеместно развёрнутая версия – назовём её VMAF v0 – сливает три feature (VIF, метрику потери детали ADM и motion-feature), которые все считаются по каналу luma. Netflix говорит это прямо в инженерном посте июня 2026, анонсирующем следующую версию: «VMAF v0 извлекает только luma-feature, поэтому не осведомлён о цветовых артефактах. На практике кодирование и масштабирование вносят цветовые артефакты через квантование и субдискретизацию» (Netflix Technology Blog, «VMAF v1: Good Is Not Good Enough», 2026). Читайте это как слова автора метрики о том, что де-факто отраслевое число качества не измеряет цвет.
Это тот же урок, что и временное слепое пятно в джаддере и стуттере: метрика не может оценить измерение, которое она ни разу не получает. Там это было время показа кадра; здесь – цветовые каналы. И, как всегда, пулинг делает только хуже – даже цветовая ошибка, которая попала в покомпонентное число, усредняется по кадру, пока локальное растекание на одном краю едва шевелит среднее. Это ещё одна запись в длинном списке того, где врут объективные метрики.
«Частая ошибка: сертифицировать цвет luma-числом. Дорогая ошибка – прогнать клип через «VMAF» или «PSNR», увидеть высокую оценку и подписать цвет. Стандартная модель VMAF и отчёт Y-PSNR подтвердили яркость, а не цвет. Клип может показать средний VMAF 96 и иметь красный текст, который заметно растекается на каждом кадре. Если в зоне ответственности – цветопередача (насыщенная графика, бренд-цвета, тона кожи, экранный текст, HDR с широким охватом), не давайте luma-метрике говорить за неё. Сообщайте покомпонентный chroma PSNR рядом с Y, добавьте перцептивную метрику цветоразличия, а для всего, что отгружается, – смотрите на насыщенные края. И никогда не сравнивайте два клипа с разной субдискретизацией (4:2:0 против 4:2:2) по luma-метрике так, будто число поймало разницу; оно не может.»
Как реально измерить цвет
Если повседневные метрики слепы к цвету, что его видит? Четыре честных варианта, примерно по возрастанию строгости.
Покомпонентный chroma PSNR. Самое дешёвое лечение – перестать выбрасывать две трети чисел, которые вы и так считаете. Фильтр psnr во FFmpeg возвращает psnr_y, psnr_u и psnr_v для каждого кадра; сообщайте и порогуйте значения U и V, а не только Y. Клип с цветовым растеканием покажет здоровый psnr_y и заметно более низкие psnr_u/psnr_v. Это не скажет, перцептивно ли плох дефект – PSNR слабо коррелирует с глазом, в цвете как и в яркости, – но скажет, что цветовые каналы получили повреждение, которое скрыло Y-число.
Перцептивные метрики цветоразличия: ΔE-ITP и CIEDE2000. В цветовой науке есть меры, специально построенные предсказывать, увидит ли человек разницу в цвете. CIEDE2000 (ΔE00, стандартизована CIE; Sharma, Wu, Dalal, 2005) сравнивает два цвета в перцептивно настроенном пространстве и возвращает одно число разности, где примерно ΔE = 1,0 – это едва заметная разница (JND): ниже ~1 большинство людей не видят, 2–3,5 – обычный предел коммерческой приемлемости. Для современного HDR и широкого охвата ITU ратифицировал преемника: ΔE-ITP, определённый в ITU-R BT.2124-0 (2019), который сравнивает цвета в пространстве ICtCp, спроектированном для HDR/WCG, и отмасштабирован так, что значение 1 снова равно одному JND. Они дают число цветовой ошибки, которое реально отслеживает восприятие, – то, чего chroma PSNR не делает.
Цветовая feature VMAF v1. По состоянию на июнь 2026 самая используемая перцептивная видеометрика наконец смотрит на цвет. VMAF v1, открытый Netflix, добавляет цветовую feature (модифицированный SpEED-QA, применённый к цветовым каналам) именно для того, чтобы поймать артефакты субдискретизации и квантования, которые v0 не видел (Netflix Technology Blog, 2026; на основе Chen et al., «Perceptual video quality prediction emphasizing chroma distortions», IEEE TIP, 2021). Это новое, и это важно: quality gate, построенный на VMAF v0, слеп к цвету по конструкции, а переход на v1 – это способ закрыть пробел внутри метрики, которой вы уже доверяете. Называйте версию – «VMAF» без версии больше не говорит читателю, измерили ли цвет.
Субъективное тестирование – истина в последней инстанции. Поскольку ни одна объективная цветовая метрика не идеальна, цветовое качество в конечном счёте решается так же, как всякое качество: правильно проведённым субъективным тестом, где зрители смотрят на насыщенные края, тона кожи и цветной текст в контролируемых условиях. Когда цветовая метрика и глаз расходятся, побеждает глаз, а метрика – это прокси, который не сработал.
| Метрика / метод | Что измеряет | Нужен референс | Где врёт по цвету |
|---|---|---|---|
| Y-PSNR | Ошибка яркости на кадр (дБ) | Full-reference | Слеп к цвету – измеряет только luma; растекание и сдвиг в цветовых каналах не видны |
| VMAF v0 | Слитная перцептивная оценка (0–100) | Full-reference | Только luma-feature; Netflix: «не осведомлён о цветовых артефактах» |
| Chroma PSNR (U/V) | Ошибка цветового канала на кадр (дБ) | Full-reference | Видит повреждение цвета, но PSNR слабо отслеживает глаз, а пулинг размывает локальное растекание |
| CIEDE2000 (ΔE00) | Перцептивное цветоразличие, шкала JND | Full-reference | Создан для цвета; по пикселям/патчам, нужны выровненные кадры; ориентирован на SDR |
| ΔE-ITP (BT.2124) | Перцептивное цветоразличие для HDR/WCG | Full-reference | Спроектирован для HDR/широкого охвата в ICtCp; 1 единица = 1 JND |
| VMAF v1 | Слитная оценка, включая chroma | Full-reference | Добавляет цветовую feature (модифицированный SpEED-QA); новинка 2026 – называйте версию |
| Субъективный тест | Цветовое качество по оценкам людей | По-разному | Истина в последней инстанции; медленнее и дороже, но единственный настоящий арбитр |
Таблица 1. Семь способов обойтись с цветовыми артефактами. Повседневные метрики (Y-PSNR, VMAF v0) слепы к цвету, потому что измеряют только яркость. Покомпонентный chroma PSNR – дешёвое первое лечение; ΔE-ITP и CIEDE2000 – перцептивные цветовые меры; VMAF v1 наконец вкладывает chroma в слитную оценку; глаз остаётся арбитром.
Разбор на числах: число, которое молчит
Сделаем слепое пятно наглядным. Возьмём тест-паттерн насыщенного красного текста на голубом фоне, закодируем его раз в 4:4:4 (полный цвет) и раз в 4:2:0 (четверть цвета) и измерим оба относительно мастера 4:4:4.
Канал яркости почти не меняется – яркостные края букв остаются там, где были, – поэтому Y-PSNR возвращается высоким, скажем 48 дБ, «визуально без потерь», число, которое большинство лестниц пропустит. Но измерьте цветовые каналы – и история переворачивается: psnr_u и psnr_v падают, скажем, до 32 дБ, потому что цветовые края вынудили разгоняться через блоки 2×2. Переведите эту краевую ошибку в перцептивную цветовую разницу – и худшие пиксели вдоль края текста окажутся на ΔE-ITP ≈ 4–6 – в несколько раз выше JND, равного 1, то есть явно видимы. Один файл, два вердикта: «отлично», если читать только Y, и «видимое цветовое растекание», как только посмотришь на цветовые каналы. Число не соврало про яркость; его просто ни разу не спросили про цвет.
Этот разрыв – высокий Y-PSNR, низкий chroma PSNR, надпороговый ΔE – и есть измерительная подпись цветового артефакта и причина существования этой статьи. (Числа выше иллюстрируют закономерность, а не измерены с конкретного клипа; скачиваемый детектор ниже воспроизводит то же соотношение на синтетическом кадре, чтобы вы увидели сами.)
Где здесь Фора Софт
Фора Софт строит видеософт с 2005 года – стриминг, конференции на WebRTC, e-learning, OTT, телемедицину и видеонаблюдение, – и цветопередача важна в части из них сильнее, чем команды ожидают. Телемедицинский поток, где тон кожи диагностичен, не терпит цветового сдвига BT.601/709; продукт для e-learning или шеринга экрана живёт и умирает на чётком цветном тексте, который 4:2:0 растекает; OTT-тайтл с насыщенной бренд-графикой показывает цветовые артефакты, которые luma-gate пропускает. Мы относимся к цвету как к отдельной измерительной задаче, отдельной от яркости: quality gate, который сообщает только Y-PSNR или VMAF v0, слеп к цвету по конструкции, поэтому мы сообщаем покомпонентный chroma PSNR рядом с luma, добавляем перцептивную проверку цветоразличия (ΔE-ITP для HDR-работ) и проверяем сигнализацию цветового пространства сквозь весь конвейер, чтобы файл декодировался тем рецептом, которым закодирован. Лечение следует за причиной – держать 4:2:2 или 4:4:4 там, где этого требуют насыщенные края и текст, и правильно проставлять primaries, transfer и matrix, чтобы ничего не уехало.
Ключевые выводы
- Растекание – локальное размазывание цвета от субдискретизации; сдвиг – глобальный уезд оттенка от неправильной матрицы декодирования.
- 4:2:0 хранит цвет в четверть разрешения, вдвое урезая сырые данные, – но размывает насыщенные края и цветной текст.
- Стандартный VMAF (v0) и обычный Y-PSNR – только яркостные; Netflix говорит, что v0 «не осведомлён о цветовых артефактах».
- Клип может читаться «отлично» по luma-метрике, пока цвет заметно растекается – метрика ни разу не видела цветовых каналов.
- Чтобы измерить цвет, используйте покомпонентный chroma PSNR, ΔE-ITP (BT.2124) или CIEDE2000, либо цветовую feature VMAF v1.
- Всегда называйте версию и канал метрики – «VMAF 96» больше не говорит, измерили ли цвет.