📚 The CoCalc Library - books, templates and other resources
cocalc-examples / stanford-tensorflow-tutorials / assignments / 02_style_transfer / style_transfer.py
132929 viewsLicense: OTHER
""" Implementation in TensorFlow of the paper1A Neural Algorithm of Artistic Style (Gatys et al., 2016)23Created by Chip Huyen ([email protected])4CS20: "TensorFlow for Deep Learning Research"5cs20.stanford.edu67For more details, please read the assignment handout:8https://docs.google.com/document/d/1FpueD-3mScnD0SJQDtwmOb1FrSwo1NGowkXzMwPoLH4/edit?usp=sharing9"""10import os11os.environ['TF_CPP_MIN_LOG_LEVEL']='2'12import time1314import numpy as np15import tensorflow as tf1617import load_vgg18import utils1920def setup():21utils.safe_mkdir('checkpoints')22utils.safe_mkdir('outputs')2324class StyleTransfer(object):25def __init__(self, content_img, style_img, img_width, img_height):26'''27img_width and img_height are the dimensions we expect from the generated image.28We will resize input content image and input style image to match this dimension.29Feel free to alter any hyperparameter here and see how it affects your training.30'''31self.img_width = img_width32self.img_height = img_height33self.content_img = utils.get_resized_image(content_img, img_width, img_height)34self.style_img = utils.get_resized_image(style_img, img_width, img_height)35self.initial_img = utils.generate_noise_image(self.content_img, img_width, img_height)3637###############################38## TO DO39## create global step (gstep) and hyperparameters for the model40self.content_layer = 'conv4_2'41self.style_layers = ['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv5_1']42# content_w, style_w: corresponding weights for content loss and style loss43self.content_w = None44self.style_w = None45# style_layer_w: weights for different style layers. deep layers have more weights46self.style_layer_w = [0.5, 1.0, 1.5, 3.0, 4.0]47self.gstep = None # global step48self.lr = None49###############################5051def create_input(self):52'''53We will use one input_img as a placeholder for the content image,54style image, and generated image, because:551. they have the same dimension562. we have to extract the same set of features from them57We use a variable instead of a placeholder because we're, at the same time,58training the generated image to get the desirable result.5960Note: image height corresponds to number of rows, not columns.61'''62with tf.variable_scope('input') as scope:63self.input_img = tf.get_variable('in_img',64shape=([1, self.img_height, self.img_width, 3]),65dtype=tf.float32,66initializer=tf.zeros_initializer())67def load_vgg(self):68'''69Load the saved model parameters of VGG-19, using the input_img70as the input to compute the output at each layer of vgg.7172During training, VGG-19 mean-centered all images and found the mean pixels73to be [123.68, 116.779, 103.939] along RGB dimensions. We have to subtract74this mean from our images.7576'''77self.vgg = load_vgg.VGG(self.input_img)78self.vgg.load()79self.content_img -= self.vgg.mean_pixels80self.style_img -= self.vgg.mean_pixels8182def _content_loss(self, P, F):83''' Calculate the loss between the feature representation of the84content image and the generated image.8586Inputs:87P: content representation of the content image88F: content representation of the generated image89Read the assignment handout for more details9091Note: Don't use the coefficient 0.5 as defined in the paper.92Use the coefficient defined in the assignment handout.93'''94###############################95## TO DO96self.content_loss = None97###############################9899def _gram_matrix(self, F, N, M):100""" Create and return the gram matrix for tensor F101Hint: you'll first have to reshape F102"""103###############################104## TO DO105return None106###############################107108def _single_style_loss(self, a, g):109""" Calculate the style loss at a certain layer110Inputs:111a is the feature representation of the style image at that layer112g is the feature representation of the generated image at that layer113Output:114the style loss at a certain layer (which is E_l in the paper)115116Hint: 1. you'll have to use the function _gram_matrix()1172. we'll use the same coefficient for style loss as in the paper1183. a and g are feature representation, not gram matrices119"""120###############################121## TO DO122return None123###############################124125def _style_loss(self, A):126""" Calculate the total style loss as a weighted sum127of style losses at all style layers128Hint: you'll have to use _single_style_loss()129"""130###############################131## TO DO132self.style_loss = None133###############################134135def losses(self):136with tf.variable_scope('losses') as scope:137with tf.Session() as sess:138# assign content image to the input variable139sess.run(self.input_img.assign(self.content_img))140gen_img_content = getattr(self.vgg, self.content_layer)141content_img_content = sess.run(gen_img_content)142self._content_loss(content_img_content, gen_img_content)143144with tf.Session() as sess:145sess.run(self.input_img.assign(self.style_img))146style_layers = sess.run([getattr(self.vgg, layer) for layer in self.style_layers])147self._style_loss(style_layers)148149##########################################150## TO DO: create total loss.151## Hint: don't forget the weights for the content loss and style loss152self.total_loss = None153##########################################154155def optimize(self):156###############################157## TO DO: create optimizer158self.opt = None159###############################160161def create_summary(self):162###############################163## TO DO: create summaries for all the losses164## Hint: don't forget to merge them165self.summary_op = None166###############################167168169def build(self):170self.create_input()171self.load_vgg()172self.losses()173self.optimize()174self.create_summary()175176def train(self, n_iters):177skip_step = 1178with tf.Session() as sess:179180###############################181## TO DO:182## 1. initialize your variables183## 2. create writer to write your grapp184###############################185186sess.run(self.input_img.assign(self.initial_img))187188###############################189## TO DO:190## 1. create a saver object191## 2. check if a checkpoint exists, restore the variables192##############################193194initial_step = self.gstep.eval()195196start_time = time.time()197for index in range(initial_step, n_iters):198if index >= 5 and index < 20:199skip_step = 10200elif index >= 20:201skip_step = 20202203sess.run(self.opt)204if (index + 1) % skip_step == 0:205###############################206## TO DO: obtain generated image, loss, and summary207gen_image, total_loss, summary = None, None, None208###############################209210# add back the mean pixels we subtracted before211gen_image = gen_image + self.vgg.mean_pixels212writer.add_summary(summary, global_step=index)213print('Step {}\n Sum: {:5.1f}'.format(index + 1, np.sum(gen_image)))214print(' Loss: {:5.1f}'.format(total_loss))215print(' Took: {} seconds'.format(time.time() - start_time))216start_time = time.time()217218filename = 'outputs/%d.png' % (index)219utils.save_image(filename, gen_image)220221if (index + 1) % 20 == 0:222###############################223## TO DO: save the variables into a checkpoint224###############################225pass226227if __name__ == '__main__':228setup()229machine = StyleTransfer('content/deadpool.jpg', 'styles/guernica.jpg', 333, 250)230machine.build()231machine.train(300)232233