TensorFlow实战——CNN(VGGNet19)——图像风格转化

https://www.jianshu.com/p/2961d27674a5?from=timeline 代码如下:

# -*- coding: utf-8 -*-
"""
Created on Mon Apr 22 14:30:27 2019
@author: 10244074
"""

import scipy.io as sio
import tensorflow as tf
import numpy as np
import PIL

vgg19Model = "imagenet-vgg-verydeep-19.mat"
vggLayer = sio.loadmat(vgg19Model)['layers'][0]
noiseSave = "noiseImage"
contextPath = "2 (1).png"
stylePath = "2 (2).png"
# 设置图像的路径以及需要调整到的宽度值和高度值
IMAGE_W = 800
IMAGE_H = 600
CONTENT_LAYERS = [('conv4_2', 1.)]
STYLE_LAYERS = [('conv1_1', 1.), ('conv2_1', 1.), ('conv3_1', 1.), ('conv4_1', 1.), ('conv5_1', 1.)]


def getWeightAndBias(i):
    weight = vggLayer[i][0][0][0][0][0]
    weight = tf.constant(weight)
    bias = vggLayer[i][0][0][0][0][1]
    bias = tf.constant(np.reshape(bias, bias.size))
    return weight, bias


# 定义建立池化层和卷积层网络的函数
def build_net(ntype, nin, nwb=None):
    if ntype == 'conv':
        return tf.nn.relu(tf.nn.conv2d(nin, nwb[0], strides=[1, 1, 1, 1], padding='SAME') + nwb[1])
    elif ntype == 'pool':
        return tf.nn.avg_pool(nin, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')


def getNet(inputImage):
    net = {}
    # net["input"] = tf.Variable(np.zeros((1, IMAGE_H, IMAGE_W, 3)).astype("float32"))
    net["input"] = inputImage
    net["conv1_1"] = build_net("conv", net["input"], getWeightAndBias(0))
    net['conv1_2'] = build_net('conv', net['conv1_1'], getWeightAndBias(2))
    net['pool1'] = build_net('pool', net['conv1_2'])
    net['conv2_1'] = build_net('conv', net['pool1'], getWeightAndBias(5))
    net['conv2_2'] = build_net('conv', net['conv2_1'], getWeightAndBias(7))
    net['pool2'] = build_net('pool', net['conv2_2'])
    net['conv3_1'] = build_net('conv', net['pool2'], getWeightAndBias(10))
    net['conv3_2'] = build_net('conv', net['conv3_1'], getWeightAndBias(12))
    net['conv3_3'] = build_net('conv', net['conv3_2'], getWeightAndBias(14))
    net['conv3_4'] = build_net('conv', net['conv3_3'], getWeightAndBias(16))
    net['pool3'] = build_net('pool', net['conv3_4'])
    net['conv4_1'] = build_net('conv', net['pool3'], getWeightAndBias(19))
    net['conv4_2'] = build_net('conv', net['conv4_1'], getWeightAndBias(21))
    net['conv4_3'] = build_net('conv', net['conv4_2'], getWeightAndBias(23))
    net['conv4_4'] = build_net('conv', net['conv4_3'], getWeightAndBias(25))
    net['pool4'] = build_net('pool', net['conv4_4'])
    net['conv5_1'] = build_net('conv', net['pool4'], getWeightAndBias(28))
    net['conv5_2'] = build_net('conv', net['conv5_1'], getWeightAndBias(30))
    net['conv5_3'] = build_net('conv', net['conv5_2'], getWeightAndBias(32))
    net['conv5_4'] = build_net('conv', net['conv5_3'], getWeightAndBias(34))
    net['pool5'] = build_net('pool', net['conv5_4'])
    return net


def getImage(path):
    image = np.array(PIL.Image.open(path))
    # image=scipy.misc.imresize(image,(IMAGE_H,IMAGE_W))
    image = image[np.newaxis, :, :, :] - 128.0  # 以0为中心,可以加快收敛
    image = image.astype(np.float32)
    return image


def saveImage(image, path, i):
    image = image + 128
    image = image[0]
    image = np.clip(image, 0, 255).astype("uint8")
    path1 = path + str(i) + ".png"
    PIL.Image.fromarray(image).save(path1)


def getLoss(noiseImage, contextImage, styleImag):
    contextLay = getNet(contextImage)
    styleLay = getNet(styleImag)
    noiseLay = getNet(noiseImage)
    styleLoss = sum(map(lambda l: l[1] * buildStyLoss(noiseLay, styleLay, l[0]), STYLE_LAYERS))
    contextLoss = sum(map(lambda l: l[1] * buildConLoss(noiseLay, contextLay, l[0]), CONTENT_LAYERS))
    return contextLoss, styleLoss


def buildConLoss(noiseLay, contextLay, strKey):
    noiseLay = noiseLay[strKey]
    contextLay = contextLay[strKey]
    _, high, wid, chan = map(lambda l: l.value, noiseLay.get_shape())
    size = high * wid * chan
    return tf.nn.l2_loss(contextLay - noiseLay) / size


def buildStyLoss(noiseLay, styleLay, strKey):
    noiseLay = noiseLay[strKey]
    styleLay = styleLay[strKey]
    _, high, wid, chan = map(lambda l: l.value, noiseLay.get_shape())
    size = high * wid * chan
    noiseLay = tf.reshape(noiseLay, (-1, chan))
    noiseLay = tf.matmul(tf.transpose(noiseLay), noiseLay)
    styleLay = tf.reshape(styleLay, (-1, chan))
    styleLay = tf.matmul(tf.transpose(styleLay), styleLay)
    return tf.nn.l2_loss(noiseLay - styleLay) / (size ** 2)


with tf.Session() as sess:
    contextImage = getImage(contextPath)
    styleImage = getImage(stylePath)
    noiseImage = tf.Variable(np.random.randn(1, IMAGE_H, IMAGE_W, 3), dtype="float32")
    contextLoss, styleLoss = getLoss(noiseImage, contextImage, styleImage)
    totalLoss = contextLoss + 0.0001*styleLoss
    train = tf.train.AdamOptimizer(2.0).minimize(totalLoss)
    sess.run(tf.global_variables_initializer())
    for i in range(0, 500):
        finaIma, _, loss, mu, xin = sess.run([noiseImage, train, totalLoss, contextLoss, styleLoss])
        print("contextLoss: " + str(mu) + "  " + "styleLoss: " + str(xin))
        if i % 25 == 0:
            saveImage(finaIma, noiseSave, i)

 

你可能感兴趣的:(TensorFlow实战——CNN(VGGNet19)——图像风格转化)