PSNR простыми словами: что измеряет и где врёт

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

Кратко

Peak Signal-to-Noise Ratio, почти всегда записываемое как PSNR, – это число, которое измеряет, насколько сжатое видео отклонилось от оригинала, считая пиксельную ошибку и выражая её в децибелах: больше – лучше, а у одинаковых файлов оно равно бесконечности. PSNR – метрика, с которой все начинают, потому что она быстрая, не требует обучающих данных, не имеет лицензии и работает где угодно – поэтому каждый кодировщик тихо использует её разновидность внутри своего цикла оптимизации. Но PSNR измеряет пиксельную ошибку, а не то, что видит глаз: она одинаково взвешивает различие на лице и различие в плоском небе, так что два клипа с одинаковым PSNR могут выглядеть очевидно по-разному. Эта статья показывает, что именно вычисляет PSNR, проговаривает децибельную математику вслух, называет значения, которых стоит ожидать, точно указывает, где число врёт, и показывает, когда PSNR всё ещё правильный инструмент.

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

Если вы измеряете качество видео, PSNR – первое число, которое вы увидите, и первое, которому захочется чрезмерно довериться. Оно встречается в логах кодировщиков, в выводе FFmpeg, в маркетинговых графиках вендоров и в академических таблицах – обычно без объяснения, что оно может и чего не может сказать. Эта статья даёт такое объяснение, чтобы вы читали значение PSNR как скептик: понимая, что оно измеряет, для каких сравнений оно валидно и на каком именно контенте оно введёт вас в заблуждение. Это фундамент для перцептивных метрик, которые идут следом, – SSIM и VMAF, – обе они существуют именно потому, что PSNR оказалось недостаточно.

Что PSNR на самом деле измеряет

Начнём с того, на чём PSNR построено, потому что название это прячет. Под децибелами PSNR – это измерение пиксельной ошибки: насколько в среднем каждый пиксель сжатого видео отличается от того же пикселя оригинала, в квадрате.

Думайте о ней как о проверке орфографии, которая считает неверные буквы. Дайте ей оригинал документа и копию – она скажет, сколько символов отличается. Чего она не скажет – читается ли предложение по-прежнему хорошо: опечатка в заголовке и опечатка в сноске считаются одинаково. У PSNR та же слепая зона. Она считает, сколько значений пикселей изменилось и насколько, никогда не спрашивая, попали ли эти изменения туда, куда смотрит глаз.

Чтобы измерить эту пиксельную ошибку, нужен чистый оригинал, кадр в кадр. Это делает PSNR full-reference-метрикой – метрикой, которая сравнивает искажённое видео с полным несжатым мастером. Если оригинала нет на диске, PSNR вообще нельзя вычислить; на прямой трансляции или пользовательском клипе мастера нет, и числа просто не существует. (Три схемы опоры – full, reduced и no-reference – разобраны в статье full-reference, reduced-reference, no-reference метрики; PSNR прочно сидит в первой.)

От пиксельной ошибки к децибелам: математика, показанная один раз

PSNR вычисляется в два шага. Сначала вы измеряете сырую ошибку через Mean Squared Error, почти всегда записываемое как MSE. Затем превращаете эту ошибку в децибелы. Оба шага коротки, и увидеть их один раз – значит снять всю мистику.

Mean Squared Error – это ровно то, что говорит название, читаемое справа налево: возьмите ошибку в каждом пикселе (значение оригинала минус значение сжатого), возведите её в квадрат, затем возьмите среднее всех этих квадратов по всему кадру. Возведение в квадрат делает две вещи: делает каждую ошибку положительной, чтобы они не сокращались, и наказывает большие ошибки гораздо сильнее малых. Для изображения шириной m и высотой n:

MSE = (1 / (m·n)) · Σ Σ [ I(i,j) − K(i,j) ]²

Здесь I – оригинальный кадр, K – сжатый кадр, а двойная сумма проходит по каждому пикселю. MSE, равное нулю, означает, что кадры идентичны. Большее MSE означает больше ошибки.

MSE само по себе неудобно читать – его масштаб зависит от битовой глубины, а числа неинтуитивны. Поэтому PSNR перемасштабирует его относительно самого яркого возможного пикселя и берёт логарифм, который сжимает огромный диапазон ошибки в дружелюбное двузначное децибельное число:

PSNR = 10 · log₁₀ ( MAX² / MSE )   [дБ]

MAX – наибольшее значение, которое может принять пиксель. Для обычного 8-битного видео это 255; для B бит на отсчёт это 2^B − 1 (1023 для 10 бит, 4095 для 12 бит). Поскольку формула делит MAX² на MSE, меньшая ошибка даёт большее PSNR – шкала идёт интуитивно, больше значит лучше.

Разобранный пример

Допустим, вы измеряете 8-битный клип и получаете MSE = 25. Это значит, что средний пиксель промахивается на 5 уровней (потому что 5² = 25) по шкале 0–255 – небольшая ошибка. Подставим:

PSNR = 10 · log₁₀ ( 255² / 25 )
     = 10 · log₁₀ ( 65025 / 25 )
     = 10 · log₁₀ ( 2601 )
     = 10 · 3.415
     = 34.15 дБ

Итак, средняя ошибка в 5 уровней приземляется примерно на 34 дБ. Теперь увеличим ошибку: MSE = 100 (средняя ошибка 10 уровней) даёт 10 · log₁₀(65025 / 100) = 28.1 дБ. А уменьшим до наименьшей возможной ненулевой ошибки, MSE = 1, и получим 10 · log₁₀(65025) = 48.13 дБ – это наибольшее конечное PSNR, которого может достичь 8-битный сигнал на грани идеального совпадения. У идеального совпадения MSE = 0, деление взрывается, и PSNR бесконечно.

Рисунок 1. PSNR за четыре шага: разность, квадрат, среднее (MSE), затем перевод в децибелы. Метрика никогда не смотрит, где ошибки, – только насколько они велики в среднем.

Одно правило, которое стоит запомнить

Поскольку PSNR логарифмично, есть чистый приём: каждое уменьшение ошибки вдвое добавляет примерно 3 дБ (так как 10 · log₁₀ 2 ≈ 3.01), а каждое удвоение отнимает примерно 3 дБ. Так что если кодировщик A набирает 36 дБ, а кодировщик B – 39 дБ на том же клипе, у B примерно вдвое меньше пиксельной ошибки, чем у A. Эта интуиция «3 дБ на удвоение» – самое полезное, что стоит вынести из математики.

Чтение значения PSNR: децибельная шкала

Значение PSNR ничего не значит, пока вы не знаете, какой диапазон ожидать. Для 8-битного видео и изображений с потерями реальное PSNR почти всегда оказывается между 30 и 50 дБ, а полосы внутри этого диапазона имеют грубые, проверенные временем значения.

Ниже примерно 30 дБ ошибки обычно видимы – картинка выглядит деградировавшей для внимательного зрителя. От 30 до примерно 40 дБ вы в нормальном рабочем диапазоне сжатия стримингового уровня, где качество от приемлемого до хорошего и большинство зрителей довольны. Выше 40 дБ сжатый кадр близок к оригиналу, а приближаясь к потолку 48 дБ, разница почти незаметна для 8-битного контента. Бóльшая битовая глубина сдвигает всю шкалу вверх: качественную 12-битную картинку оценивают на 60 дБ и выше, а 16-битные данные идут примерно от 60 до 80 дБ, потому что больше бит означает большее MAX и более высокий потолок.

Рисунок 2. 8-битная шкала PSNR с размещёнными на ней разобранными примерами. Полосы – правила большого пальца, а не гарантии: контент и кодек их двигают.

Оговорка к этой шкале – важнейшее предложение в статье. Значение PSNR окончательно валидно только при сравнении результатов одного и того же кодека на одном и том же контенте (Huynh-Thu и Ghanbari, Electronics Letters, 2008). Оценка 38 дБ на клипе с анимацией и оценка 38 дБ на клипе с киноплёночным зерном не означают, что они выглядят одинаково хорошо, – относительно друг друга они не значат ничего. Используйте PSNR, чтобы сравнить два кодирования одного источника, и сравнение надёжно. Используйте его для ранжирования качества разных источников, разрешений или кодеков – и вы гадаете на кофейной гуще.

Luma, chroma и «среднее», которое вы на самом деле приводите

Между формулой и числом в вашем логе есть ещё одна тонкость. Видео – не один канал; оно разбито на яркость (luma, компонента Y) и цвет (chroma, компоненты U и V). PSNR вычисляется отдельно для каждой, так что инструмент сообщает psnr_y, psnr_u, psnr_v и объединённое psnr_avg.

Глаз гораздо чувствительнее к яркости, чем к цвету, – поэтому кодировщики тратят большую часть битов на luma. По той же причине PSNR по яркости (psnr_y) – то число, которое приводят большинство инженеров: оно отслеживает ту часть картинки, которую зрители замечают. Объединённое среднее взвешено по числу пикселей в каждой плоскости, и поскольку chroma обычно субдискретизирована, luma в нём всё равно доминирует. Когда вы читаете или приводите значение PSNR, говорите, какое именно: «PSNR 38 дБ» без названной компоненты – небольшая, но реальная неоднозначность.

Как вычислить PSNR с помощью FFmpeg

Сами формулу вы будете писать редко. Повседневный инструмент – FFmpeg, чей фильтр psnr принимает два видеовхода (сначала искажённый клип, затем опорный) и печатает покомпонентное и среднее PSNR.

# PSNR между искажённым кодированием и его опорным мастером.
# Вывод печатает psnr_y, psnr_u, psnr_v и psnr_avg в консоль.
ffmpeg -i distorted.mp4 -i reference.mp4 \
  -lavfi psnr -f null -

Чтобы сохранить значение на каждый кадр – полезно для поиска худших моментов, а не только среднего, – пишите файл статистики:

# Покадровое PSNR в psnr.log (n, mse_avg, psnr_avg, значения по плоскостям).
ffmpeg -i distorted.mp4 -i reference.mp4 \
  -lavfi "psnr=stats_file=psnr.log" -f null -

Форма команды кодирует full-reference-контракт: без обоих файлов она не запустится. Если вам нужны PSNR, SSIM и VMAF за один проход, фильтр libvmaf может выдать все три – этот процесс с выбором модели и разбором вывода подробно разобран в статье измерение качества с FFmpeg и libvmaf, а быстрый справочник со стороны кодировщика живёт в шпаргалке по FFmpeg раздела Video Encoding.

Чтобы математика стала осязаемой прямо на рабочем столе, мы собрали небольшой скрипт с минимумом зависимостей, который вычисляет PSNR между двумя файлами изображений или кадров с нуля – MSE, затем децибелы – и печатает каждое промежуточное значение, чтобы вы видели, откуда именно берётся число. Скачайте PSNR-калькулятор «с нуля» (Python) и запустите его на своих кадрах.

Ловушка выравнивания

PSNR предполагает, что два видео точно совпадают: тот же кадр, в том же разрешении, с той же яркостью. Сравните кадр 100 кодирования с кадром 98 мастера – сдвиг на два кадра – и PSNR сообщит об обвале качества, которого глаз никогда не увидел бы. Сдвиг на один пиксель или небольшое смещение яркости делают то же. Из-за этой чувствительности МСЭ стандартизировал отдельное PSNR с компенсацией выравнивания – ITU-T J.340 (2010), которое корректирует постоянный пространственный сдвиг, временной сдвиг и яркостное усиление до оценки. Практическое правило: если оценка PSNR выглядит шокирующе плохой, подозревайте рассинхрон раньше, чем кодировщик. Сначала откалибруйте, потом оценивайте.

Почему PSNR плохо предсказывает воспринимаемое качество

Вот суть дела и причина, по которой существует каждая метрика после PSNR. PSNR измеряет пиксельную ошибку с идеальной арифметикой и почти без понимания зрения. У неё три слепые зоны, важные каждый день.

Во-первых, она считает каждый пиксель одинаково важным. Ошибка в резком крае лица и такая же ошибка в участке плоского неба вносят в MSE одинаковый вклад, хотя глаз прощает небо и мгновенно замечает лицо. Метрика понятия не имеет, куда вы смотрите.

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

В-третьих, она не может различить два очень разных искажения, если у них одинаковая суммарная ошибка. Слабая ровная дымка шума по всему кадру и кусок уродливой блочности в одном углу могут дать одинаковое MSE – а значит, одинаковое PSNR, – выглядя при этом совершенно по-разному для зрителя.

Рисунок 3. Одинаковое PSNR, разное качество. PSNR суммирует пиксельную ошибку и не видит, что одно искажение попадает туда, куда смотрит глаз, а другое – нет.

Это не маргинальная претензия. Определяющее академическое исследование по вопросу – статья Huynh-Thu и Ghanbari «Scope of validity of PSNR in image/video quality assessment» (2008) – показало, что согласие PSNR с мнением людей держится лишь внутри одного контента и кодека и ломается между ними. На больших смешанных тестовых наборах корреляция PSNR с человеческими Mean Opinion Scores обычно заметно отстаёт от перцептивных метрик – иллюстративные цифры из современных стриминговых баз ставят корреляцию PSNR существенно ниже, чем у SSIM и VMAF, хотя точный разрыв зависит от базы, так что относитесь к ним как к порядку, а не к оценкам. Честная формулировка такова: каждая объективная метрика, включая PSNR, – это прокси человеческого мнения, который оценивают по субъективным тестам, и PSNR – среди слабейших прокси, что у нас есть.

Где PSNR всё ещё правильный инструмент

Если PSNR плохо предсказывает восприятие, почему оно везде – и почему мы всё ещё его используем? Потому что для нескольких конкретных задач его слабости не кусаются, а сильные стороны решают.

Оно быстрое и бесплатное. PSNR – это горстка арифметических операций на пиксель, без модели для загрузки, без обучающих данных, без лицензии. Оно работает в реальном времени на чём угодно – поэтому каждый видеокодировщик использует MSE или PSNR внутри своей rate-distortion-оптимизации (RDO), внутреннего цикла, который тысячи раз за кадр решает, стоит ли потратить ещё один бит ради ошибки, которую он уберёт. Перцептивная метрика слишком медленна, чтобы вызывать её в этом цикле; PSNR для него идеально.

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

Оно универсальная база. Поскольку PSNR десятилетиями вычисляется одинаково, это единственное число, которое могут выдать любая статья, любой кодек и любой инструмент, – что делает его общей валютой для BD-rate и других rate-distortion-сравнений. И оно точно для проверки безпотерьности: бесконечное PSNR доказывает, что два файла побитово идентичны, – правильный инструмент, чтобы подтвердить, что транскодирование ничего не изменило.

Правило простое. Берите PSNR, когда сравниваете кодирования одного источника, когда нужна скорость или когда нужна узнаваемая всеми база. Берите перцептивную метрику, когда предсказываете, насколько хорошо видео будет выглядеть для зрителя.

Перцептивные родственники: PSNR-HVS, PSNR-HVS-M и XPSNR

Слабости PSNR были достаточно очевидны, чтобы исследователи построили перцептивно взвешенные версии, сохраняющие его скорость. PSNR-HVS взвешивает пиксельные ошибки моделью человеческой контрастной чувствительности, так что ошибки, которые глаз едва видит, считаются меньше. PSNR-HVS-M идёт дальше и добавляет визуальное маскирование – то, как насыщенные области прячут ошибки, – и в своей оценке 2007 года отслеживало человеческое суждение заметно лучше, чем PSNR и SSIM.

Новейший и самый практичный из них – XPSNR, Extended Perceptually Weighted PSNR от Fraunhofer HHI, добавленный в FFmpeg в 2024 году. Это низкосложное, психовизуально взвешенное PSNR, чьи значения лежат в том же децибельном диапазоне, что и у обычного PSNR, но ближе следуют за воспринимаемым качеством; для современного контента высокого разрешения сообщается, что оно коррелирует с субъективными оценками лучше, чем VMAF, на VVC-кодированном UHD-видео. Если вам нравится простота PSNR, но нужно число, более близкое к глазу, стоит знать про xpsnr в свежей сборке FFmpeg:

# Extended perceptually weighted PSNR (Fraunhofer HHI, FFmpeg 2024+).
ffmpeg -i distorted.mp4 -i reference.mp4 -lavfi xpsnr -f null -

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

PSNR против SSIM против VMAF: когда что брать

PSNR – одна из трёх метрик, которые вы будете встречать постоянно, и быстрейший способ удержать их в голове – поставить рядом. Важны не только оценки, но и что каждая метрика на самом деле измеряет и где каждая врёт.

МетрикаШкалаЧто измеряетГде врёт (слепая зона)Лучше всего для
PSNRдБ (≈20–50, ∞ если идентично)Средняя пиксельная ошибка vs оригиналИгнорирует, где ошибки; одинаковая оценка для очень разных искаженийСравнение на одном кодеке, RDO, ворота регрессии, проверки безпотерьности
SSIM0–1 (больше лучше)Структурное сходство – яркость, контраст, структураПропускает часть цветовых и временных ошибок; всё ещё пространственная модельПерцептивный прокси лучше PSNR, покадровая структура
VMAF0–100 (больше лучше)Слитое, обученное на восприятии качество (зависит от модели)Бессмысленно без названной модели; обманывается резкостьюПредсказание воспринимаемого стримингового качества в масштабе

Таблица 1. Три full-reference-метрики с одного взгляда. Всем нужен оригинал; они различаются тем, насколько близко подбираются к глазу и что пропускают. Выбирайте строку под задачу – и всегда называйте условия.

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

Частые ошибки с PSNR

«Ошибка: сравнивать PSNR между разным контентом, разрешениями или кодеками. Кодирование мультфильма на 40 дБ и кодирование зернистого фильма на 34 дБ не говорят, что мультфильм «выглядит лучше» – PSNR валидно только при сравнении кодирований одного источника. Кросс-контентные ранжирования по PSNR – самое частое злоупотребление метрикой.»
«Ошибка: приводить одно число PSNR без контекста. «PSNR 38» прячет, luma это или среднее, усреднено по среднему или по худшему случаю и на каком контенте. Одно среднее PSNR может прятать пару ужасных секунд внутри в остальном чистого клипа – поэтому важен пулинг. Приводите компоненту, пулинг и контент.»
«Ошибка: оптимизировать под PSNR, а не под зрителя. Настройка кодировщика на максимизацию PSNR может подтолкнуть его к выборам, которые хорошо набирают по пиксельной ошибке, но выглядят хуже, – например, к чрезмерному сглаживанию деталей. Метрика – это прокси; оптимизировать прокси за пределом, где он отслеживает восприятие, – так команды выпускают видео, которое набирает высоко и выглядит плоско.»

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

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

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

  • PSNR измеряет среднюю пиксельную ошибку и выражает её в децибелах – больше лучше, идентично – бесконечность.
  • Математика коротка: возвести в квадрат попиксельные ошибки, усреднить (MSE), затем 10·log₁₀(MAX²/MSE).
  • Для 8-битного видео с потерями ожидайте 30–50 дБ; ниже 30 дБ ошибки обычно видимы; 48.13 дБ – конечный 8-битный потолок.
  • PSNR валидно только при сравнении кодирований одного контента на одном кодеке.
  • Оно плохо предсказывает воспринимаемое качество, потому что игнорирует, где ошибки, и как глаз их маскирует.
  • Оно всё ещё правильный инструмент для RDO, сравнения одного источника, ворот регрессии и проверки безпотерьности.

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

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

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