Эта статья — третья из моей серии «Рисование ИИ», нажмитездесьВесь цикл статей можно посмотреть
Исходный код этой статьи можно получить, ответив на «Миграция стиля изображения» в фоновом режиме общедоступной учетной записи WeChat «01 Binary».
Введение
Так называемая передача стиля изображения относится к технологии объединения содержимого изображения содержимого A со стилем изображения стиля B для создания изображения C со стилем изображения A и содержимым изображения B. В настоящее время эта технология получила широкое распространение.Вот приложение от Amway - "Big Painter", которое может автоматически преобразовывать фотографии пользователя в картины в стиле художника.
Подготовить
На самом деле, когда я только начинал писать эту статью, я собирался подробно изложить принцип, но потом обнаружил, что формул слишком много, даже если бы я написал, никто бы не прочитал, тем более, что пользователи изначально таргетировали по этой статье нужно только реализовать функции новичка. Кроме того, существует слишком много блогов о принципиальном анализе передачи стиля, поэтому здесь я сосредоточусь на том, как использовать TensorFlow для реализации приложения быстрой передачи стиля, и анализ принципа будет пройден. Если вы хотите добиться только этого эффекта, вы можете перейти к разделу «Запуск».
На первом этапе нам нужно заранее установить TensorFlow.Если у вас есть партнер по графическому процессору, вы можете обратиться к этой моей статье, чтобы создать среду графического процессора:«Искусственный интеллект рисует первую пулю — используйте графический процессор, чтобы ускорить процесс обучения», если вы планируете запускать его напрямую с ЦП, вы можете выполнить следующую строку
pip install numpy tensorflow scipy
принцип
Эта статья основана наA Neural Algorithm of Artistic StyleМетод, предложенный в этой статье, реализован.Если вы считаете, что читать английскую статью слишком хлопотно, вы также можете проверить мой перевод этой статьи.【Перевод】Алгоритм нейронной сети для передачи художественного стиля.
Чтобы интегрировать стиль карты стилей с содержимым карты контента, сгенерированное изображение должно быть как можно ближе к карте контента по содержанию и как можно ближе к карте стиля по стилю. необходимо определитьФункция потери контентаифункция потери стиля, которая взвешивается как функция общих потерь.
предварительно обученная модель
CNN имеет возможность абстрагировать и понимать изображения, поэтому выходные данные каждого сверточного слоя можно рассматривать как содержимое изображения.Здесь мы используем модель, обученную VGG19 для обучения миграции.Принято считать, что обучение сверточной нейронной сети Пошаговый процесс извлечения признаков набора данных, от простых признаков до сложных признаков. То, что обученная модель изучила, — это метод извлечения признаков изображения, а модель — это модель, предварительно обученная на наборе данных imagenet, поэтому теоретически ее также можно напрямую использовать для извлечения признаков других изображений, хотя эффект может не быть в оригинале Модели, обученные на наборах данных, хороши, но могут сэкономить много времени на обучение, что очень полезно в определенных ситуациях.
Загрузите предварительно обученную модель
def vggnet(self):
# 读取预训练的vgg模型
vgg = scipy.io.loadmat(settings.VGG_MODEL_PATH)
vgg_layers = vgg['layers'][0]
net = {}
# 使用预训练的模型参数构建vgg网络的卷积层和池化层
# 全连接层不需要
# 注意,除了input之外,这里参数都为constant,即常量
# 和平时不同,我们并不训练vgg的参数,它们保持不变
# 需要进行训练的是input,它即是我们最终生成的图像
net['input'] = tf.Variable(np.zeros([1, settings.IMAGE_HEIGHT, settings.IMAGE_WIDTH, 3]), dtype=tf.float32)
# 参数对应的层数可以参考vgg模型图
net['conv1_1'] = self.conv_relu(net['input'], self.get_wb(vgg_layers, 0))
net['conv1_2'] = self.conv_relu(net['conv1_1'], self.get_wb(vgg_layers, 2))
net['pool1'] = self.pool(net['conv1_2'])
net['conv2_1'] = self.conv_relu(net['pool1'], self.get_wb(vgg_layers, 5))
net['conv2_2'] = self.conv_relu(net['conv2_1'], self.get_wb(vgg_layers, 7))
net['pool2'] = self.pool(net['conv2_2'])
net['conv3_1'] = self.conv_relu(net['pool2'], self.get_wb(vgg_layers, 10))
net['conv3_2'] = self.conv_relu(net['conv3_1'], self.get_wb(vgg_layers, 12))
net['conv3_3'] = self.conv_relu(net['conv3_2'], self.get_wb(vgg_layers, 14))
net['conv3_4'] = self.conv_relu(net['conv3_3'], self.get_wb(vgg_layers, 16))
net['pool3'] = self.pool(net['conv3_4'])
net['conv4_1'] = self.conv_relu(net['pool3'], self.get_wb(vgg_layers, 19))
net['conv4_2'] = self.conv_relu(net['conv4_1'], self.get_wb(vgg_layers, 21))
net['conv4_3'] = self.conv_relu(net['conv4_2'], self.get_wb(vgg_layers, 23))
net['conv4_4'] = self.conv_relu(net['conv4_3'], self.get_wb(vgg_layers, 25))
net['pool4'] = self.pool(net['conv4_4'])
net['conv5_1'] = self.conv_relu(net['pool4'], self.get_wb(vgg_layers, 28))
net['conv5_2'] = self.conv_relu(net['conv5_1'], self.get_wb(vgg_layers, 30))
net['conv5_3'] = self.conv_relu(net['conv5_2'], self.get_wb(vgg_layers, 32))
net['conv5_4'] = self.conv_relu(net['conv5_3'], self.get_wb(vgg_layers, 34))
net['pool5'] = self.pool(net['conv5_4'])
return net
тренировочные идеи
Мы используем выходные данные некоторых слоев в VGG для представления характеристик содержимого и особенностей стиля изображений. Например, я использую[‘conv4_2’,’conv5_2’]
Для представления характеристик содержимого используйте[‘conv1_1’,’conv2_1’,’conv3_1’,’conv4_1’]
Представляет характеристики стиля. существуетsettings.py
в конфигурации.
# 定义计算内容损失的vgg层名称及对应权重的列表
CONTENT_LOSS_LAYERS = [('conv4_2', 0.5),('conv5_2',0.5)]
# 定义计算风格损失的vgg层名称及对应权重的列表
STYLE_LOSS_LAYERS = [('conv1_1', 0.2), ('conv2_1', 0.2), ('conv3_1', 0.2), ('conv4_1', 0.2), ('conv5_1', 0.2)]
Функция потери контента
где X — матрица признаков изображения шума, а P — матрица признаков изображения контента. M — длина * ширина P, а N — количество каналов. Окончательная потеря контента представляет собой взвешенную сумму потерь контента каждого слоя, а затем усредняется по количеству слоев.
Я знаю, что у многих людей голова болит, когда они видят математическую формулу.Простое понимание состоит в том, что эта формула позволяет модели непрерывно извлекать содержимое изображения в процессе обучения.
функция потери стиля
Рассчитать потери стиля. Мы используем матрицу GRAM матрицы признаков изображения стиля на указанном слое для измерения его стиля, а потерю стиля можно определить как норму L2 разности между матрицей GRAM изображения стиля и матрицей GRAM изображения. Матрица признаков шумового изображения.
Для функции потери стиля каждого слоя мы имеем:
где M — длина*ширина собственной матрицы, а N — количество каналов собственной матрицы. G — это матрица Грама признаков изображения шума, а А — матрица Грама признаков изображения стиля. Окончательная потеря стиля представляет собой взвешенную сумму потерь стиля каждого слоя, а затем усредняется по количеству слоев.
Точно так же не имеет значения, если вы не понимаете формулу, вы просто понимаете ее, так как эта формула может получить стиль изображения в процессе обучения.
Рассчитайте функцию общих потерь и обучите модель
Наконец, нам нужно только ввести функцию потери контента и функцию потери стиля в формулу в начале, все, что нам нужно сделать, это контролировать некоторые веса стиля и веса контента:
# 内容损失权重
ALPHA = 1
# 风格损失权重
BETA = 500
Чем больше АЛЬФА, тем больше информации о содержании окончательно сгенерированного изображения; аналогичным образом, чем больше БЕТА, тем более стилизовано окончательно сгенерированное изображение.
Когда начинается обучение, мы генерируем изображение шума на основе изображения содержимого и шума. И передайте изображение шума в сеть, рассчитайте потери, а затем отрегулируйте изображение шума в соответствии с потерями. Подайте скорректированное изображение в сеть, пересчитайте потери, перенастройте, пересчитайте ... до тех пор, пока не будет достигнуто заданное количество итераций.В это время изображение шума имеет как содержимое изображения содержимого, так и стиль изображения стиля, и вы можете сохранить его.
бегать
Если вас не интересуют приведенные выше принципы, если вы хотите запустить код напрямую, вы можете перейти в общедоступную учетную запись WeChat «01 Binary» и ответить на «Миграция стиля изображения» в фоновом режиме, чтобы получить исходный код. Далее поговорим о том, как использовать этот код, чтобы закончить свою собственную картину.
Сначала посмотрите на структуру проекта:
Под изображениями есть две картинки: карта контента и карта стиля. Выходной файл — это файл, сгенерированный в процессе обучения. Файл .mat — это предтренировочная модель. Models.py — это файл, который мы реализовали для прочитайте модель перед обучением. settings.py — это файл конфигурации, а train.py — окончательный файл обучения.
Для запуска проекта нам просто нужно выполнитьpython train.py
Вот и все, если вы хотите изменить стиль и содержимое, просто замените исходное изображение в файле изображений. Конечно, вы также можетеsettings.py
Измените путь в:
# 内容图片路径
CONTENT_IMAGE = 'images/content.jpg'
# 风格图片路径
STYLE_IMAGE = 'images/style.jpg'
# 输出图片路径
OUTPUT_IMAGE = 'output/output'
# 预训练的vgg模型路径
VGG_MODEL_PATH = 'imagenet-vgg-verydeep-19.mat'
Давайте посмотрим на фотографии после тренировки:
Наконец
Хотя мы можем добиться передачи стиля изображения с помощью приведенного выше кода, он имеет один из самых больших недостатков, то есть обученную модель нельзя сохранить.Каждый раз, когда стиль преобразуется, его нужно запускать снова.Если вы используете ЦП для запустить 1000 раундов, это займет около 30 минут, поэтому рекомендуется использовать GPU для обучения.
Однако, даже если используется графический процессор, время обучения не соответствует коммерческому использованию.Есть ли способ сохранить обученную модель стиля, а затем напрямую и быстро сгенерировать целевое изображение? Конечно, есть.Ли Фейфей из Стэнфорда опубликовал статью «Потери восприятия для передачи стиля в реальном времени и сверхразрешения», используя потери восприятия вместо потерь на пиксели и используя предварительно обученную модель vgg для упрощения первоначального расчета потерь. , добавьте сеть преобразования для непосредственного создания стиля изображения содержимого. Я не буду говорить больше здесь, если вам интересно, вы можете обратиться к двум ссылкам, которые я дал ниже:
- Глубоко интересно | 30 быстрых переводов стиля изображения
- «Принцип передачи стиля и реализации тензорного потока»
Выше приведено все содержание этой статьи.Я чувствую, что это довольно интересно сделать это лично.В связи с моими ограниченными возможностями, если есть какие-либо ошибки в статье, пожалуйста, поправьте меня, большое спасибо!
Ссылаться на
- A Neural Algorithm of Artistic Style
- Глубокое обучение на практике (1) Быстрое понимание и передача стиля
- Глубоко и интересно | 04 Передача стиля изображения
- Учебные заметки: перенос стиля изображения
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat: «01 Binary», после подписки вы можете получить компьютерные данные, тщательно собранные блоггером.