Содержание статьи +
- TL;DR
- Почему это важно
- Как выглядят рингинг и москитный шум
- Откуда они берутся: эффект Гиббса
- Почему москитный шум движется
- Где они бьют сильнее всего
- Как современные кодеки борются с рингингом: in-loop-фильтры
- Как реагируют метрики и где они врут
- Замечание об акутансе: когда лёгкий перелёт желателен
- Где здесь Фора Софт
- Ключевые выводы
- Что почитать дальше
TL;DR
Рингинг (он же звон, эффект Гиббса) – это слабое гало из ряби, которое кодек оставляет рядом с резким краем: призрак края, расходящийся наружу эхом. Москитный шум (mosquito noise) – тот же артефакт в движении: рой точек, пляшущий вокруг движущихся краёв и меняющийся каждый кадр, как комары вокруг лампы. У обоих одна причина: край построен из высокочастотной детали, блочное преобразование упаковывает эту деталь в свои самые высокочастотные коэффициенты, а квантование их выбрасывает – поэтому декодер восстанавливает край из слишком малого числа частот, и реконструкция перелетает и осциллирует (эффект Гиббса, с хрестоматийным перелётом около 9% высоты края). В отличие от бандинга, рингинг – это настоящая попиксельная ошибка, поэтому PSNR, SSIM и VMAF на него реагируют, но он прячется двумя способами: он локализован у краёв, где усреднение по всему кадру его размывает, и москитный шум темпоральный, где покадровые метрики вовсе не видят мерцания. Современные кодеки борются с ним in-loop-фильтрами, созданными под задачу, – Sample Adaptive Offset (SAO) в HEVC и направленным CDEF в AV1, – а честный способ измерить его – смотреть на области краёв и на движение, а не только на слитную оценку кадра.
Почему это важно
Если в вашем контенте есть жёсткие края – текст, субтитры, логотипы, графика, скриншоты, скринкасты, номерные знаки, – рингинг и москитный шум вероятнее всего сделают «чистое» кодирование дешёвым на вид, потому что урон кучкуется ровно там, куда глаз уже смотрит. Это ещё и артефакты, лучше всего обнажающие слабость одного числа качества: оценка усредняется по всему кадру, а рингинг живёт в тех 5% пикселей рядом с краями, поэтому усреднённый VMAF может показывать «норм», пока титр мерцает. Статья – для видеоинженера, ведущего по кодированию или QA-инженера, который видит гало вокруг текста, но хочет понять, почему именно оно образуется, почему оценка кадра его недооценивает и какие возможности кодека и привычки измерения его реально ловят. Сделайте это правильно – и ваши скринкасты и графика перестанут подставлять вас там, где зрители замечают первыми.
Как выглядят рингинг и москитный шум
Начнём с вида, потому что эти два артефакта – одна и та же физика на двух разных временны́х масштабах.
Рингинг – это набор слабых повторяющихся колебаний (ряби), идущих параллельно резкому краю и затухающих по мере удаления от него: высококонтрастная граница будто эхом отдаётся в плоскую область рядом. Вокруг чёрного текста на белом фоне это видно как серую дымку, обнимающую каждую букву; вокруг яркого логотипа на тёмном фоне – как ступенчатые призрачные контуры, уходящие наружу. Название буквально: сигнал картинки «звенит» рядом с краем, как колокол после удара. Рингинг – пространственный артефакт: его видно на одном остановленном кадре.
Москитный шум – это рингинг, который не желает стоять на месте. Когда край движется (ползущий титр, анимированный логотип, плечо человека, пересекающее чистую стену), узор ряби пересчитывается чуть иначе на каждом кадре, поэтому вместо неподвижного гало вы получаете облако мелких точек, мерцающих и ползающих вокруг края. Имя оно заслужило честно: суетливые сдвигающиеся точки похожи на рой комаров над объектом. Москитный шум – темпоральный артефакт: он гораздо заметнее при воспроизведении, чем на паузе, – именно поэтому покадровая проверка может пройти прямо мимо него.
Полезно отделить их от соседей по справочнику артефактов. Блочность – это сетка блоков, наложенная на всю картинку; бандинг – лестница в плавных градиентах. Рингинг и москитный шум другие: они липнут к краям и громче всего там, где жёсткий край сидит на спокойной поверхности.
Откуда они берутся: эффект Гиббса
Чтобы понять, почему край звенит, проследите, что кодек с ним делает. Механизм – то же квантование, что порождает блочность, но его эффект на крае иной, и его стоит проследить один раз.
Кодек разбивает каждый кадр на блоки и переписывает каждый блок дискретным косинусным преобразованием (DCT): описывает блок как сумму волновых паттернов, от плоского базового тона вверх ко всё более мелкой ряби. Гладкий участок – это в основном низкочастотные волны. Резкий край – наоборот: чистая ступень от тёмного к светлому требует высокочастотных волн, чтобы защёлкнуть переход на место, поэтому энергия края растекается по самым высокочастотным коэффициентам блока.
Теперь – бит-экономящий шаг. Квантование делит силу каждого коэффициента на шаг и округляет, и мелкие высокочастотные коэффициенты округляются прямо в ноль. Для гладкого блока это нормально – он ими почти не пользовался. Для блока с краем в этом вся проблема: декодеру приходится восстанавливать резкую ступень из усечённого набора частот, а ступень, восстановленная из слишком малого числа частот, не может остаться плоской ни с одной стороны. Она перелетает сразу за краем, отскакивает назад, снова перелетает (слабее) и колебанием приходит к покою – это и есть рябь, которую вы видите как рингинг.
Это не баг кодека; это закон фурье-реконструкции, называемый эффектом Гиббса. Восстановите любую резкую ступень из ограниченной полосы частот – и результат перелетит ступень на фиксированную долю, сколько частот ни оставь. Хрестоматийная цифра выразительна: перелёт устанавливается на около 9% высоты ступени (точнее ≈8,95%), и добавление частот делает рябь у́же и теснее к краю, но никогда не ниже. Возьмите среднеконтрастный край со ступенью в 128 кодовых значений; гиббсовский перелёт – около 0,0895 × 128 ≈ 11 кодовых значений призрака рядом с краем. Край «чёрный→белый» в тексте прыгает дальше и перелетает сильнее – поэтому текст звенит так заметно.
Одно различие, к которому литература относится аккуратно, – стоит и вам. Первый горб – сигнал, выстреливающий за значение края, – это перелёт (overshoot); затухающая рябь, идущая за ним, – это рингинг (звон). Обычно они приходят вместе, и большинство называет всё это «рингингом», но различие важно для одного средства, которое встретится дальше: лёгкий перелёт – это как раз то, чем повышение резкости делает края чёткими.
Почему москитный шум движется
Рингинг становится москитным шумом в тот миг, когда край движется, и причина в том, что кодек заново решает край с нуля на каждом кадре.
Между одним кадром и следующим движущийся край стоит в чуть ином субпиксельном положении, иначе ложится на сетку блоков и предсказывается из иного референсного участка компенсацией движения. Каждое из этих изменений подаёт квантователю чуть иной набор высокочастотных коэффициентов на округление, поэтому узор «перелёт-и-рябь» оказывается каждый раз чуть в другом месте. Глаз интегрирует эти дрожащие гало во времени и читает их как рой ползающих точек – яркость и цвет колеблются от кадра к кадру в плавно текстурированной зоне, обнимающей край. Это темпоральное мерцание – подпись москитного шума, и поэтому его относят к движущимся артефактам, тогда как простой рингинг неподвижен.
Из этого следуют два практических вывода. Во-первых, москитный шум хуже всего на высококонтрастных движущихся краях поверх спокойных фонов – ползущие белые субтитры, анимированный логотип, тёмные перила на панораме по яркому небу, – потому что у ряби есть тихая поверхность для мерцания. Во-вторых, поскольку артефакт определяется своим изменением во времени, любое измерение, смотрящее на один кадр изолированно, структурно к нему слепо. Запомните это до раздела о метриках.
Где они бьют сильнее всего
Рингинг и москитный шум разборчивы к контенту, и знание, где они кусают, говорит, куда смотреть.
Громче всего они на синтетических высококонтрастных краях: текст и субтитры, логотипы каналов и водяные знаки, элементы интерфейса в скринкасте, контурная графика мультфильмов и аниме, графики и слайды в e-learning-захвате, чёткие границы графики поверх видео. Снятый камерой материал мягких природных сцен звенит куда меньше, потому что реальные края и так слегка мягкие, а рядом есть текстура для маскировки ряби. Артефакту нужны две вещи, чтобы стать заметным, – жёсткий край и спокойная поверхность рядом, – и скринкаст-контент щедро даёт обе. Это тот артефакт, из-за которого «да просто сожмём вебинар» идёт не так.
Цвет ухудшает дело одним конкретным образом. Поскольку большинство пайплайнов доставки хранят цвет в пониженном разрешении (chroma subsampling, обычно 4:2:0), цветовые каналы квантуются ещё грубее яркости, поэтому рингинг на цветном крае может показаться каймой не того цвета рядом – пурпурным или голубым призраком вдоль насыщенной границы. Деталь со стороны причины – почему цвет субдискретизируется – лежит в статье Video Encoding про цветовые пространства; здесь же просто отметим: субдискретизированный цвет звенит в цвете.
Как современные кодеки борются с рингингом: in-loop-фильтры
Поскольку рингинг встроен в то, как блочные преобразования обращаются с краями, каждый современный кодек везёт специальную машинерию, чтобы вычистить его перед показом кадра – и, что важно, перед сохранением кадра как референса для следующего. Это in-loop-фильтры (внутрипетлевые): нормативные, встроенные в кодек, применяемые внутри петли кодирования. Три из них важны для краёв.
Первым идёт деблокинг-фильтр. DCT концентрирует ошибку на границах блоков, поэтому деблокинг сглаживает швы между блоками – его главная задача блочность, но поскольку рингинг часто едет вдоль границы блока, хороший проход деблокинга смягчает и часть его. H.264, HEVC и AV1 все его несут.
HEVC добавляет второй фильтр, нацеленный точнее на рингинг: Sample Adaptive Offset (SAO). После деблокинга SAO классифицирует каждый пиксель и добавляет небольшой корректирующий сдвиг целым группам пикселей. Его режим edge offset смотрит, как каждый пиксель соотносится с соседями вдоль выбранного направления, и подталкивает перелёты и недолёты обратно туда, где должен быть край, – а это ровно тот рингинг, что оставило высокочастотное квантование. SAO существует в стандарте H.265/HEVC во многом чтобы ослабить рингинг от грубого квантования высокочастотных коэффициентов на сильных краях.
AV1 идёт дальше всех с Constrained Directional Enhancement Filter (CDEF) – чистейшим примером дерингинг-фильтра, созданного убирать рябь, не размазывая породивший её край. CDEF сперва выясняет направление края в каждом блоке, выбирая одну из восьми ориентаций, затем гонит ограниченный низкочастотный фильтр в основном вдоль этого края и слабо поперёк. «Ограниченный» (constrained) – в этом и трюк: пофункция-ограничитель на каждый тап игнорирует соседние пиксели, слишком отличные от центрального, поэтому фильтр чистит рябь в спокойной зоне рядом с краем, но оставляет сам край резким. Поскольку он следует за краями, а не размывает во всех направлениях, CDEF убирает рингинг и DCT-«базисный шум», сохраняя чёткий переход. (Затем у AV1 есть опциональная стадия loop restoration – фильтры Винера и self-guided – для общей зачистки.) Полный фильтр описан его авторами, Midtskogen и Valin, в статье про CDEF.
На старом контенте или когда вы получаете уже повреждённый файл, запасной вариант – постобработочный дерингинг-фильтр. В FFmpeg его несёт устаревший libpostproc (pp=dr, дерингер эпохи MPEG-4), хотя его выводят из обихода и он всегда был рассчитан лишь на старые MPEG-форматы; современные пайплайны опираются на in-loop-фильтры выше и на простую выдачу краям большего числа бит. Рычаги со стороны кодирования очевидны: поднять битрейт или снизить квантователь, чтобы отбрасывалось меньше высокочастотных коэффициентов; держать in-loop-фильтры включёнными (выключение их ради «сохранения резкости» меняет немного мягкости на много рингинга); использовать кодек с правильными инструментами – скринкаст и графика выигрывают от выделенной обработки краёв в новых кодеках. Компромисс «слишком сильное фильтрование» – тема статьи Размытие и потеря детали.
Как реагируют метрики и где они врут
Вот где рингинг ведёт себя иначе, чем его собрат бандинг, и различие поучительно.
Рингинг – это настоящая попиксельная ошибка. Рябь рядом с краем по-настоящему отличается от исходных пикселей, поэтому, в отличие от бандинга, чья ошибка в одно кодовое значение почти невидима математике, рингинг регистрируется в PSNR, SSIM и VMAF. Структурный член SSIM реагирует на нарушенный край; фичи потери детали и достоверности в VMAF реагируют на добавленную рябь. Поэтому первое, что нужно сказать честно: полнореференсные метрики не слепы к рингингу так, как они слепы к бандингу.
Но рингинг прячется двумя другими способами, и оба про то, где сидит ошибка, а не существует ли она.
Первый – пространственный пулинг. Рингинг сосредоточен в тонкой полосе пикселей рядом с краями – часто несколько процентов кадра, – тогда как остальная картинка чиста. Оценка кадра усредняет ошибку по каждому пикселю, поэтому громкая ошибка края размывается тихим большинством. Пройдём арифметику. Пусть полоса рингинга покрывает около 5% кадра со среднеквадратичной ошибкой 100 (RMS-ошибка около 10 кодовых значений, что согласуется с тем гиббсовским перелётом ~11, затухающим), а остальные 95% почти идеальны:
MSE кадра = 0.05 × 100 + 0.95 × 0 = 5
PSNR кадра = 10 · log10(255² / 5)
= 10 · log10(65025 / 5)
= 10 · log10(13005)
= 41.1 дБ → читается «очень хорошо»
PSNR полосы края = 10 · log10(255² / 100)
= 10 · log10(650.25)
= 28.1 дБ → читается «заметно деградировано»Разрыв в 13 дБ между кадром и краями, из которых он построен. Число не врёт про среднее; оно врёт про восприятие, потому что глаз зрителя на краях в 28 дБ, а не на среднем в 41 дБ. Это та же ловушка, что разобрана в статье Пулинг покадровых оценок в одно число: среднее прячет локализованный дефект.
Второй – время. Москитный шум определяется мерцанием, а популярные полнореференсные метрики оценивают один кадр против его референса и затем усредняют по кадрам. Горстка кадров, где рой плох, усредняется со множеством, где он мягок, и темпоральное ползание – то, что зритель на самом деле замечает, – вообще не входит в число. У покадровой метрики нет оси для «это мерцает».
Сильнейшее свидетельство, что метрики недооценивают этот артефакт, идёт от тех, кто построил фильтр, чтобы его убрать. Когда тестировали дерингинг CDEF в AV1, он дал статистически значимое субъективное улучшение на половине тестовых клипов – выигрыш, обычно стоящий 5–10% эффективности кодирования, – тогда как объективное улучшение в PSNR и SSIM было лишь около 1%. Как сказали авторы фильтра, визуальные улучшения, мотивирующие дерингинг, в основном за пределами оценочной способности примитивных объективных инструментов вроде PSNR или SSIM. Когда удаление артефакта едва двигает метрику, но явно помогает зрителям, метрика недосчитывает артефакт.
| Метрика | Что измеряет | Нужен референс | Где она врёт на рингинге и москитном шуме |
|---|---|---|---|
| PSNR | Средняя попиксельная ошибка (дБ) | Полнореференсная | Видит энергию ряби, но усреднение по кадру размывает локализованный у краёв рингинг; нет оси времени для мерцания |
| SSIM | Структурное сходство (0–1) | Полнореференсная | Реагирует на нарушенную структуру края; всё ещё покадровая и оконно-усреднённая, поэтому локальная рябь размывается |
| VMAF | Слитная перцептивная оценка (0–100) | Полнореференсная | Фичи потери детали реагируют на рингинг лучше PSNR; модель по умолчанию пространственная, поэтому темпоральное ползание москита недооценено |
| VMAF (перцентильный пулинг) | Покадровый VMAF, пулинг по перцентилю | Полнореференсная | Min/низкий перцентиль вытаскивает рингинг плохих кадров, который скрыло бы среднее; всё же не истинная мера мерцания |
| Безреференсная edge-busyness | Энергия ряби рядом с краями; изменение от кадра к кадру | Безреференсная | Создана под это: оценивает приграничную полосу и её темпоральное дрожание; правильный инструмент для лайва, UGC и скринкаста |
Табл. 1. Пять способов измерения по-разному обходятся с рингингом и москитным шумом. Полнореференсные метрики видят рингинг (это настоящая попиксельная ошибка), но размывают его усреднением по пространству и времени; темпоральному мерцанию москита нужен либо перцентильный пулинг, либо безреференсный детектор edge-busyness. Читайте области краёв, а не только среднее по кадру.
«Частая ошибка: закрывать скринкаст по усреднённой оценке кадра. Дорогая ошибка здесь – прочитать «VMAF 95, отгружаем» на вебинаре, захвате слайдов или промо с логотипами, где каждый дефект собран на краях текста и графики, составляющих несколько процентов кадра. Среднее усредняет мерцание прочь, и артефакт добирается ровно до того типа контента – резких синтетических краёв, – к которому зрители чувствительнее всего. Когда у контента жёсткие края, измеряйте области краёв отдельно, используйте низкоперцентильный (не средний) темпоральный пулинг, чтобы плохие кадры не прятались, и смотрите движущийся клип, а не стоп-кадр – москитный шум проявляется только в движении. Вторая ловушка на другом конце: переусиление резкости, добавляющее гало нарочно, может поднять видимую резкость, посеяв рингинг, который метрика не отметит, – так что не гонитесь за акутансом за точку, где край начинает звенеть.»
Замечание об акутансе: когда лёгкий перелёт желателен
Одна тонкость держит дерингинг честным. Первая часть артефакта – перелёт прямо на крае – это тот же механизм, что фильтры резкости используют намеренно: малый перелёт повышает акутанс, видимую резкость края, преувеличивая контраст поперёк него. Поэтому unsharp mask «вытягивает» картинку, и поэтому некоторые JPEG-кодеры намеренно дают краю перелететь, а затем клиппируют его, чтобы замаскировать рингинг. Грань между «чётко» и «звенит» поэтому перцептивная, а не абсолютная: щепотка перелёта читается как резкость, поезд затухающей ряби – как дефект. Настраивая дерингинг-фильтр или резкость, вы выбираете, где на этой грани сидеть, – ещё одна причина, по которой здесь финальный судья глаз, а не метрика.
Где здесь Фора Софт
Фора Софт делает видеософт с 2005 года – стриминг, WebRTC-конференции, e-learning, OTT, телемедицину и видеонаблюдение, – и рингинг наша работа встречает чаще всего, потому что так много её насыщено краями: общие слайды и экраны в e-learning и конференциях, субтитры и логотипы каналов в OTT и текст, который важнее всего в видеонаблюдении, – номерные знаки и таймстемпы. Мы трактуем это как задачу измерения известной формы: найти сильные края, оценить рябь в полосе рядом с ними и то, как она мерцает от кадра к кадру, и никогда не закрывать насыщенное краями кодирование усреднённым по кадру числом, которое усредняет мерцание прочь. Средства тогда следуют за причиной – больше бит туда, где живут края, нужные in-loop-фильтры оставлены включёнными, правильный кодек для скринкаста, – и где это помогает решению, мы указываем на собственные данные бенчмарков, чтобы вы проверяли метод, а не верили на слово.
Ключевые выводы
- Рингинг – гало из ряби рядом с резким краем; москитный шум – это гало, мерцающее от кадра к кадру на движущемся крае.
- У обоих причина одна: квантование выбрасывает высокочастотные коэффициенты, нужные краю, – эффект Гиббса, перелёт ~9%.
- Сильнее всего бьют по тексту, логотипам, субтитрам и скринкасту – жёсткие края на спокойных фонах.
- Кодеки борются с ними in-loop-фильтрами: деблокинг, SAO в HEVC и направленный CDEF в AV1.
- В отличие от бандинга, рингинг – настоящая попиксельная ошибка, поэтому PSNR/SSIM/VMAF его видят, но усреднение по кадру его размывает.
- Москитный шум темпоральный: измеряйте области краёв и берите перцентильный (не средний) пулинг, и смотрите в движении.