Предлагаю вашему вниманию перевод статьи Neural Network As Predictor For Image Coding (PNG). Блог автора находится здесь.
Главной причиной данной работы было улучшение существующих предварительных фильтров. Создать новый фильтр, который с помощью искусственной нейронной сети делал бы наилучший прогноз, приводящий к лучшему сжатию файла.
Классически PNG-компрессия делится на два шага:
В данной статье важен только первый шаг. На рисунке ниже вы можете видеть существующие на данный момент предварительные фильтры, и как они сохраняют разницу между реальным и предсказанным пикселем.
![Работа предиктора](https://habrastorage.org/r/w1560/getpro/habr/post_images/239/e1b/ede/239e1bede7199b66555641537983d782.png)
Существующие на данный момент фильтры + новое решение:
Последний фильтр – новая реализация автора данной статьи. Он внутренне использует нейронную сеть с массивом входных пикселей. В результате возвращает переменную предсказанного пикселя. Как и в других фильтрах сохраняется разность между оригинальным и предсказанным значением. Но что это за входные значения спросите вы? На рисунке ниже автор попытался описать процесс передачи нейронной сети входных значений более наглядно и понятно. Во-первых, есть три различные части изображения:
![Области изображения](https://habrastorage.org/r/w1560/getpro/habr/post_images/53a/296/7bd/53a2967bd7bfcbd21faadf0a030df58b.png)
Вся красная область будет скопирована 1:1, поскольку для начала работы нейрофильтра необходимы исходные данные. Вот в ченм причина копирования такой рамки изображения. Конфигурация сети была такая:
Так что все пиксели с 1-го по 28-й будут скопированы.
Первый пиксель, прошедший обработку фильтром находится в позиции (5,4). Этот пиксель может быть предсказан с помощью остальных 28-ми пикселей и нейронной сети. Это видно из иллюстрации выше.
Все зеленые пиксели – входные пиксели, которые обрабатывает нейронная сеть, в результате получается предсказанное значение для СИНЕГО пикселя.
В этом разделе автор описывает разработанные и используемые компоненты. Весь код написан на JAVA.
На первом этапе необходимо обучить нейронную сеть. Чтобы выполнить этот шаг немного быстрее, автор разработал Pattern Exporter, который создает тренировочную последовательность для JavaNNS Tool. Для наглядности данный шаг описывает рисунок ниже.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/146/d3e/44a/146d3e44ae224ef696a786ff1fd585a6.png)
После окончания обучения нейронной сети, ее необходимо использовать в кодере/энкодере. Детальное пояснение описанного этапа приведено на рисунке ниже.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/950/3a7/372/9503a7372ebabd16d019e998e4b84cb1.png)
Для кодирования и декодирования автор использовал библиотеку pngj. Найти ее можно тут.
Существует множество способов выбора конфигурации нейронной сети.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/d14/98e/965/d1498e965e67fbc185c32b54436ac831.png)
Возможные способы выбора конфигурации нейронной сети:
Ниже приведены некоторые и оцененных автором оптимальных вариантов для проектирования нейронной сети. В основном он оценивал их, просто проверяя при помощи нескольких выборок изображений, а затем вычислял BPP (bit per pixel) нейронной сети и определил лучшие параметры. Это привело к следующим результатам:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/7cc/c2a/880/7ccc2a880be31a4da3e2de9af2b41da4.png)
Оцененная конфигурация нейронной сети:
На следующем этапе автор сравнивал свой нейрофильтр с другими фильтрами PNG, которые используются в настоящее время. Тестирование происходило на нескольких изображениях.
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/6c9/c87/604/6c9c8760446dbde8d297e5d3dfe24d1b.png)
Видно, что нейронная сеть несколько хуже справляется с сжатием изображения, чем фильтры Paeth и Average, но она намного лучше, чем Sub и Up. После этой проверки, была проведена еще одна, в ней участвовало гораздо больше изображений (111), на которых были запечатлена природа. Необходимо было узнать, с какими изображения фильтр справляется лучше всего, а с какими хуже.Ниже представлены изображения, с которыми нейронная сеть справилась намного лучше всех остальных фильтров:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/efe/cf5/94c/efecf594ceb8aef74060eaad8f8ade9e.png)
Так что, можно сделать выводы о том, что нейронная сеть хороша в использовании, если в изображении присутствует:
На следующем шаге автор порылся в своих фотографиях, сделанных за время отпуска, чтобы найти ту, что удовлетворяла бы условия, описанные выше и нашел такую:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/2f3/a25/242/2f3a25242ec188f0274ddf54b14d7fbd.png)
В результате были расчитаны следующие значения BPP для 6 фильтров:
Таким образом теория о признаках изображения для лучшего сжатия с помощью нейрофильтра подтвердились.
Еще один тест автор проводил, чтобы выяснить, как влияет на сжатие происхождение объекта на изображении. Получились следующие результаты:
![image](https://habrastorage.org/r/w1560/getpro/habr/post_images/094/6f8/956/0946f8956694307c01dcb6f39122d2c8.png)
Проект есть на GIT Hub. Кому интересно, можете посмотреть.
Тема исследования
Главной причиной данной работы было улучшение существующих предварительных фильтров. Создать новый фильтр, который с помощью искусственной нейронной сети делал бы наилучший прогноз, приводящий к лучшему сжатию файла.
Сжатие
Классически PNG-компрессия делится на два шага:
- Предварительная фильтрация (с использованием предикторов);
- Компрессия (с помощью DEFLATE).
В данной статье важен только первый шаг. На рисунке ниже вы можете видеть существующие на данный момент предварительные фильтры, и как они сохраняют разницу между реальным и предсказанным пикселем.
![Работа предиктора](https://habrastorage.org/getpro/habr/post_images/239/e1b/ede/239e1bede7199b66555641537983d782.png)
Существующие на данный момент фильтры + новое решение:
Тип | Имя | Функция фильтра | Функция восстановления |
0 | None | Filt(x) = Orig(x) | Recon(x) = Filt(x) |
1 | Sub | Filt(x) = Orig(x) — Orig(a) | Recon(x) = Filt(x) + Recon(a) |
2 | Up | Filt(x) = Orig(x) — Orig(b) | Recon(x) = Filt(x) + Recon(b) |
3 | Average | Filt(x) = Orig(x) — floor((Orig(a) — Orig(b) / 2)) | Recon(x) = Filt(x) + floor((Recon(a) — Recon(b) / 2)) |
4 | Paeth | Filt(x) = Orig(x) — PaethPredictor(Orig(a), Orig(b), Orig(d)) | Recon(x) = Filt(x) + PaethPredictor(Recon(a), Recon(b), Recon(d)) |
5 | Neural Network | Filt(x) = Orig(x) — NN(ArrayOfInputPixels) | Recon(x) = Filt(x) + NN(ArrayOfInputPixels) |
Нейронная сеть в качестве предиктора
Последний фильтр – новая реализация автора данной статьи. Он внутренне использует нейронную сеть с массивом входных пикселей. В результате возвращает переменную предсказанного пикселя. Как и в других фильтрах сохраняется разность между оригинальным и предсказанным значением. Но что это за входные значения спросите вы? На рисунке ниже автор попытался описать процесс передачи нейронной сети входных значений более наглядно и понятно. Во-первых, есть три различные части изображения:
- Копируемая (обозначена КРАСНЫМ);
- Входные пиксели для нейронной сети (обозначены ЗЕЛЕНЫМ);
- Предсказанный пиксель (обозначен СИНИМ).
![Области изображения](https://habrastorage.org/getpro/habr/post_images/53a/296/7bd/53a2967bd7bfcbd21faadf0a030df58b.png)
Скопированные пиксели
Вся красная область будет скопирована 1:1, поскольку для начала работы нейрофильтра необходимы исходные данные. Вот в ченм причина копирования такой рамки изображения. Конфигурация сети была такая:
- 28 входных нейронов (отмечено ЗЕЛЕНЫМ) – (8*4-4) px.
- 1 выходной нейрон (отмечено СИНИМ) – 29-й px.
Так что все пиксели с 1-го по 28-й будут скопированы.
Входные пиксели
Первый пиксель, прошедший обработку фильтром находится в позиции (5,4). Этот пиксель может быть предсказан с помощью остальных 28-ми пикселей и нейронной сети. Это видно из иллюстрации выше.
Прогнозируемый пиксель
Все зеленые пиксели – входные пиксели, которые обрабатывает нейронная сеть, в результате получается предсказанное значение для СИНЕГО пикселя.
Компоненты
В этом разделе автор описывает разработанные и используемые компоненты. Весь код написан на JAVA.
На первом этапе необходимо обучить нейронную сеть. Чтобы выполнить этот шаг немного быстрее, автор разработал Pattern Exporter, который создает тренировочную последовательность для JavaNNS Tool. Для наглядности данный шаг описывает рисунок ниже.
![image](https://habrastorage.org/getpro/habr/post_images/146/d3e/44a/146d3e44ae224ef696a786ff1fd585a6.png)
После окончания обучения нейронной сети, ее необходимо использовать в кодере/энкодере. Детальное пояснение описанного этапа приведено на рисунке ниже.
![image](https://habrastorage.org/getpro/habr/post_images/950/3a7/372/9503a7372ebabd16d019e998e4b84cb1.png)
- Входное изображение: простое изображение, которое будет сжимать нейронная сеть.
- PNG Encoder/Decoder: кодирование и декодирование изображения с использование предиктора на нейронной сети.
- Neural Netwrok: нейронная сеть, разработанная на языке программирования JAVA.
- JNNSParser
- Выходное изображение: в качестве выхода должно получится изображение меньше того, что сжималось.
Для кодирования и декодирования автор использовал библиотеку pngj. Найти ее можно тут.
Результаты
Существует множество способов выбора конфигурации нейронной сети.
![image](https://habrastorage.org/getpro/habr/post_images/d14/98e/965/d1498e965e67fbc185c32b54436ac831.png)
Возможные способы выбора конфигурации нейронной сети:
- выбор количества входных нейронов;
- определение схемы входных нейронов;
- выбор количества скрытых нейронов;
- выбор количества скрытых слоев нейронов;
- определение функций активации нейронов;
- определение алгоритма обучения
- и прочее...
Ниже приведены некоторые и оцененных автором оптимальных вариантов для проектирования нейронной сети. В основном он оценивал их, просто проверяя при помощи нескольких выборок изображений, а затем вычислял BPP (bit per pixel) нейронной сети и определил лучшие параметры. Это привело к следующим результатам:
![image](https://habrastorage.org/getpro/habr/post_images/7cc/c2a/880/7ccc2a880be31a4da3e2de9af2b41da4.png)
Оцененная конфигурация нейронной сети:
- Количество входных нейронов: 28.
- Количество скрытых нейронов:
- 9 нейронов (3х3);
- 25 нейронов (5х5).
- Количество скрытых слоев: 1.
- Функция активации: сигмоида, ограничивающая диапазон от 0,2 до 0,8.
- Алгоритм обучения: обратное распространение ошибки.
Сравнение с другими предикторами PNG
На следующем этапе автор сравнивал свой нейрофильтр с другими фильтрами PNG, которые используются в настоящее время. Тестирование происходило на нескольких изображениях.
![image](https://habrastorage.org/getpro/habr/post_images/6c9/c87/604/6c9c8760446dbde8d297e5d3dfe24d1b.png)
Видно, что нейронная сеть несколько хуже справляется с сжатием изображения, чем фильтры Paeth и Average, но она намного лучше, чем Sub и Up. После этой проверки, была проведена еще одна, в ней участвовало гораздо больше изображений (111), на которых были запечатлена природа. Необходимо было узнать, с какими изображения фильтр справляется лучше всего, а с какими хуже.Ниже представлены изображения, с которыми нейронная сеть справилась намного лучше всех остальных фильтров:
![image](https://habrastorage.org/getpro/habr/post_images/efe/cf5/94c/efecf594ceb8aef74060eaad8f8ade9e.png)
I wasnt sure what these picture have in common. Well there are many flowers. So possibly my Neural Network really likes Flowers. But I wasn’t very comfortable with that explanation.
Так что, можно сделать выводы о том, что нейронная сеть хороша в использовании, если в изображении присутствует:
- множество текстур;
- различные текстуры;
- мало шума.
На следующем шаге автор порылся в своих фотографиях, сделанных за время отпуска, чтобы найти ту, что удовлетворяла бы условия, описанные выше и нашел такую:
![image](https://habrastorage.org/getpro/habr/post_images/2f3/a25/242/2f3a25242ec188f0274ddf54b14d7fbd.png)
В результате были расчитаны следующие значения BPP для 6 фильтров:
Тип | Имя | BPP |
0 | None | 7.289 |
1 | Sub | 6.681 |
2 | Up | 6.667 |
3 | Average | 6.433 |
4 | Paeth | 6.486 |
5 | NN | 6.368 |
Таким образом теория о признаках изображения для лучшего сжатия с помощью нейрофильтра подтвердились.
Сравнение изображений природы с изображением того, что создал человек
Еще один тест автор проводил, чтобы выяснить, как влияет на сжатие происхождение объекта на изображении. Получились следующие результаты:
![image](https://habrastorage.org/getpro/habr/post_images/094/6f8/956/0946f8956694307c01dcb6f39122d2c8.png)
Заключение
- Есть большой потенциал. Не было достаточно времени, чтобы найти подходящую настройку нейронной сети. Может быть, если бы специализировался в данной области, то нейрофильтр побил бы по показаниям BPP другие фильтры.
- Возможно, используя другую топологию нейронной сети, можно привнести улучшения. Были мысли о рекурсивных нейронных сетях…
- Другой идеей было то, что можно было обучить нейронную сеть обрабатывать только один тип изображений.
- Производительность не была целью, над которой работал автор. Понятно, что другие фильтры обрабатывают изображения гораздо быстрее, чем приведенное решение.
Проект есть на GIT Hub. Кому интересно, можете посмотреть.