AI绘画第二弹——图像风格迁移

简介:

简介

所谓图像风格迁移,是指将一幅内容图 A 的内容,和一幅风格图 B 的风格融合在一起,从而生成一张具有 A 图风格和 B 图内容的图片 C 的技术。目前这个技术已经得到了比较广泛的应用,这里安利一个 app——"大画家",这个软件可以将用户的照片自动变换为具有艺术家的风格的图片。

准备

其实刚开始写这篇文章的时候我是准备详细介绍下原理的,但是后来发现公式实在是太多了,就算写了估计也没什么人看,而且这篇文章本来定位的用户就是只需要实现功能的新人。此外,有关风格迁移的原理解析的博客实在是太多了,所以这里我就把重点放在如何使用 TensorFlow 实现一个快速风格迁移的应用上,原理的解析就一带而过了。如果只想实现这个效果的可以跳到"运行"一节。

第一步我们需要提前安装好 TensorFlow,如果有 GPU 的小伙伴可以参考我的这篇文章搭建一个 GPU 环境:《AI 绘画第一弹——用 GPU 为你的训练过程加速》,如果打算直接用 CPU 运行的话,执行下面一行话就可以了

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)]

内容损失函数

image-20190429151634583

其中,X 是噪声图片的特征矩阵,P 是内容图片的特征矩阵。M 是 P 的长*宽,N 是信道数。最终的内容损失为,每一层的内容损失加权和,再对层数取平均。

我知道很多人一看到数学公式就会头疼,简单理解就是这个公式可以让模型在训练过程中不断的抽取图片的内容。

风格损失函数

计算风格损失。我们使用风格图像在指定层上的特征矩阵的 GRAM 矩阵来衡量其风格,风格损失可以定义为风格图像和噪音图像特征矩阵的格莱姆矩阵的差值的 L2 范数。

对于每一层的风格损失函数,我们有:

其中 M 是特征矩阵的长*宽,N 是特征矩阵的信道数。G 为噪音图像特征的 Gram 矩阵,A 为风格图片特征的 GRAM 矩阵。最终的风格损失为,每一层的风格损失加权和,再对层数取平均。

同样的,看不懂公式没关系,你就把它理解为这个公式可以在训练过程中获取图片的风格。

计算总损失函数并训练模型

最后我们只需要将内容损失函数和风格损失函数带入刚开始的公式中即可,要做的就是控制一些风格的权重和内容的权重:

# 内容损失权重
ALPHA = 1
# 风格损失权重
BETA = 500

ALPHA 越大,则最后生成的图片内容信息越大;同理,BETA 越大,则最后生成的图片风格化更严重。

当训练开始时,我们根据内容图片和噪声,生成一张噪声图片。并将噪声图片喂给网络,计算 loss,再根据 loss 调整噪声图片。将调整后的图片喂给网络,重新计算 loss,再调整,再计算…直到达到指定迭代次数,此时,噪声图片已兼具内容图片的内容和风格图片的风格,进行保存即可。

运行

如果对上述原理不感兴趣的,想直接运行代码的可以去微信公众号「01 二进制」后台回复「图像风格迁移」获得源码。接下来我们来说说如何使用这个代码跑出自己的绘画。

首先看下项目结构:

images 下有两张图片,分别是内容图和风格图,output 下是训练过程中产生的文件,.mat 文件就是预训练模型,models.py 是我们实现的用于读取预训练模型的文件,settings.py 是配置文件,train.py 是最终的训练文件。

想要运行该项目,我们只需要执行python train.py即可,想更改风格和内容的的话只要在 images 文件中更换原先的图片即可。当然你也可以在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'

我们来看看训练后的图片:

最后

虽然通过上述代码我们可以实现图像的风格迁移,但是他有一个最大的缺点,就是无法保存训练好的模型,每次转换风格都要重新跑一遍,如果使用 CPU 跑 1000 轮的话大约是在 30 分钟左右,因此推荐大家使用 GPU 进行训练。

但是即使使用上了 GPU,训练时间也无法满足商业使用的,那有没有什么办法可以保存训练好的风格模型,然后直接快速生成目标图片呢?当然是有的,斯坦福的李飞飞发表过一篇《Perceptual Losses for Real-Time Style Transfer and Super-Resolution》,通过使用 perceptual loss 来替代 per-pixels loss 使用 pre-trained 的 vgg model 来简化原先的 loss 计算,增加一个 transform Network,直接生成 Content image 的 style。这里就不再多说了,感兴趣的可以参考我下面给出的两个链接:

  1. 《深度有趣 | 30 快速图像风格迁移》
  2. 《风格迁移背后原理及 tensorflow 实现》

以上就是本篇文章的全部内容,个人做下来感觉还是挺有意思的,因个人能力有限,文中如有纰漏错误之处,还请各位大佬指正,万分感谢!

参考

  1. A Neural Algorithm of Artistic Style
  2. 深度学习实战(一)快速理解实现风格迁移
  3. 深度有趣 | 04 图像风格迁移
  4. 学习笔记:图像风格迁移
相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
3天前
|
机器学习/深度学习 人工智能 编解码
Inf-DiT:清华联合智谱AI推出超高分辨率图像生成模型,生成的空间复杂度从 O(N^2) 降低到 O(N)
Inf-DiT 是清华大学与智谱AI联合推出的基于扩散模型的图像上采样方法,能够生成超高分辨率图像,突破传统扩散模型的内存限制,适用于多种实际应用场景。
45 21
Inf-DiT:清华联合智谱AI推出超高分辨率图像生成模型,生成的空间复杂度从 O(N^2) 降低到 O(N)
|
8天前
|
人工智能 UED
VersaGen:生成式 AI 代理,基于 Stable Diffusion 生成图像,专注于控制一至多个视觉主体等生成细节
VersaGen 是一款生成式 AI 代理,专注于文本到图像合成中的视觉控制能力,支持多种视觉控制类型,并通过优化策略提升图像生成质量和用户体验。
30 8
VersaGen:生成式 AI 代理,基于 Stable Diffusion 生成图像,专注于控制一至多个视觉主体等生成细节
|
23天前
|
机器学习/深度学习 人工智能
Leffa:Meta AI 开源精确控制人物外观和姿势的图像生成框架,在生成穿着的同时保持人物特征
Leffa 是 Meta 开源的图像生成框架,通过引入流场学习在注意力机制中精确控制人物的外观和姿势。该框架不增加额外参数和推理成本,适用于多种扩散模型,展现了良好的模型无关性和泛化能力。
68 11
Leffa:Meta AI 开源精确控制人物外观和姿势的图像生成框架,在生成穿着的同时保持人物特征
|
28天前
|
人工智能 API 语音技术
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
TEN Agent 是一个开源的实时多模态 AI 代理框架,集成了 OpenAI Realtime API 和 RTC 技术,支持语音、文本和图像的多模态交互,具备实时通信、模块化设计和多语言支持等功能,适用于智能客服、实时语音助手等多种场景。
148 15
TEN Agent:开源的实时多模态 AI 代理框架,支持语音、文本和图像的实时通信交互
|
20天前
|
存储 人工智能 安全
从AI换脸到篡改图像,合合信息如何提升视觉内容安全?
从AI换脸到篡改图像,合合信息如何提升视觉内容安全?
从AI换脸到篡改图像,合合信息如何提升视觉内容安全?
|
1月前
|
机器学习/深度学习 人工智能
SNOOPI:创新 AI 文本到图像生成框架,提升单步扩散模型的效率和性能
SNOOPI是一个创新的AI文本到图像生成框架,通过增强单步扩散模型的指导,显著提升模型性能和控制力。该框架包括PG-SB和NASA两种技术,分别用于增强训练稳定性和整合负面提示。SNOOPI在多个评估指标上超越基线模型,尤其在HPSv2得分达到31.08,成为单步扩散模型的新标杆。
70 10
SNOOPI:创新 AI 文本到图像生成框架,提升单步扩散模型的效率和性能
|
1月前
|
人工智能 搜索推荐 开发者
Aurora:xAI 为 Grok AI 推出新的图像生成模型,xAI Premium 用户可无限制访问
Aurora是xAI为Grok AI助手推出的新图像生成模型,专注于生成高逼真度的图像,特别是在人物和风景图像方面。该模型支持文本到图像的生成,并能处理包括公共人物和版权形象在内的多种图像生成请求。Aurora的可用性因用户等级而异,免费用户每天能生成三张图像,而Premium用户则可享受无限制访问。
66 11
Aurora:xAI 为 Grok AI 推出新的图像生成模型,xAI Premium 用户可无限制访问
|
1月前
|
机器学习/深度学习 人工智能 编解码
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
OminiControl 是一个高度通用且参数高效的 AI 图像生成框架,专为扩散变换器模型设计,能够实现图像主题控制和空间精确控制。该框架通过引入极少量的额外参数(0.1%),支持主题驱动控制和空间对齐控制,适用于多种图像生成任务。
71 10
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
|
1月前
|
Web App开发 机器学习/深度学习 人工智能
Magic Copy:开源的 AI 抠图工具,在浏览器中自动识别图像进行抠图
Magic Copy 是一款开源的 AI 抠图工具,支持 Chrome 浏览器扩展。它基于 Meta 的 Segment Anything Model 技术,能够自动识别图像中的前景对象并提取出来,简化用户从图片中提取特定元素的过程,提高工作效率。
83 7
Magic Copy:开源的 AI 抠图工具,在浏览器中自动识别图像进行抠图
|
2月前
|
人工智能 JavaScript 数据可视化
深入探索 Flux Tools 在 AI 图像创作中的强大功能
Flux Tools 是由 Black Forest Labs 开发的一套先进 AI 图像编辑工具,集成了修补、扩展、深度映射和边缘检测等功能,为用户提供高精度的图像控制能力,广泛应用于照片编辑、数字艺术创作和设计工作等领域,极大提升了创作效率与自由度。
下一篇
开通oss服务