Какие факторы вызывают или предотвращают «потерю поколений», когда JPEG повторно сжаты несколько раз?

29

В течение многих лет я считал, что повторное сжатие файлов JPEG несколько раз будет постепенно ухудшать его качество, пока они не станут неузнаваемым беспорядком, как это делают фотокопии фотокопий. Это интуитивно понятно, поскольку JPEG - это формат с потерями. Есть также другие вопросы и ответы, которые утверждают, что это так:

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

Что технически происходит при повторном сжатии JPEG?  Что теряется и как? Будет ли изображение действительно превращаться в снежный беспорядок, который раньше появлялся на телевидении? А как насчет тех видео, где изображения распадаются после многократного повторного сжатия?

(Пожалуйста, не просто махайте рукой и обращайтесь к общей концепции потерь.)

(Этот вопрос и ответы, которые он привлек к этому моменту, сосредоточены на технических факторах (специфических настройках и манипуляциях с изображением), которые вызывают или предотвращают ухудшение качества изображения при повторном сжатии файла JPEG несколько раз.)

xiota
источник
2
@MonkeyZeus Некоторое (небольшое) количество данных изображения теряется из-за ошибки округления с качеством 100. Повторное сжатие с той же настройкой (например, 80) не приводит к постепенной потере данных. Это «общеизвестно», что этот вопрос и ответы предназначены для решения.
xiota
1
@MonkeyZeus Значения, такие как «100» и «80» (или «10, 11, 12» в Photoshop) являются произвольными - 100% не без потерь.
mattdm

Ответы:

32

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

  • Границы MCU остаются нетронутыми (8x8 блоков).

  • Подвыборка цветности отключена.

  • Постоянный DQT (одинаковая настройка качества).

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


Алгоритм сжатия JPEG

  1. Конвертировать цветовое пространство. При желании уменьшите информацию о цвете (подвыбор цветности) (с потерями) . Если данные не понижены, потеря информации является результатом ошибки округления .

  2. Сегментация. Разделите каждый канал на блоки 8x8 (MCU = минимальная единица кодирования). (Lossless)

    Примечание. Если включена субдискретизация по цветности, MCU может эффективно составлять 16x8, 8x16 или 16x16 с точки зрения исходного изображения. Тем не менее, MCU все еще являются блоками 8x8.

  3. Дискретное косинусное преобразование (DCT) на каждом MCU. Потеря информации является результатом ошибки округления .

  4. Квантование.  Значение в каждой ячейке блока MCU делится на число, указанное в таблице квантования (DQT). Значения округлены в меньшую сторону, многие из которых станут нулевыми. Это основная часть алгоритма с потерями.

  5. Зигзагообразный скан. Переставьте значения в каждом MCU в последовательность чисел, следуя зигзагообразному шаблону. Нули, которые произошли во время квантования, будут сгруппированы вместе. (Lossless)

  6. DPCM = дифференциальная импульсная кодовая модуляция. Преобразуйте числовые последовательности в форму, которую легче сжать. (Lossless)

  7. RLE = Длина кодирования. Последовательные нули сжимаются. (Lossless)

  8. Энтропия / кодирование Хаффмана. (Lossless)

Повторное сжатие JPEG

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

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

При оптимальных условиях повторное сжатие JPEG с теми же настройками качества приведет к точно такому же JPEG. Другими словами, повторное сжатие JPEG потенциально без потерь . На практике повторное сжатие JPEG не является без потерь, но подвержено и ограничено ошибкой округления. Хотя ошибки округления часто в конечном итоге сходятся к нулю , поэтому воссоздается точно такое же изображение, дополнительная выборка цветности может привести к значительным изменениям цвета.

Демонстрация (установка того же качества)

Я написал следующий bashскрипт, который использует ImageMagick для многократного повторного сжатия файла JPEG с заданной настройкой качества:

#!/usr/bin/env bash
n=10001; q1=90
convert original.png -sampling-factor 4:4:4 -quality ${q1} ${n}.jpg

while true ; do
   q2=${q1}            # for variants, such as adding randomness
   convert ${n}.jpg -quality ${q2} $((n+1)).jpg
   #\rm $((n-5)).jpg   # uncomment to avoid running out of space
   n=$((n+1))

   echo -n "$q2  "
   md5sum ${n}.jpg
done

После нескольких сотен итераций я запустил md5sumрезультаты:

d9c0d55ee5c8b5408f7e50f8ebc1010e  original.jpg

880db8f146db87d293def674c6845007  10316.jpg
880db8f146db87d293def674c6845007  10317.jpg
880db8f146db87d293def674c6845007  10318.jpg
880db8f146db87d293def674c6845007  10319.jpg
880db8f146db87d293def674c6845007  10320.jpg

Мы видим, что действительно ошибка округления сведена к нулю, и одно и то же изображение воспроизводится снова и снова .

Я повторил это несколько раз с различными изображениями и настройками качества. Обычно, устойчивое состояние достигается, а точное же изображение воспроизводится снова и снова.

А как насчет результатов @ mattdm ?

Я попытался воспроизвести результаты mattdm, используя Imagemagick в Ubuntu 18.04. Первоначально это был необработанный перевод в TIFF в Rawtherapee, но, похоже, он больше не доступен. Вместо него я взял увеличенную версию и уменьшил ее до исходного размера (256х256). Затем я неоднократно сжимался до 75, пока не получил схождение. Вот результат (оригинал, 1, n, разница):

попытка повторить матдм

Мои результаты разные. Без подлинного оригинала причину разницы определить невозможно.

Что насчет монтажа @ ths ?

Я повторно сжал изображение от верхнего левого угла монтажа до схождения в 90. Это результат (оригинал, 1, n, разница):

попытка воспроизвести этот монтаж

После включения подвыборки цветности цвета меняются к моменту достижения устойчивого состояния.

тыс цветов сдвига

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

Изменяя переменную q2, настройка качества может быть ограничена набором равномерно распределенных значений.

q2=$(( (RANDOM % 3)*5  + 70 ))

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

Кажется, что в равновесии происходит то, что коэффициент DCT перед квантованием должен делиться на все (или большинство) квантовых значений. Например, если переключаться между двумя DQT, где коэффициент DCT делится попеременно на 3 и 5, равновесие будет достигаться, когда коэффициент DCT делится на 15. Это объясняет, почему падение качества намного больше, чем разница между исходными настройками.

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

ИА недоволен, когда q2меняется так:

q2=$(( (RANDOM % 9)  + 90 ))

Чтобы сделать видео, используйте ffmpeg:

rename 's@1@@' 1*.jpg
ffmpeg -r 30 -i %04d.jpg -c:v libx264 -crf 1 -vf fps=25 -pix_fmt yuv420p output.mp4

Наблюдение за первыми 9999 итерациями почти похоже на наблюдение за водой. Может хотеть удвоить скорость воспроизведения. Вот ИА после 11999 итераций:

11999 итераций, случайный DQT

Что если границы MCU изменятся?

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

Как насчет редактирования?

Эффект повторного сжатия после редактирования зависит от конкретного выполненного редактирования. Например, сохранение с той же настройкой качества после уменьшения артефактов JPEG приведет к повторному появлению тех же артефактов. Однако применение локализованного изменения, такого как целительная кисть, не затронет области, которые не были затронуты.

Наибольшее падение качества изображения происходит при первом сжатии файла с заданной настройкой качества. Впоследствии повторное сжатие с той же настройкой не должно приводить к каким-либо изменениям, превышающим ошибку округления. Таким образом, я ожидаю, что циклы редактирования-сохранения при заданном параметре качества будут выглядеть как любое другое изображение, сохраненное с тем же параметром качества (пока границы MCU остаются нетронутыми и субсэмплирование цветности отключено ).

А как насчет этих видео?

  • Неправильная реализация JPEG? ( Повторное сохранение 500 раз с Photoshop в 10/12. )

  • Изменение настроек качества. (Большинство видео.)

  • Нарушение границ MCU. (Обрезка или вращение )

  • Другие маневры, которые снижают качество изображения или мешают алгоритму JPEG?

Могу ли я перезаписать свои оригиналы повторно сжатыми JPEG-файлами?

Целесообразно хранить резервные копии всех исходных файлов, но если вы случайно перезаписаете один из них, ущерб, скорее всего, будет ограниченным. Также было бы хорошо работать в JPEG с отключенной подвыборкой цветности.

JPEG нельзя использовать для изображений, которые используют более 8 бит на цвет.

xiota
источник
5
однако, картина сильно отличается от циклов load- edit -save. в этом случае повторное квантование приведет к ухудшению.
тыс
2
Я только что сделал тест с тем же сценарием, что и в ответе. Вот монтаж каждого 20-го изображения до 100: i.stack.imgur.com/xtob6.jpg, что важно.
тыс
2
ах. нашел проблему с моим изображением. если у вас включена подвыборка цветности, это приводит к прогрессирующему ухудшению.
тыс
2
Нашел это тоже. Таким образом, включение цветовой субсэмплирования существенно меняет цвет в изображении до достижения устойчивого состояния.
Xiota
2
Повторные загрузки и сохранения с использованием одних и тех же параметров, скорее всего, не приведут к неограниченной потере качества, поскольку большинство входных файлов могут быть загружены и повторно сохранены без внесения дополнительной ошибки округления, а файлы, на которые могут повлиять ошибки округления, вероятно, будут преобразованы в файлы, которые не будут. С другой стороны, повторяющиеся циклы загрузки / сохранения, которые чередуются между параметрами сжатия, которые похожи, но не идентичны, могут привести к ошибкам округления в каждом цикле.
суперкат
20

Потеря при сжатии реальна, особенно при работе с более высокими уровнями сжатия JPEG.

Теоретически, если вы повторно сохраняете файлы JPEG с точно такими же параметрами и выравниваете кадрирование по 8 × 8 блокам, ухудшение должно быть минимальным. Однако, если вы используете высокий уровень сжатия, вы увидите дальнейшую потерю, потому что артефакты, возникающие при первоначальном сжатии, являются постоянными изменениями в изображении и тоже будут повторно сжаты, вызывая больше артефактов.

Если вы повторно сохраните файл с низким уровнем сжатия (высокое качество, например, «100» в Gimp или 11 или 12 в Photoshop), любые новые добавленные артефакты будет трудно заметить. Это не сделает изображение лучше , но не намного хуже. Тем не менее, это внесет изменения по всему изображению.

В качестве быстрого теста я использовал ImageMagick для повторного сжатия изображения JPEG снова и снова на 75%. Приведенные ниже примеры загружаются в виде файлов PNG, чтобы избежать дальнейшего повторного сжатия, и их размер удвоился при преобразовании в формат PNG, чтобы сделать эффект более очевидным. (Оригиналы, использованные в тесте, не были удвоены.) Оказывается, что после восьми повторных выборок эффект сходился к совершенно стабильному результату, где повторное сжатие приводит к получению бит-в-бит идентичного файла.

Вот несжатый оригинал:

оригинал, без сжатия JPEG

Вот результат перехода на 75% JPEG:

первый JPEG

И вот что решено:

второй проход

Эта единичная секунда сохранения приводит к значительному ухудшению!

И вот окончательное конвергентное изображение (8 проход):

сходились JPEG

Опять же, цвета определенно еще более нестабильны, в том числе некоторые образцы ложных цветов, и блочные артефакты выпадают больше. Алгоритм сходится, но в значительно ухудшенной версии. Так что не делай этого.

Но вот то же самое с уровнем качества 99% после 9 проходов (точка, где он сходится, так что дальнейшие проходы идентичны):

99% 9 раз

Здесь разница едва регистрируется. (Я имею в виду буквально; сравнивайте их пиксель за пикселем с несжатой версией, и отклонение - это просто очень незначительный случайный шум.) Итак, что если я вернусь к этому первому 75% изображению, а затем сохраню его на 99%? Ну, это, (только после одного раза):

75% один раз, а затем 99% один раз

К моему удивлению, сохранение в высоком качестве определенно заметно лучше, чем сохранение с теми же параметрами. Но есть очевидная новая деградация вокруг розовой отделки и глаз. В переработанной версии с теми же настройками артефакты JPEG преувеличиваются с каждым повторным сжатием. С низким разрешением и низким качеством, которое я выбрал, это оказывается хуже, чем повторное сжатие по-другому.

На тех видео: я нашел это как главный хит Google. Обратите внимание, что в описании сказано:

Это то, что происходит, если вы повторно кодируете изображение JPEG много раз со случайными настройками высокого качества (85 или выше).

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

Второе видео , которое я нашел , говорит:

Изображение JPEG было скопировано и повернуто на полный оборот для каждого изображения. [...] (596 действий "повернуть по часовой стрелке")

Итак, опять же, что-то было сделано, чтобы ошибки накапливались.

В любом случае, для практического редактирования фотографий стоит отметить, что экономия 75% за один раз намного хуже, чем экономия при 99% в миллион раз . В моем примере, артефакты на 75% настолько очевидны, что дальнейшая деградация подобна сбросу воды в океан. Если вы сохраняете на достаточно высоком уровне, чтобы эти артефакты не были видны, то сохранение снова с исходными настройками является хорошей стратегией. Конечно, если вы можете всегда работать с несжатыми оригиналами, вам лучше.

Если по какой-то причине вам нужно (или вы предпочитаете) просто работать с JPEG, настройте камеру на сохранение с максимально возможным качеством , даже если вы не заметите разницу в исходных файлах. См. Стоит ли использовать настройку качества Pentax Premium JPEG? более подробно об этом - не обязательно на самом деле специфично для Pentax.

mattdm
источник
(1) Вы экономите на 75%. При такой настройке ожидается потеря качества изображения. (2) Это изображение было выбрано и изменено для усиления артефактов сжатия JPEG. (3) Изображение сходится после 8 циклов повторного сжатия, после чего качество изображения не ухудшается. (4) Видео с этим изображением, показывающим «потерю поколения», ничего не произойдет после первой 1/4 секунды.
Xiota
5
(1) Да. (2) «Выбрано» как типичная фотография, где можно заботиться о подобных вещах. «Изменено» только для увеличения. Обратите внимание, что это только для отображения здесь - я не удвоил размер изображения, с которым я работал. (3) Да, но на практике для редактирования, это первые несколько раундов, которые могут вас волновать. (4) Это правда, но это не значит, что сходиться в худшем случае и оставаться там полезно в любом случае.
mattdm
Для репликации возьмите первое изображение и измените размер до 256 × 256 без какой-либо передискретизации или интерполяции.
mattdm
Я не вижу большой разницы между изображениями, которые вы показываете. Но если я возьму разницу в изображениях с однократной повторной и многократной повторной компрессией и увеличу их, чтобы сделать их видимыми, я получу такой (гораздо более убедительный) результат: i.stack.imgur.com/57uaY.png (см. Мой удаленный файл) Ответьте на вопрос, что именно было сделано) Это более убедительно, потому что людям не нужно постоянно смотреть на изображение, чтобы обнаружить мелкие различия.
Сабольч
Различия довольно маленькие. Если у вас большой ЖК-экран, другая «гамма», возникающая из-за немного разных углов обзора, может сделать артефакты более заметными.
xiota
5

Повторное сжатие оказывает ощутимое влияние на качество изображения, и этот эффект гораздо более выражен при изменении степени сжатия.

В качестве быстрой проверки здесь приведены некоторые значения SSIM для операций, выполняемых с тестовым изображением, содержащим комбинацию линейных и непрерывных объектов. Я выбрал JPG95, потому что это то, чему меня учили использовать в школе Ad-photo, и JPG83, потому что это распространено среди поставщиков цифрового контента.

  • Сохранить изображение Tiff как JPG95 - .9989
  • Сохранить изображение Tiff как JPG83 - .9929
  • Восстановить изображение JPG95 как JPG95 10 раз - .9998
  • Восстановить изображение JPG83 как JPG83 10 раз - .9993
  • Восстановите JPG95 как JPG83, затем восстановите как JPG95 - .9929
  • Восстановите JPG95 как JPG83, затем JP83 до JP92, затем JPG92 до JPG86 - .9914

Таким образом, величина структурного сходства, потерянного при повторном сохранении при одном и том же сжатии в 10 раз, составляет 1/10 от потерянного при сохранении его с качеством от tiff. Однако потеря качества из-за изменения сжатия JPG даже один раз такая же, как и потеря качества при сохранении этого изображения из Tiff в JPG.

Я проведу этот тест еще несколькими способами и обновлю.

Методология : в ImageJ:

  1. Конвертировать Tiff RGB в оттенки серого 8 бит
  2. Сохранить JPG95 и JPG83 из Tiff Original
  3. Выполните дальнейшие операции восстановления, как указано
  4. Загрузите сравнительные изображения и используйте плагин SSIM Index

ПРИМЕЧАНИЕ. Многие люди, впервые смотрящие на значения SSIM, читают их в процентах и ​​считают, что разница невелика. Это не обязательно правда. Значения SSIM следует сравнивать относительно друг друга, а не рассматривать как отклонение от 1.

PhotoScientist
источник
@xiota, я использую плагин SSIM для ImageJ. Это одна из немногих реализаций SSIM, которая позволяет настраивать параметры (я установил ширину фильтра равной 8, чтобы с большей вероятностью обнаруживать изменения в 16-пиксельных блоках JPEG.) Я предпочитаю SSIM, потому что он более чувствителен к различиям в энергии перераспределение. Различное изображение может вводить в заблуждение, если различия устраняются или различия сосредоточены в небольшой области.
PhotoScientist
И на ваш второй вопрос, это говорит о том, что разница от JPG95 к JPG83 до JPG95 такая же, как от Tiff до JPG83. Если вы хотите Tiff-JPG95-JPG83-JPG95, то есть .9923
PhotoScientist
Добавлена ​​попытка с четырьмя различными компрессиями. Потери еще больше, но ясно, что "сходимость", наблюдаемая в нескольких поколениях одного и того же сжатия, также присутствует при попытке нескольких различных сжатий. Тем не менее, я хотел бы попробовать это в рабочем процессе, ориентированном на приложения, но это требует немного больше усилий.
PhotoScientist
Другая проблема заключается в том, что не существует стандартного сопоставления настроек «качества» с пороговыми значениями SSIM, и нет никакого способа определить, какие настройки качества будут необходимы, чтобы избежать значительной потери информации. Если загрузить файл JPEG и сохранить его на достаточно высоком уровне, можно избежать дополнительной потери качества, но файл, вероятно, увеличится. Если неизвестно, какой параметр использовался при создании файла, может быть трудно определить, какой параметр использовать при повторном сохранении.
суперкат
4

Ничего подобного экспериментам. Следующий скрипт bash (написанный на Linux, может работать на OSX, если у вас есть ImageMagick ):

  • начиная с первого изображения (по имени step000.jpg)
  • берет файл JPEG, добавляет белую точку (чтобы доказать, что это новое изображение) и сохраняет его как (PNG без потерь)
  • принимает PNG и повторно сжимает его как JPEG (поэтому мы никогда не сжимаем JPEG в JPEG и не можем предположить, что программа просто копирует кодированные блоки)
  • делает изображение, которое показывает разные пиксели между двумя JPEG
  • промойте и повторите, используя вывод JPG предыдущего шага

Результат таков:

  1. нет больших потерь при высоких качествах JPG
  2. ошибки округления в конечном итоге решаются, после небольшого количества поколений вещи больше не ухудшаются.

Конечно, все это предполагает, что JPEG сохраняется одним и тем же программным обеспечением с одинаковыми параметрами каждый раз.

#! /bin/bash
# Runs successive JPEG saves on an image to evaluate JPEG losses

# convert & compare command from imagemagick
# if you use a recent version of IM, set these variables to:
# compare="magick compare"
# convert="magick convert"
convert=convert
compare=compare

dotradius=2
defaultsteps=10
defaultquality=90 # default quality for "convert"

function usage {
        echo "Usage: $0 [quality [steps]]"
        echo ""
        echo "Where:"
        echo "       - 'quality' is the quality factor of the JPEG compression "
        echo "          (1-100, 100 is best, default is $defaultquality)"
        echo "       - 'steps' is the number of successive steps to perform"
        echo "         (default is $defaultsteps)"
        echo ""
        echo "Produces:"
        echo "   - successive saves of a JPEG image to test JPEG-induced losses."
        echo "   - compare images with the original file and the 1st JPEG save."
        echo ""
        echo "Starts from a 'step000.jpg' file in the current directory."
        exit 1
}

[[ -n "$3" ]] && { usage ; exit 1 ; }
steps=${1:-$defaultsteps}
quality=${2:-$defaultquality}    
dotcolor="white" # change this if the top of the image is too clear

echo "Running with $steps steps with quality $quality"

for step in $(seq $steps)
do 
    echo "Step $step of $steps"
    src=$(printf step%03d $(( $step - 1 )) ) 
    dst=$(printf step%03d $(( $step )) )
    dif=$(printf diff%03d $(( $step )) )
    # dot coordinates
    let cxc="2 * $dotradius * $step"
    let cxr="$cxc + $dotradius"
    let cyc="$dotradius * 2"
    let cyr="$dotsradius * 2"

    $convert $src.jpg -fill white -draw "circle $cxc,$cyc,$cxr,$cyr" $dst.png
    $convert $dst.png -quality $quality $dst.jpg
    rm $dst.png
    $compare $src.jpg $dst.jpg $dif.jpg
done

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

xenoid
источник
1
Мне было любопытно по поводу другого программного обеспечения. Я пытался сохранить 7x из 7 различных программ. Разница была довольно большой, поэтому я разбил ее, чтобы проверить, не были ли потери в каждом приложении. Одно из приложений отвечало за все варианты. После того, как я удалил красную сельдь, 6-кратное сохранение из 6-кратных программ было таким же, как 6-кратное сохранение из ImageJ
PhotoScientist
Вероятно, есть какое-то плохо закодированное программное обеспечение. Также возможно, что смешивание алгоритмов из различных приложений также предотвратит ошибки округления.
ксеноид
@xiota, это была странная маленькая программа под названием FLEMinimizer. Я даже не помню, почему у меня это было вообще. Другими были ImageJ, Matlab, Photoshop, программа просмотра изображений FastStone, Ifranview и CameraRaw. Между этими шестью почти не было различий.
PhotoScientist