TensorFlow练手项目三:使用VGG19迁移学习实现图像风格迁移

使用VGG19迁移学习实现图像风格迁移


2020.3.15 更新:

使用Python 3.7 + TensorFlow 2.0的实现:

有趣的深度学习——使用TensorFlow 2.0实现图片神经风格迁移 (https://blog.csdn.net/aaronjny/article/details/104879258)


转载请注明出处:https://blog.csdn.net/aaronjny/article/details/79681080


一直想要做个图像风格迁移来玩玩的,感觉还是蛮有意思的。

所谓图像风格迁移,即给定内容图片A,风格图片B,能够生成一张具有A图片内容和B图片风格的图片C。

比如说,我们可以使用梵高先生的名画《星夜》 作为风格图片,来与其他图片生成具有《星夜》风格新图片。emmm,夭寿啦,机器帮你画世界名画啦。。。

举两个生成的例子:

均使用《星夜》作为风格图片(可以替换,我以《星夜》为例):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PBbLpmXy-1584256961127)(https://raw.githubusercontent.com/AaronJny/nerual_style_change/master/sample/input_style_1.jpg)]

示例1:

网络上找到的一张风景图片。

内容图片:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hBlBxLwz-1584256961128)(https://raw.githubusercontent.com/AaronJny/nerual_style_change/master/sample/input_content_1.jpg)]

生成图片:

生成图片1

生成图片的尺寸比较小,没办法,我的显卡太差了,尺寸大一点的话显卡内存不足。

示例2:

嗷嗷嗷,狼人嚎叫~

内容图片:

内容图片2

生成图片:

生成图片2

效果还凑合吧,可以接受。

下面记录实现过程。


一.获取预训练的vgg19模型

VGG19是Google DeepMind发表在ICLR 2015上的论文《VERY DEEP CONVOLUTIONAL NETWORK SFOR LARGE-SCALE IMAGE RECOGNITION》中提出的一种DCNN结构。

众所周知,CNN在图片处理上表现良好,VGG19提出后,也被用在图像处理上。我这里要用到的VGG19模型就是在imagenet数据集上预训练的模型。

一般认为,深度卷积神经网络的训练是对数据集特征的一步步抽取的过程,从简单的特征,到复杂的特征。

训练好的模型学习到的是对图像特征的抽取方法,所以在imagenet数据集上训练好的模型理论上来说,也可以直接用于抽取其他图像的特征,这也是迁移学习的基础。自然,这样的效果往往没有在新数据上重新训练的效果好,但能够节省大量的训练时间,在特定情况下非常有用。

预训练好的VGG19模型可以从这里下载,模型大小500M+。

二.模型编写

这里的模型基本上就是VGG19模型,只是稍微做了一些修改。

我们要从预训练的模型中,获取卷积层部分的参数,用于构建我们自己的模型。VGG19中的全连接层舍弃掉,这一部分对提取图像特征基本无用。

要注意的是,我这里提取出来的VGG参数全部是作为constant(即常量)使用的,也就是说,这些参数是不会再被训练的,在反向传播的过程中也不会改变。

另外,输入层要设置为Variable,我们要训练的就是这个。最开始输入一张噪音图片,然后不断地根据内容loss和风格loss对其进行调整,直到一定次数后,该图片兼具了风格图片的风格以及内容图片的内容。当训练结束时,输入层的参数就是我们生成的图片。

附一张VGG结构图:

VGG结构图

这个代码里主要是定义VGG,至于LOSS在训练过程中进行说明。

models.py

# -*- coding: utf-8 -*-
# @Time    : 18-3-23 下午12:20
# @Author  : AaronJny
# @Email   : Aaron__7@163.com
import tensorflow as tf
import numpy as np
import settings
import scipy.io
import scipy.misc


class Model(object):
    def __init__(self, content_path, style_path):
        self.content = self.loadimg(content_path)  # 加载内容图片
        self.style = self.loadimg(style_path)  # 加载风格图片
        self.random_img = self.get_random_img()  # 生成噪音内容图片
        self.net = self.vggnet()  # 建立vgg网络

    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
  • 55
    点赞
  • 339
    收藏
    觉得还不错? 一键收藏
  • 56
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 56
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值