Макроблокинг и сетка DCT: причина и измерение

Автор: Николай СапуновОбновлено: август 202613 мин чтения
Содержание статьи +

TL;DR

Блочность (она же макроблокинг) – самый узнаваемый артефакт сжатия: картинка распадается на видимые квадраты, потому что каждый современный кодек сжимает кадр на сетке блоков и при низком битрейте квантует соседние блоки так грубо, что они перестают совпадать на общей границе. Сетка реальна и считаема – в кадре 1920×1080 помещается 32 400 трансформных блоков 8×8, и каждый – потенциальный шов. Кодеки борются с ней нормативным внутрицикловым деблокинг-фильтром (определён внутри H.264/AVC и HEVC, в AV1 к нему добавлены CDEF и loop restoration), и именно поэтому сильно сжатое современное видео скорее мягкое, чем «плиточное» – блочность меняют на размытие. Популярные полнореференсные метрики ловят блочность лучше большинства артефактов, потому что это пространственная структурная ошибка, но PSNR недооценивает видимый шов, поэтому в контроле качества рядом с числом стоит держать перцептивную или специальную метрику блочности и взгляд на плоские области, где сетка проступает первой.

Почему это важно

Если вы кодируете или принимаете видео по QC, блочность – это тот артефакт, который клиент сфотографирует и пришлёт вам, потому что его видит и называет даже не инженер. Понимание, где именно она рождается – на сетке блочного преобразования и его квантователе, – подсказывает, какая ручка реально её чинит, а какая «починка» лишь прячет её за мягкостью. Статья написана для видеоинженера, ведущего по кодированию или QA-инженера, который видит плитки, но хочет их измерить, привязать к настройке и выбрать метрику, которая их не пропустит. Это первый глубокий разбор в галерее артефактов, потому что блочность – самое ясное окно в то, как работает любой блочный кодек и где он ломается.

Что такое блочность на самом деле

Начнём с вида. Блочность – это распад картинки на видимые квадраты или прямоугольники, словно изображение пересобрали из грубой мозаичной плитки. На лице это уплощает щёки в грани; на небе кладёт шахматную доску; в движении заставляет целые плитки отставать на такт от остального кадра. Привычное имя макроблокинг идёт от макроблока – блока 16×16 пикселей, который старые кодеки обрабатывали как целое, – но квадраты, что вы видите, и есть служебная сетка кодека, проступающая сквозь картинку.

Ключевая мысль, и причина, по которой справочник вообще возможен: эта сетка не случайна. Это фиксированная решётка, которую кодер наложил на кадр ещё до того, как что-либо сжал. Когда артефакт появляется, он появляется на этой решётке – прямые горизонтальные и вертикальные швы через равные промежутки, – и именно это позволяет глазу (и метрике) узнать его мгновенно. Облако случайного шума может быть чем угодно; чистая сетка швов может быть только одним.

Помогает представить сжатие как облицовку стены мелкой квадратной плиткой, где каждую плитку затирают отдельно. Положите аккуратно – стена читается как одна поверхность. Сделайте наспех – каждая плитка сядет чуть на другой высоте, свет поймает каждый шов затирки, и сетка выскочит. Блочность – это те линии затирки: плитки (блоки) обработали независимо, и при низком битрейте они больше не стыкуются заподлицо.

Откуда берётся сетка: блочно-трансформное кодирование

Каждый массовый кодек – H.264/AVC, HEVC, AV1 – это блочно-трансформный кодер. Он режет кадр на блоки и сжимает каждый блок отдельно дискретным косинусным преобразованием (DCT) – математическим шагом, который переписывает пиксели блока как сумму волновых паттернов, от плоской волны «средней яркости» до мелкой ряби. Гладким блокам нужны лишь первые несколько волн; детальным – много. Представление блока в виде волн и делает возможным следующий шаг – выбросить часть из них.

Этот следующий шаг – квантование: кодер делит силу каждой волны (её DCT-коэффициент) на шаг и округляет до ближайшего целого, что полностью удаляет мелкие высокочастотные волны. Квантование – там, где экономятся биты и происходит потеря. Чем грубее шаг – чем ниже целевой битрейт, – тем больше волн округляется в ноль, и тем сильнее каждый блок сваливается к одному плоскому тону.

Вот механизм в одном предложении: поскольку DCT считается для каждого блока независимо и никогда не моделирует корреляцию через границы блоков, два соседних блока могут округлиться к двум разным плоским тонам, и картинка получает видимую ступень ровно на шве между ними. Классическая таксономия искажений Юэна и Ву назвала это определяющей причиной эффекта блочности, а Ван, Бовик и Эванс смоделировали блочную картинку именно как чистое изображение с добавленным «блочным сигналом», живущим на сетке.

Замечание о сетках, потому что на терминах люди спотыкаются. Макроблок (16×16 в H.264) и его наследники – Coding Tree Units до 64×64 в HEVC, суперблоки до 128×128 в AV1 – это крупные единицы, на которые кодек делит кадр для предсказания. Внутри них DCT работает на меньших трансформных блоках (4×4 и 8×8 в H.264; от 4×4 до 32×32 в HEVC; до 64×64 в AV1). Швы, что вы видите, могут лечь на любую из сеток, поэтому практичный термин остаётся обобщённым «блок», а не «макроблок» – современная сетка переменная, а не фиксированные 16×16.

Рисунок 1. Как рождается сетка. Каждый блок преобразуется и квантуется сам по себе; грубое округление уплощает его до чуть иного тона, и несовпадение проступает швом на решётке.

Почему она появляется на низком битрейте и где прячется

Блочность – артефакт битрейтового голодания. При щедром битрейте шаг квантователя мал, большинство DCT-волн выживает, и соседние блоки восстанавливаются достаточно близко, чтобы шов остался ниже порога глаза. Заморите кодирование – и шаг растёт: в пределе выживает лишь средняя яркость каждого блока (его DC-коэффициент), каждый блок становится плоским квадратом, и кадр превращается в буквальную мозаику сплошных плиток. Механика квантования и управления битрейтом со стороны кодера – как задаётся шаг квантователя и краткая версия того, как читать метрики при настройке кодека, – принадлежит разделу Video Encoding обзору метрик качества; здесь мы остаёмся на распознавании и измерении результата.

Где сетка проступает первой – то, что стоит запомнить, потому что это говорит, куда смотреть. Блочность виднее всего в гладких, малодетальных областях – чистое небо, студийная стена, медленный градиент, – где маленькой ступени между двумя плоскими тонами нечем прикрыться, и глаз цепляется за прямой шов. Виднее всего меньше в насыщенной текстуре – листва, гравий, волосы, – где окружающая деталь маскирует границу. Это текстурная маскировка, и поэтому проверку на блочность стоит начинать с самой плоской части кадра, а не с самой занятой.

Арифметику того, почему это важно для измерения, стоит проделать вслух один раз, потому что она вскрывает ловушку. Возьмём 8-битную картинку, где каждый пиксель идёт 0–255, а пиковое значение – 255. Допустим, плоский участок, который был ровным 128, восстановился как два соседних блока: левый сел на 125, правый – на 131. Каждый пиксель ошибается на 3, поэтому среднеквадратичная ошибка равна 3² = 9, а пиковое отношение сигнал/шум – метрика «сырой» пиксельной ошибки, в децибелах – это:

PSNR = 10 · log10(255² / MSE)
     = 10 · log10(65025 / 9)
     = 10 · log10(7225)
     = 38,6 дБ

PSNR 38,6 дБ читается как чистое кодирование по любому эмпирическому правилу. Но ступень в шесть кодовых значений, идущая прямо по середине плоского поля, отчётливо видна – глаз создан находить ровно такой прямой яркостный край. Этот разрыв между «38,6 дБ, выглядит нормально» и швом, на который можно ткнуть пальцем, – и есть вся причина, по которой блочности нужно отдельное внимание в рабочем процессе измерения.

Деблокинг-фильтр, который с ней борется

Современные кодеки не оставляют швы в покое. Внутрь стандартов H.264/AVC и HEVC встроен нормативный внутрицикловый деблокинг-фильтр (in-loop deblocking): после восстановления кадра кодек проходит по границам блоков и сглаживает те, что выглядят искусственными ступенями, а не настоящими краями сцены. «Внутрицикловый» – важное слово: отфильтрованный кадр возвращается в петлю предсказания и становится опорным для последующих кадров, поэтому кодер и декодер обязаны применять идентичный фильтр, иначе они разойдутся. Это не то же самое, что постобработочный деблокинг, который вы применяете только при показе и который никогда не трогает петлю предсказания.

Фильтр намеренно осторожен, чтобы не стереть настоящую деталь. В H.264 он идёт по каждой границе трансформного блока 4×4 или 8×8 и решает для каждой границы, насколько сильно сглаживать, по силе границы (boundary strength) от 0 (не трогать) до 4 (сильнейшее), задаваемой тем, были ли блоки внутрикадровыми (intra), несут ли они кодированные коэффициенты и насколько крута яркостная ступень. Максимум он правит три пикселя с каждой стороны шва. HEVC упрощает это до деблокинг-сетки 8×8 с тремя уровнями силы, затем добавляет вторую внутрицикловую стадию, Sample Adaptive Offset (SAO), которая сдвигает значения пикселей по областям, отыгрывая точность. AV1 идёт ещё дальше, выстраивая три опциональные внутрицикловые стадии – деблокинг-фильтр, затем Constrained Directional Enhancement Filter (CDEF), нацеленный на рябь, затем фильтр восстановления (loop restoration), – с выбором силы для каждого суперблока.

Деблокинг-фильтр себя оправдывает. Команда, спроектировавшая фильтр H.264, сообщила, что его включение срезало битрейт примерно до 9% при равном качестве или, эквивалентно, подняло качество при равном битрейте – крупная экономия для одного внутрициклового инструмента. У этой выгоды есть побочный эффект, который вы уже видели, не называя: когда у кодера кончаются биты, деблокинг-фильтр сглаживает неизбежную ошибку в мягкость вместо швов. Это центральный размен видео низкого битрейта – блочность меняют на размытие, – и поэтому сильно сжатые современные потоки выглядят мутными там, где видео образца 2005 года выглядело бы плиточным. Сторона размытия в этом размене получает собственный разбор в статье Размытие и потеря деталей.

Из этого следуют два рабочих рычага. На стороне кодирования x264 и x265 открывают внутрицикловый фильтр через управление --deblock alpha:beta (и переключатель --no-deblock); выключение его «ради резкости» – частый способ отгрузить видимые плитки, поэтому оставляйте его включённым, пока не измерили причину поступить иначе. На уже повреждённом материале, который нельзя перекодировать начисто, постобработочный деблокинг – фильтр deblock в FFmpeg или старые постпроцессоры pp/spp – может снять остроту существующей блочности ценой деталей.

# Перекодировать с включённым внутрицикловым деблокинг-фильтром (по умолчанию в x264), слегка ослабленным
ffmpeg -i input.mov -c:v libx264 -crf 23 -x264-params "deblock=-1:-1" output.mp4

# Постобработать видимую блочность на материале, который нельзя перекодировать из источника
ffmpeg -i blocky_input.mp4 -vf "deblock=filter=strong:block=8" -c:v libx264 -crf 18 deblocked.mp4
Рисунок 2. Деблокинг-фильтр. Он сглаживает искусственные швы внутри петли – H.264 по силе границы, HEVC добавляет SAO, AV1 добавляет CDEF и loop restoration, – меняя видимую блочность на лёгкую мягкость.

Как измерить блочность и где врут метрики

Блочность – самый дружелюбный артефакт для популярных полнореференсных метрик, потому что это ровно то, что они созданы видеть: пространственная структурная разница между референсом и кодировкой, сидящая в яркостном (luma) канале, куда метрики кладут основной вес. SSIM (Structural Similarity, структурное сходство 0–1) и VMAF (Video Multimethod Assessment Fusion, перцептивная оценка Netflix 0–100) обе неплохо отслеживают блочность, и даже PSNR движется в верную сторону. Поэтому, в отличие от бандинга или джаддера – настоящих слепых зон метрик, каталогизированных в Где врут объективные метрики, – блочность в целом регистрируется.

Ложь тоньше: это вопрос веса, а не слепоты. Как показал разбор с числами, PSNR оценивает видимый шов как малую пиксельную ошибку, поэтому блочная кодировка может выдать приличный PSNR, выглядя при этом явно плиточной на плоских областях. PSNR измеряет пиксельное расстояние, а не то, легла ли ошибка на прямую линию, за которой охотится глаз. Опирайтесь на перцептивную метрику (SSIM или VMAF), когда подозреваемый – блочность, и никогда не подписывайте кодировку по одному PSNR – полный разбор претензий к пиксельным метрикам в статье PSNR: объяснение.

Есть также схема измерения, которую полнореференсные метрики попросту не обслуживают: живые потоки и пользовательский контент (UGC), где нет первозданного оригинала для сравнения. Для них нужна безреференсная (no-reference) метрика блочности – та, что находит сетку по одному закодированному кадру. У исследований есть чистый ответ. Ван, Бовик и Эванс показали, что блочность можно найти вслепую, взяв разности вдоль каждой строки и столбца и прогнав FFT: блочная картинка ставит резкие пики в спектре мощности на частоте сетки блоков (N/8 и её гармоники для сетки 8 пикселей), а у чистой картинки их нет. Размер этих пиков и есть мера блочности. Более ранняя работа Ву и Юэна (Generalized Block-edge Impairment Metric, GBIM) и более поздняя PSNR-B, добавляющая к PSNR член блочности, атакуют ту же задачу со стороны пикселей.

МетрикаЧто измеряетНужен референсГде врёт на блочности
PSNRСредняя пиксельная ошибка в дБПолнореференснаяЛовит, но недооценивает видимый шов как малую ошибку
SSIMСтруктурное сходство, 0–1ПолнореференснаяХорошо отслеживает; одно число прячет, какая область задета
VMAFСлитная перцептивная оценка, 0–100ПолнореференснаяХорошо отслеживает; указывайте модель и доверительный интервал
PSNR-BPSNR плюс член блочностиПолнореференснаяСоздана под блочность; всё ещё нужен первозданный оригинал
Blind FFT (Ван-Бовик)Мощность на частоте сеткиБезреференснаяРаботает на live/UGC; может ложно срабатывать на реальной сеточной текстуре
GBIMВзвешенная разность на границахБезреференснаяМожет переучесть реальный край, легший на сетку

Таблица 1. Шесть способов поставить число на блочность. Полнореференсные метрики её видят; безреференсные – то, к чему тянешься на live и UGC, где оригинала нет. Сопровождайте число взглядом на плоские области, где блочность проступает первой.

Рисунок 3. Поведение метрик на блочности. Полнореференсные её ловят (PSNR недооценивает); безреференсные детекторы – те, что работают на live и UGC. Вердикт несут и цвет, и колонка, поэтому ни один из них не одинок.

Безреференсный подход через FFT стоит ещё одного предложения, потому что он так нагляден. Когда вы строите спектр мощности разностей строк и столбцов блочного кадра, сетка блоков заявляет о себе всплеском на одной конкретной частоте – обратной размеру блока, – поднимающимся над гладкой кривой натурального изображения. Этот всплеск и есть артефакт, выраженный числом. Небольшой безреференсный детектор на этой идее мы прикладываем ниже.

Рисунок 4. Сигнатура блочности. В частотной области сетка блоков – это всплеск на частоте сетки (N/8) и её гармониках: есть в блочном кадре, нет в чистом. На это и опирается безреференсный детектор.
«Частая ошибка: выключить деблокинг-фильтр «чтобы оставить резкость». Когда кодировка выглядит мягкой, соблазн – отключить внутрицикловый деблокинг-фильтр, чтобы деталь выжила. На лёгком контенте при здоровом битрейте это может чуть помочь; на заморенном битрейте это просто меняет лёгкую мягкость на жёсткие видимые плитки – худший из двух артефактов и тот, что замечают клиенты. Деблокинг-фильтр нормативен и битрейт-эффективен не зря; реальное лечение «мягкость-или-блочность» – это больше бит, лучший пресет или более низкое разрешение на выпуклой оболочке, а не выключение фильтра. И никогда не объявляйте кодировку чистой по одному PSNR – подтвердите плоские области глазом или метрикой блочности.»

Где здесь Фора Софт

Фора Софт выпускает видеопродукты с 2005 года – стриминг, WebRTC-конференции, OTT, e-learning, телемедицина и видеонаблюдение, – и блочность доходит до нас чаще других жалоб, потому что её видит и описывает конечный пользователь. Блочный поток с камеры наблюдения – обычно вопрос битрейта или управления битрейтом на камере или транскодере, тогда как блочность, всплывающая только после сетевой просадки, – вопрос доставки, и чинят их в разных местах. Мы относимся к блочности как к задаче измерения в первую очередь: найти сетку, подтвердить на плоских областях, решить, делает ли внутрицикловый фильтр свою работу, и лишь затем менять настройку. Где это помогает решению, мы указываем на собственные бенчмарк-данные, чтобы вы могли проверить метод, а не верить нам на слово.

Ключевые выводы

  • Блочность – это видимая сетка блоков, проступающая сквозь картинку; она рождается на трансформной решётке кодека.
  • Грубое квантование уплощает каждый блок до иного тона, поэтому на границах открываются швы.
  • Она проступает первой в гладких областях и прячется в насыщенной текстуре (текстурная маскировка).
  • Внутрицикловый деблокинг-фильтр (H.264/HEVC/AV1) меняет блочность на лёгкую мягкость.
  • PSNR ловит блочность, но недооценивает; опирайтесь на SSIM, VMAF или метрику блочности.
  • Для live и UGC без референса используйте безреференсный детектор блочности.

Что почитать дальше

Строите такую систему?

Подберём параметры кодирования под ваш контент и посчитаем стоимость доставки до старта разработки.