ilyakurdyukov / jpeg-quantsmooth

JPEG artifacts removal based on quantization coefficients.
GNU Lesser General Public License v2.1
252 stars 21 forks source link

Experiment ? #20

Open zvezdochiot opened 3 years ago

zvezdochiot commented 3 years ago

Hi @ilyakurdyukov .

The other day I came across jpeg with CMYK color space. jpegqs (at least from https://github.com/ImageProcessing-ElectronicPublications/libjpegqs) did a great job with it. But it turned out that only http://netpbm.sourceforge.net/ can work with such a file. Don't want to play with the coefficients for obtaining pseudo-lossless color space conversion?

ilyakurdyukov commented 3 years ago

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

zvezdochiot commented 3 years ago

Почему трудно? Натравливаешь grep на PDF по ключу /DeviceCMYK. Для извлечения либо popler-utils, либо mupdf, либо https://github.com/ImageProcessing-ElectronicPublications/python-pdf-jpeg-extract . Смысл вопроса: используя то, что цветовые схемы либо прямо пропорциональны, либо повёрнуты на 120 градусов, осуществлять пересчёт коэффициентов без декодирования (idct).

ilyakurdyukov commented 3 years ago

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

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

Это возможно только для RGB

Я знаю, что в YCbCr (основе) каналы сохраняются специфичным образом. Поэтому и указал pseudo-lossless. Никаким lossless-ом здесь естественно не пахнет. Но получить преобразование вполне себе можно. Я бы сам попробовал, если бы разобрался с 0-ым коэффициентом.

PS: И это не должно входить в jpegqs! Речь за отдельную тулзу.

ilyakurdyukov commented 3 years ago

Что у тебя с нулевым коэффициентом? Может я тебя не понял и ты предлагал на основе двух одинаковых изображений сохранённых в разных системах - восстановить оригинал?

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

сохранённых в разных системах - восстановить оригинал?

Да откуда ж такое взять? Нет конечно. Речь за топорный цветовой пересчёт коэффициентов без декодирования.

ilyakurdyukov commented 3 years ago

Без декодирования ты это не сделаешь. Единственный случай когда это возможно - это если всё изображение одного цвета, но разной яркости, и при этом не чёрно-белое. В чёрно-белом будет только K компонента использоваться.

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

Без декодирования ты это не сделаешь.

Мне пока этот момент непонятен. Но это не единственный такой момент. Ежели ты уверен, то закрывай. Хотя могу предложить ещё один эксперимент, но уже у меня он вызывает сомнения. А именно использовать фазовый сдвиг + межблоковую коррекцию для "сдвига" границ блоков без декодирования.

ilyakurdyukov commented 3 years ago

Что ты называешь фазовым сдвигом и сдвигом границ, и что это должно давать в результате?

zvezdochiot commented 3 years ago

фазовый сдвиг - это легкота, косинус сумы, точнее говоря суммы частот ij-ого косинуса и фазы необходимого сдвига. Но есть ньюанс, косинус то периодичен. "Сдвиг" влево приведёт к переносу 0-го столбца вправо. А надобно то позаимствовать из соседнего блока. Отсюда возникает настоящая алхимия с межблочной коррекцией. Для чего? Проблема круппинга.

ilyakurdyukov commented 3 years ago

Утилита jpegtran умеет кропать, но по границе блоков. А сдвинуть блоки не получится, потому что в DCT не чистый косинус, а еще окно сверху наложено.

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

окно сверху наложено.

Ты имеешь в виду сам блок 8x8? Ну так внутри блока ничто не мешает провернуть. А цикличность уже придётся решать межблочной корректировкой (чуть ли не методом тыка).

Как это решать? Начиная с простых схем: чёрный либо белый квадрат 8x8 точно в блоке на сером фоне пробовать "сдвинуть" влево-вправо, а потом вернуть назад.

ilyakurdyukov commented 3 years ago

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

zvezdochiot commented 3 years ago

Совершенно верно. Именно поэтому и предлагается такой "чистый" опыт. Он даёт подробную "картинку".

zvezdochiot commented 3 years ago

Расширю немного тему "экспериментов". Есть такая штука: https://github.com/ImageProcessing-ElectronicPublications/jpeg-recompress . Она производит перекодирование всего изображения пока не достигнет нужного показателя метрики. А не стоит ли производить манипуляции с самими коэффициентами без полного перекодирования? (правда здесь чисто коэффициентами не отделаешься - декодер нужен для метрик, хотя бы стандартный).

ilyakurdyukov commented 3 years ago

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

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

далее накладывать квантизацию

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

Меня интересует не какое то конкретное преобразование коэффициентов (но не произвольное, смысл какой то всё равно должен быть), а проведение обратного действия и определение "необратимой" составляющей. Исследование этой самой "необратимой" составляющей и внесение корректировок для её подавления и есть тот самый pseudo-lossless.

ilyakurdyukov commented 3 years ago

Показать где mozjpeg найти или сам найдёшь? Там это и пытаются решить.

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

где mozjpeg

Где mozjpeg, а где то, о чём я говорю. @kornelski итак уже во всю отбивается от "новоделов". Не надо смешивать "тёплое" с "мягким", субстанция получается не очень приятная. К тому же решает он задачу по совершенно другому вектору. Если тебе показалось, что по тому же, то это кажимость.

ilyakurdyukov commented 3 years ago

"обратимость" существует для конкретного алгоритма, а не сама по себе. Стандартное JPEG декодирование тоже можно считать алгоритмом который восстанавливает коэффициенты в изображение, в mozjpeg делают чтобы лучше выглядело со стандартным декодером. Если хочется лучший формат, то лучше обратить внимание на webp, jpegxl, heif или avif.

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

webp, jpegxl, heif или avif.

bpg и pgf забыл. Нет, не интересует. Не тот "вектор". Ежели нужно конкретизировать мой "вектор", то основное его проявление в реализациях - это RIS в методах масштабирования изображений.

PS: Наглядное разъяснение по RIS:

ilyakurdyukov commented 3 years ago

По примеру к твоему gimp-plugin-resize-ris вообще сложно заметить какие-то различия с обычным cubic. Для cubuc формул бывают разные полиномы, вот на уровне этой разницы.

У меня есть свой тест с фрактальным апскейлом, который даёт следующий результат: https://drive.google.com/file/d/1YwZO1EAMw8ZrMIP17lgaJoxSugX6uKkw/view

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

сложно заметить какие-то различия

Различия - это "побочный эффект". Смысл не в различиях, а в том, для чего производится RIS. Говоря конкретнее, для того, чтобы можно было "вернуть всё назад". Основное применение - увеличить масштаб, наложить некий фильтр, вернуться к исходному масштабу. Дополнительное применение - upscale.

ilyakurdyukov commented 3 years ago

Вообще-то пример что я показал тоже можно вернуть назад, просто усреднив блоки 4x4.

zvezdochiot commented 3 years ago

@ilyakurdyukov say:

тоже можно вернуть назад, просто усреднив блоки 4x4.

Значит твой метод тоже можно отнести к "незеркальному" RIS (большинство), потому что строгого "правила" к масштабированию в RIS нету.