import numpy as np
import pandas as pd
import tensorflow as tf
import keras.preprocessing.image as process_im
from keras.applications import vgg19
from keras.models import Model
from tensorflow.python.keras import models
from tensorflow.python.keras import losses
from tensorflow.python.keras import layers
from tensorflow.python.keras import backend as k
from PIL import Image # Python Image Libraryimport matplotlib.pyplot as plt # 可视化库import functools # 用以为可调用对象(callable objects)定义高阶函数或操作import IPython.display # python的交互式shell
图像预处理
PIL中的image对象调用resize方法,此处将图像进行缩放为某高宽的高质量图像
img_to_array转换前后类型都是一样的,唯一区别是转换前元素类型是整型,转换后元素类型是浮点型(和keras等机器学习框架相适应的图像类型。Keras introduced a special function called img_to_array which accepts an input image and then orders the channels correctly based on the image_data_format setting)
content_layers =['block5_conv2']
style_layers =['block1_conv1','block2_conv1','block3_conv1','block4_conv1','block5_conv1']# get the neural transfer modeldefget_model(content_layers_names, style_layers_names):"""
:param content_layers_names: content layers names list
:param style_layers_names: style layers name list
:return: neural transfer model
"""
vgg = tf.keras.applications.vgg19.VGG19(include_top=False)# 删掉最后一层;默认加载ImageNet上的预训练权重
vgg.trainable =False# 参数不可训练# get the content layer and style layer
content_output =[vgg.get_layer(name=layer).output for layer in content_layers_names]
style_output =[vgg.get_layer(name=layer).output for layer in style_layers_names]
model_output = style_output + content_output # list combine# get the neural transfer model
neural_transfer_model = models.Model([vgg.input], model_output)return neural_transfer_model
代价函数
内容代价函数
内容直接定义为内容层的激活值,所以内容代价函数定义为激活值的均方差误差MSE
# get content lossdefcontent_loss_layer(output_layer, target_layer):"""
:param output_layer:
:param target_layer:
:return: some layer content loss
"""# MSE, all elements
content_loss = tf.reduce_mean(tf.square(output_layer - target_layer))return content_loss
# get the gram matrix for style costdefgram_matrix(layer):"""
:param layer: some layer of model
:return: Gram matrix
"""
channels =int(layer.shape[-1])# 通道数为layer最后一层的维度
vector = tf.reshape(layer,[-1, channels])# reshape to n*channel
n = tf.shape(vector)[0]# n=nw*nh# vector.T*vector
gram = tf.matmul(vector, vector, transpose_a=True)return gram / tf.cast(n, tf.float32)# get some layer style lossdefstyle_loss_layer(output_layer, target_layer):"""
:param output_layer:
:param target_layer:
:return:
"""# get the gram matrix of the layer
gram_output = gram_matrix(output_layer)
gram_target = gram_matrix(target_layer)# use the gram to compute the loss of some layer# /(nw*nh*nc)
style_loss = tf.reduce_mean(tf.square(gram_target - gram_output))return style_loss