美文网首页深度学习基石程序员
如何生成一幅艺术作品

如何生成一幅艺术作品

作者: 小聪明李良才 | 来源:发表于2017-03-19 22:16 被阅读1377次

    示例怎么能够产生一幅艺术

    github阅读效果更佳

    假设我们有一幅大师的画作了,我们怎么能够提取出“大师作品”中的纹理和颜色这些细节让我们的计算机知道,而不是只看到画的整体造型呢?

    对于这个提取特征的问题我们先放一下,如果我们已经有了这些特征,我们要如何应用这些特征到我们新的图片上去呢?我们要将原有图片的风格干净的滤除掉,换作我们指定的风格。
    看下面的图片

    我们称风格画为s,原画为c,转换后的画为x,并且我们有两个评判函数:

    output_4_0.png
    style_image_path = 'images/styles/wave.jpg'
    style_image = Image.open(style_image_path)
    style_image = style_image.resize((height, width))
    style_image
    
    output_5_0.png

    接着我们将图片内容进行转换,转换到我们后续处理适合的形式

    content_array = np.asarray(content_image, dtype='float32')
    content_array = np.expand_dims(content_array, axis=0)
    print(content_array.shape)
    
    style_array = np.asarray(style_image, dtype='float32')
    style_array = np.expand_dims(style_array, axis=0)
    print(style_array.shape)
    
    (1, 512, 512, 3)
    (1, 512, 512, 3)
    

    下一步为了符合 Simonyan and Zisserman (2015)中描述的数据输入格式,我们要做下面的转换

    1. 减去RGB的平均值,在 ImageNet training set 中计算得到的,
    2. 将RGB的顺序变为BGR
    content_array[:, :, :, 0] -= 103.939
    content_array[:, :, :, 1] -= 116.779
    content_array[:, :, :, 2] -= 123.68
    content_array = content_array[:, :, :, ::-1]
    
    style_array[:, :, :, 0] -= 103.939
    style_array[:, :, :, 1] -= 116.779
    style_array[:, :, :, 2] -= 123.68
    style_array = style_array[:, :, :, ::-1]
    

    接着我们定义了在Keras中的3个变量

    content_image = backend.variable(content_array)
    style_image = backend.variable(style_array)
    combination_image = backend.placeholder((1, height, width, 3))
    
    # 我们将其组合到一起
    input_tensor = backend.concatenate([content_image,
                                        style_image,
                                        combination_image], axis=0)
    

    在Keras中有训练好的VGG模型,此处我们使用在Johnson et al. (2016)中提出的VGG16模型,
    我们可以通过下面的语句方便的使用训练好的模型

    model = VGG16(input_tensor=input_tensor, weights='imagenet',
                  include_top=False)
    
    Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
    

    在Keras中对于VGG16的每一层都有自己的名字和输出,我们可以方便的取到
    此处我们取的16层模型,最先的19层模型可以看地址:http://ethereon.github.io/netscope/#/gist/3785162f95cd2d5fee77

    layers = dict([(layer.name, layer.output) for layer in model.layers])
    layers
    
    {'block1_conv1': <tf.Tensor 'Relu:0' shape=(3, 512, 512, 64) dtype=float32>,
     'block1_conv2': <tf.Tensor 'Relu_1:0' shape=(3, 512, 512, 64) dtype=float32>,
     'block1_pool': <tf.Tensor 'MaxPool:0' shape=(3, 256, 256, 64) dtype=float32>,
     'block2_conv1': <tf.Tensor 'Relu_2:0' shape=(3, 256, 256, 128) dtype=float32>,
     'block2_conv2': <tf.Tensor 'Relu_3:0' shape=(3, 256, 256, 128) dtype=float32>,
     'block2_pool': <tf.Tensor 'MaxPool_1:0' shape=(3, 128, 128, 128) dtype=float32>,
     'block3_conv1': <tf.Tensor 'Relu_4:0' shape=(3, 128, 128, 256) dtype=float32>,
     'block3_conv2': <tf.Tensor 'Relu_5:0' shape=(3, 128, 128, 256) dtype=float32>,
     'block3_conv3': <tf.Tensor 'Relu_6:0' shape=(3, 128, 128, 256) dtype=float32>,
     'block3_pool': <tf.Tensor 'MaxPool_2:0' shape=(3, 64, 64, 256) dtype=float32>,
     'block4_conv1': <tf.Tensor 'Relu_7:0' shape=(3, 64, 64, 512) dtype=float32>,
     'block4_conv2': <tf.Tensor 'Relu_8:0' shape=(3, 64, 64, 512) dtype=float32>,
     'block4_conv3': <tf.Tensor 'Relu_9:0' shape=(3, 64, 64, 512) dtype=float32>,
     'block4_pool': <tf.Tensor 'MaxPool_3:0' shape=(3, 32, 32, 512) dtype=float32>,
     'block5_conv1': <tf.Tensor 'Relu_10:0' shape=(3, 32, 32, 512) dtype=float32>,
     'block5_conv2': <tf.Tensor 'Relu_11:0' shape=(3, 32, 32, 512) dtype=float32>,
     'block5_conv3': <tf.Tensor 'Relu_12:0' shape=(3, 32, 32, 512) dtype=float32>,
     'block5_pool': <tf.Tensor 'MaxPool_4:0' shape=(3, 16, 16, 512) dtype=float32>,
     'input_1': <tf.Tensor 'concat:0' shape=(3, 512, 512, 3) dtype=float32>}
    

    下面我们来回到我们之前要做的事情,我们需要定义图片内容和风格的差异,现在我们有了VGG16之后,我们就可以开始了,先初始化一些变量

    content_weight = 0.025
    style_weight = 5.0
    total_variation_weight = 1.0
    

    下面我们将开始使用VGG16的各个层来定义内容和风格这两个比较抽象的东西

    loss = backend.variable(0.)
    

    内容差异函数

    我们来看看不同层级出来的图片信息,我们提取出VGG16中的不同层级,然后将其运用到图片上,看下会得到什么

    output_34_0.png

    总结

    本文只是一个粗略的学习过程,还有更多的论文需要去学习,期待继续学习分享的

    参考

    原文:https://harishnarayanan.org/writing/artistic-style-transfer/
    github地址:https://github.com/llSourcell/How-to-Generate-Art-Demo/blob/master/demo.ipynb
    视频地址:https://www.youtube.com/watch?v=Oex0eWoU7AQ

    
    

    相关文章

      网友评论

      • 32f0a00330b5:“减去RGB的平均值,在 ImageNet training set 中计算得到的”没有看明白,能深入讲解一下吗?
        32f0a00330b5:0,1,2后面-= 和+=的常量是从哪里得到的呢?
      • Flippancy:麻烦,请问一下你是用什么配置的电脑吗?我一次要10多分钟,而且loss不见减少。代码是完全照抄的。用的是macbookpro。最低配的一款= =。
        小聪明李良才: @Flippancy 是很慢。我是在aws上跑的,mac根本跑不动
      • kylesean:这不就是那个去年下半年很火的app?梅德韦杰夫都玩过啊,擦,就是想不起名字来。
        小聪明李良才: @kylesean 是好多类似的app了,我自己照着实现了下,发现运行起来好慢,不知道他们是做了什么改进能把速度提上去的
      • 开发者头条_程序员必装的App:感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/0ffr9s 欢迎点赞支持!
        欢迎订阅《phper进击之路》https://toutiao.io/subjects/75799

      本文标题:如何生成一幅艺术作品

      本文链接:https://www.haomeiwen.com/subject/gmbvnttx.html