В этом посте я покажу, как создать сеть автокодировщика, которая может сверхразрешить изображение до 4x, а также способы увеличения его до 10x и, возможно, даже больше.

Зачем использовать автоэнкодер?

Есть много причин, по которым вы можете захотеть использовать этот тип сети, один из примеров - передача изображения в приложении чата. Приложения чата, такие как WhatsApp и Instagram, используют этот тип сжатия, хотя они более сложные и обучаемые в течение более длительного времени и с гораздо большим объемом данных, они используют, потому что из-за сжатия изображения объем данных для загрузки уменьшается, что снижает скорость загрузки. увеличиваются, а также уменьшается объем данных для хранения на серверах без потери качества изображения.

Ссылка на блокнот



Связываю Colab Notebook для проекта здесь. Я буду использовать Google Colab, поскольку они предоставляют бесплатные облачные графические процессоры для обучения, что делает ненужными мощные машины для этих задач.

Обзор

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

Библиотеки для импорта

Мы будем использовать Tensorflow 2.0 для построения сети, модуль U rllib для загрузки изображений, Numpy для обработки массива изображений, Open -Cv2 для изменения размера изображения, модуль Os для загрузки изображений и Matplotlib для отображения изображений.

Что такое автоэнкодеры?

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

Как вы уже догадались, он состоит из кодировщика и декодера. Роль кодировщика состоит в том, чтобы сжимать данные до более низкого измерения таким образом, чтобы сохранялись только наиболее важные функции, такие как PCA, а роль декодера - восстанавливать данные из представления более низкого измерения, чтобы как можно ближе к нему приблизиться. оригинал.

Сборка кодировщика

Здесь у нас есть 2 блока Conv2D, так как у нас есть изображения всего 256 пикселей в высоту и ширину. Однако при использовании изображений размером 1920 X 1080 пикселей я бы предложил использовать более 4 блоков Conv2D с увеличением фильтра в 2 раза. Это обеспечит наличие достаточного количества параметров для изменения и достаточного количества фильтров, которые в конечном итоге можно будет использовать для сверхразрешения изображения до 10x.

Вот краткое изложение модели.

Model: "model" _________________________________________________________________ Layer (type)                 Output Shape              Param #    ================================================================= input_2 (InputLayer)         [(None, 256, 256, 3)]     0          _________________________________________________________________ conv2d_5 (Conv2D)            (None, 256, 256, 64)      1792       _________________________________________________________________ conv2d_6 (Conv2D)            (None, 256, 256, 64)      36928      _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 128, 128, 64)      0          _________________________________________________________________ conv2d_7 (Conv2D)            (None, 128, 128, 128)     73856      _________________________________________________________________ conv2d_8 (Conv2D)            (None, 128, 128, 128)     147584     _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 64, 64, 128)       0          _________________________________________________________________ conv2d_9 (Conv2D)            (None, 64, 64, 256)       295168     ================================================================= Total params: 555,328
Trainable params: 555,328 
Non-trainable params: 0 _________________________________________________________________

Как видите, у нас есть 256 фильтров, мы могли бы остановиться на 128 или 64, но у нас не так много изображений, с которыми можно было бы тренироваться, а также реальные размеры изображения всего 256X 256, и из-за этого , мы должны компенсировать это, используя множество фильтров. Хотя в реальной жизни изображение будет 1920 X 1080, и поэтому сжатие до 192 X 108 будет гораздо более очевидным.

Изображение, чтобы лучше понять поток кодировщика

Вся модель

Как вы можете видеть, мы используем повышающую дискретизацию вместо Conv2D Transpose, это связано с тем, что транспонирование Conv2D имеет обучаемые параметры, но при этом полезно для нашей задачи, оно увеличивает время обучения и небольшой объем данных, который у нас есть, он не нужен, но, безусловно, для Для моделей производственного уровня обязательно использовать слой Conv2D Transpose вместо слоя Upsampling2D.

Вот резюме,

Model: "model_15" _______________________________________________________________
Layer (type)                    Output Shape         Param #
===============================================================
input_21 (InputLayer)           [(None, 256, 256, 3)   0
________________________________________________________________ conv2d_141 (Conv2D)             (None, 256, 256, 64)  1792          ________________________________________________________________ conv2d_142 (Conv2D)             (None, 256, 256, 64)  36928                 ________________________________________________________________ max_pooling2d_36 (MaxPooling2D) (None, 128, 128, 64)   0           ________________________________________________________________ conv2d_143 (Conv2D)             (None, 128, 128, 128  73856           ________________________________________________________________ conv2d_144 (Conv2D)             (None, 128, 128, 128  147584                   ________________________________________________________________ max_pooling2d_37 (MaxPooling2D) (None, 64, 64, 128)    0                       ________________________________________________________________ conv2d_145 (Conv2D)             (None, 64, 64, 256)   295168              ________________________________________________________________ up_sampling2d_21 (UpSampling2D) (None, 128, 128, 256   0                        ________________________________________________________________ conv2d_146 (Conv2D)             (None, 128, 128, 128  295040               ________________________________________________________________ conv2d_147 (Conv2D)             (None, 128, 128, 128  147584                   ________________________________________________________________ add_20 (Add)                    (None, 128, 128, 128   0           ________________________________________________________________ up_sampling2d_22 (UpSampling2D) (None, 256, 256, 128   0                 ________________________________________________________________ conv2d_148 (Conv2D)             (None, 256, 256, 64)  73792               ________________________________________________________________ conv2d_149 (Conv2D)             (None, 256, 256, 64)  36928                      ________________________________________________________________ add_21 (Add)                    (None, 256, 256, 64)   0                      ________________________________________________________________ conv2d_150 (Conv2D)             (None, 256, 256, 3)   1731                   ================================================================ Total params: 1,110,403 
Trainable params: 1,110,403 
Non-trainable params: 0 ________________________________________________________________

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

Остаточное соединение более очевидно на этой диаграмме:

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

Однако я предлагаю не использовать его в продакшене, а использовать Perpetual loss, он лучше, чем MSE. Исследовательскую статью, объясняющую потерю, можно найти здесь.

Получение данных и метод обучения

Я получил изображения автомобилей из сети изображений с помощью Urllib, а затем использовал OpenCV, чтобы изменить размер изображения до 1/4 его размера. Использование изображения с измененным размером с большой потерей данных в качестве входных данных и исходного изображения сверхвысокого разрешения в качестве изображения для сравнения потерь.

Таким образом, модель будет постепенно учиться увеличивать разрешение изображения до 4-кратного его исходного разрешения, оптимизируя потери между восстановленным и исходным изображением.

Конечный результат

Как видите, наш автоэнкодер отлично справляется со своей задачей!

Места для улучшения

Ниже приведены способы увеличения сверхвысокого разрешения до 10 раз, а может быть, даже больше!

  1. Самым важным моментом было бы использовать изображения Full HD для обучения модели, а также использовать более 5000 изображений.
  2. Используйте слои Conv2D Transpose вместо слоев Upscaling.
  3. Используйте Perceptual Loss вместо MSE.
  4. Используйте оптимизатор Adam вместо Adadelta.
  5. Используйте Сверточные слои с динамической регуляризацией.

Примечание

Я впервые пишу статью и что-то объясняю, поэтому, пожалуйста, дайте мне знать, как я могу улучшить, а также сообщите, если вы чего-то не поняли. Я буду более чем счастлив помочь. Кроме того, подробное объяснение кода можно найти здесь: https://www.coursera.org/learn/image-super-resolution-autoencoders-keras/