Улучшение изображений с помощью нейросети с OpenCV (в 3 шага)

Tags: Изображения, улучшение, OpenCV, разрешение, upscale

Эта статья расскажет о том, как увеличить разрешение ваших изображений, используя новейшие алгоритмы, с помощью простой в и функциональной библиотеки OpenCV на Python – улучшение изображений доступно каждому!

Эта статья – перевод. Для тех, кто хорошо знает английский – вот оригинал.
На основе этой статьи я сделал бота.

Сверхразрешение в OpenCV

OpenCV – это библиотека компьютерного зрения с открытым исходным кодом, которая содержит обширную коллекцию отличных алгоритмов. В одном из последних обновлений OpenCV появилася простой в использовании интерфейс для реализации сверхразрешения (Super Resolution – SR) на основе методов глубокого обучения. Интерфейс содержит предварительно обученные модели – эффективные и простые в использовании. В этой статье я объясню, что они могут и покажу, шаг за шагом, как с ними работать. Пока что поддерживаются C ++ и Python.

ПРИМЕЧАНИЕ: Вам не нужны специальные знания о SR, чтобы использовать этот код. Я запускаю его на компьютере с Ubuntu 16.04, но он работает для любых других дистрибутивов (также работает на Windows).

Шаги

  • 1. Установка OpenCV с модулями contrib (включая dnn_superres).
  • 2. Загрузка предварительно обученных моделей.
  • 3. Увеличение масштаба изображения.

1. Установка OpenCV с модулями contrib.

Наш первый шаг – установить OpenCV. Некоторые функции будут доступны позже, поэтому будьте осторожны с версией: 4.2.0 для C ++, 4.3.0 добавляет перенос Python, 4.4.0 добавляет вывод GPU. Вы можете следовать инструкциям из документации opencvОчень важно, чтобы вы также установили модуль contrib, потому что именно там находится код интерфейса SR. Вы можете установить все модули contrib или только необходимый SR. Интерфейс или модуль, который мы будем использовать, называется dnn_superres (dnn означает глубокую нейронную сеть; superres – сверхразрешение).

2. Загрузка предварительно обученной модели.

Нам нужно загрузить предварительно обученные модели отдельно, потому что кодовая база OpenCV их не содержит. Причина в том, что некоторые из них довольно большие. И если бы они входили в стандартную кодовую базу, людям, которым они не понадобятся, все равно пришлось бы их загружать. На выбор предлагается несколько моделей (см. раздел Модели этой статьи). Все они являются реализациями популярных статей SR. Пока давайте выберем небольшую модель. Вы можете скачать её здесь. Эта предварительно обученная модель может увеличить разрешение изображения на 2.

3. Увеличение масштаба изображения.

Теперь мы готовы масштабировать наши собственные изображения или даже видео. Я приведу пример кода для C ++ и Python. (Если вы хотите использовать графический процессор для вывода, пожалуйста, также обратитесь к примечаниям внизу этой страницы.) Давайте сначала посмотрим на C ++:

#include 
#include 
#include 

using namespace std;
using namespace cv;
using namespace dnn;
using namespace dnn_superres;

int main(int argc, char *argv[])
{
    //Создаём объект модуля
    DnnSuperResImpl sr;

    //Устанавливаем изображение для улучшения
    string img_path = "image.png";
    Mat img = cv::imread(img_path);

    //Считываем нужную модель
    string path = "FSRCNN_x2.pb";
    sr.readModel(path);

    //Устанавливаем модель и масштаб 
    sr.setModel("fsrcnn", 2);

    //Улучшаем
    Mat img_new;
    sr.upsample(img, img_new);
    cv::imwrite( "upscaled.png", img_new);

    return 0;
}

Я объясню важные части кода.

//Считываем нужную модель
string path = "FSRCNN_x2.pb";
sr.ReadModel(path);

Эта часть загружает все переменные выбранной модели и подготавливает нейронную сеть к выводу. Параметр – путь к предварительно загруженной вами обученной модели. Если вы хотите использовать другую модель, просто загрузите ее (см. раздел “Модели” этой статьи) и обновите путь.

//Устанавливаем модель и масштаб 
sr.setModel("fsrcnn", 2);

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

Первый параметр – это название модели. Вы можете выбирать между: “edsr”, “fsrcnn”, “lapsrn”, “espcn”. Очень важно, чтобы эта модель соответствовала модели, указанной вами в ‘sr.ReadModel()’. Технические характеристики каждой модели приведены в разделе Модели в конце статьи.

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

//Улучшаем
Mat img_new;
sr.upsample(img, img_new);
cv::imwrite( "увеличенный.png", img_new);

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

Теперь просто скомпилируйте и запустите свой файл, чтобы увеличить масштаб изображений!

Вот код на Python:

import cv2
from cv2 import dnn_superres

# Создаём sr-объект
sr = dnn_superres.DnnSuperResImpl_create()

# Считываем изображение
image = cv2.imread('./input.png')

# Считываем модель
path = "EDSR_x3.pb"
sr.readModel(path)

# Устанавливаем модель и масштаб 
sr.setModel("edsr", 3)

# Улучшаем
result = sr.upsample(image)

# Сохраняем
cv2.imwrite("./upscaled.png", result)

Он почти такой же, что и в C ++, за исключением двух вещей

1. Вы должны использовать другую функцию конструктора:

# Создаём sr-объект
sr = dnn_superres.DnnSuperResImpl_create()

2. При увеличении масштаба вы можете назначить увеличенное изображение напрямую, вместо создания изображения-заполнителя:

# Улучшаем
result = sr.upsample(image)

Модели

В настоящее время модулем поддерживаются 4 различные модели SR. Все они могут увеличивать масштаб изображений в 2, 3 и 4 раза. LapSRN може увеличить масштаб аж в 8 раз. Они отличаются точностью, размером и скоростью.

Ввод:

введённое изображение бабочки в плохом качестве

Увеличено с помощью билинейной интерполяции (коэффициент 3):

Улучшенное изображение бабочки с помощью билинейной интерполяции

Увеличенный на FSRCNN (коэффициент 3):

Улучшение изображений

Увеличено на ESDR (в 3 раза):

Улучшенное изображение бабочки с помощью ESDR

Ввод:

Увеличено с помощью билинейной интерполяции (коэффициент 3):

Увеличено на FSRCNN (в 3 раза):

Увеличено на ESDR (в 3 раза):

Оригинальное изображение:

Как вы можете видеть, модели дают довольно приятные результаты, которые уделывают простую билинейную интерполяцию. EDSR дает потрясающие результаты, хотя и немного медленно (вывод за пару секунд). Попробуйте сами!

Примечания по реализации:

  • Если при использовании изображений в формате .jpg выдается ошибка, попробуйте формат .png.
  • Убедитесь, что ваши параметры setModel() совпадают с моделью, которую вы используете в ReadModel().
  • Попробуйте разные модели, чтобы получить разные результаты с точки зрения скорости и производительности.
  • Если вы хотите использовать свой графический процессор для вывода (стандартно это CPU), вы можете установить backend и target на CUDA, после ознакомления с моделью. В зависимости от вашего графического процессора это даст вам увеличение скорости. Это новая функция, поэтому вам нужна версия 4.4.0. Смотрите соответствующий запрос. Вам также необходимо создать opencv с поддержкой CUDA, например, вот так: ссылка на команду сборки opencv.

Установка backend/target на C++

//Считываем нужную модель
string path = "FSRCNN_x2.pb";
sr.readModel(path);

//Установите backend CUDA и target, чтобы включить вывод графического процессора
sr.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA)
sr.setPreferableTarget(cv::dnn::DNN_BACKEND_CUDA)
  
//итдитд..

Установка backend/target на Python

# Считываем нужную модель
path = "EDSR_x3.pb"
sr.readModel(path)

# Установите backend CUDA и target, чтобы включить вывод графического процессора
sr.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
sr.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)

#итдитд..

Ссылки

[1] Bee Lim, Sanghyun Son, Heewon Kim, Seungjun Nah, and Kyoung Mu Lee, “Enhanced Deep Residual Networks for Single Image Super-Resolution”, 2nd NTIRE: New Trends in Image Restoration and Enhancement workshop and challenge on image super-resolution in conjunction with CVPR 2017.

[2] Shi, W., Caballero, J., Huszár, F., Totz, J., Aitken, A., Bishop, R., Rueckert, D. and Wang, Z., “Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network”, Proceedings of the IEEE conference on computer vision and pattern recognition CVPR 2016.

[3] Chao Dong, Chen Change Loy, Xiaoou Tang. “Accelerating the Super-Resolution Convolutional Neural Network”, in Proceedings of European Conference on Computer Vision ECCV 2016.

[4] Lai, W. S., Huang, J. B., Ahuja, N., and Yang, M. H., “Deep laplacian pyramid networks for fast and accurate super-resolution”, In Proceedings of the IEEE conference on computer vision and pattern recognition CVPR 2017.

06.04.2023
Михаил Гок