Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132929 views
License: OTHER
1
""" Implementation in TensorFlow of the paper
2
A Neural Algorithm of Artistic Style (Gatys et al., 2016)
3
4
Created by Chip Huyen ([email protected])
5
CS20: "TensorFlow for Deep Learning Research"
6
cs20.stanford.edu
7
8
For more details, please read the assignment handout:
9
https://docs.google.com/document/d/1FpueD-3mScnD0SJQDtwmOb1FrSwo1NGowkXzMwPoLH4/edit?usp=sharing
10
"""
11
import os
12
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
13
import time
14
15
import numpy as np
16
import tensorflow as tf
17
18
import load_vgg
19
import utils
20
21
def setup():
22
utils.safe_mkdir('checkpoints')
23
utils.safe_mkdir('outputs')
24
25
class StyleTransfer(object):
26
def __init__(self, content_img, style_img, img_width, img_height):
27
'''
28
img_width and img_height are the dimensions we expect from the generated image.
29
We will resize input content image and input style image to match this dimension.
30
Feel free to alter any hyperparameter here and see how it affects your training.
31
'''
32
self.img_width = img_width
33
self.img_height = img_height
34
self.content_img = utils.get_resized_image(content_img, img_width, img_height)
35
self.style_img = utils.get_resized_image(style_img, img_width, img_height)
36
self.initial_img = utils.generate_noise_image(self.content_img, img_width, img_height)
37
38
###############################
39
## TO DO
40
## create global step (gstep) and hyperparameters for the model
41
self.content_layer = 'conv4_2'
42
self.style_layers = ['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv5_1']
43
# content_w, style_w: corresponding weights for content loss and style loss
44
self.content_w = None
45
self.style_w = None
46
# style_layer_w: weights for different style layers. deep layers have more weights
47
self.style_layer_w = [0.5, 1.0, 1.5, 3.0, 4.0]
48
self.gstep = None # global step
49
self.lr = None
50
###############################
51
52
def create_input(self):
53
'''
54
We will use one input_img as a placeholder for the content image,
55
style image, and generated image, because:
56
1. they have the same dimension
57
2. we have to extract the same set of features from them
58
We use a variable instead of a placeholder because we're, at the same time,
59
training the generated image to get the desirable result.
60
61
Note: image height corresponds to number of rows, not columns.
62
'''
63
with tf.variable_scope('input') as scope:
64
self.input_img = tf.get_variable('in_img',
65
shape=([1, self.img_height, self.img_width, 3]),
66
dtype=tf.float32,
67
initializer=tf.zeros_initializer())
68
def load_vgg(self):
69
'''
70
Load the saved model parameters of VGG-19, using the input_img
71
as the input to compute the output at each layer of vgg.
72
73
During training, VGG-19 mean-centered all images and found the mean pixels
74
to be [123.68, 116.779, 103.939] along RGB dimensions. We have to subtract
75
this mean from our images.
76
77
'''
78
self.vgg = load_vgg.VGG(self.input_img)
79
self.vgg.load()
80
self.content_img -= self.vgg.mean_pixels
81
self.style_img -= self.vgg.mean_pixels
82
83
def _content_loss(self, P, F):
84
''' Calculate the loss between the feature representation of the
85
content image and the generated image.
86
87
Inputs:
88
P: content representation of the content image
89
F: content representation of the generated image
90
Read the assignment handout for more details
91
92
Note: Don't use the coefficient 0.5 as defined in the paper.
93
Use the coefficient defined in the assignment handout.
94
'''
95
###############################
96
## TO DO
97
self.content_loss = None
98
###############################
99
100
def _gram_matrix(self, F, N, M):
101
""" Create and return the gram matrix for tensor F
102
Hint: you'll first have to reshape F
103
"""
104
###############################
105
## TO DO
106
return None
107
###############################
108
109
def _single_style_loss(self, a, g):
110
""" Calculate the style loss at a certain layer
111
Inputs:
112
a is the feature representation of the style image at that layer
113
g is the feature representation of the generated image at that layer
114
Output:
115
the style loss at a certain layer (which is E_l in the paper)
116
117
Hint: 1. you'll have to use the function _gram_matrix()
118
2. we'll use the same coefficient for style loss as in the paper
119
3. a and g are feature representation, not gram matrices
120
"""
121
###############################
122
## TO DO
123
return None
124
###############################
125
126
def _style_loss(self, A):
127
""" Calculate the total style loss as a weighted sum
128
of style losses at all style layers
129
Hint: you'll have to use _single_style_loss()
130
"""
131
###############################
132
## TO DO
133
self.style_loss = None
134
###############################
135
136
def losses(self):
137
with tf.variable_scope('losses') as scope:
138
with tf.Session() as sess:
139
# assign content image to the input variable
140
sess.run(self.input_img.assign(self.content_img))
141
gen_img_content = getattr(self.vgg, self.content_layer)
142
content_img_content = sess.run(gen_img_content)
143
self._content_loss(content_img_content, gen_img_content)
144
145
with tf.Session() as sess:
146
sess.run(self.input_img.assign(self.style_img))
147
style_layers = sess.run([getattr(self.vgg, layer) for layer in self.style_layers])
148
self._style_loss(style_layers)
149
150
##########################################
151
## TO DO: create total loss.
152
## Hint: don't forget the weights for the content loss and style loss
153
self.total_loss = None
154
##########################################
155
156
def optimize(self):
157
###############################
158
## TO DO: create optimizer
159
self.opt = None
160
###############################
161
162
def create_summary(self):
163
###############################
164
## TO DO: create summaries for all the losses
165
## Hint: don't forget to merge them
166
self.summary_op = None
167
###############################
168
169
170
def build(self):
171
self.create_input()
172
self.load_vgg()
173
self.losses()
174
self.optimize()
175
self.create_summary()
176
177
def train(self, n_iters):
178
skip_step = 1
179
with tf.Session() as sess:
180
181
###############################
182
## TO DO:
183
## 1. initialize your variables
184
## 2. create writer to write your grapp
185
###############################
186
187
sess.run(self.input_img.assign(self.initial_img))
188
189
###############################
190
## TO DO:
191
## 1. create a saver object
192
## 2. check if a checkpoint exists, restore the variables
193
##############################
194
195
initial_step = self.gstep.eval()
196
197
start_time = time.time()
198
for index in range(initial_step, n_iters):
199
if index >= 5 and index < 20:
200
skip_step = 10
201
elif index >= 20:
202
skip_step = 20
203
204
sess.run(self.opt)
205
if (index + 1) % skip_step == 0:
206
###############################
207
## TO DO: obtain generated image, loss, and summary
208
gen_image, total_loss, summary = None, None, None
209
###############################
210
211
# add back the mean pixels we subtracted before
212
gen_image = gen_image + self.vgg.mean_pixels
213
writer.add_summary(summary, global_step=index)
214
print('Step {}\n Sum: {:5.1f}'.format(index + 1, np.sum(gen_image)))
215
print(' Loss: {:5.1f}'.format(total_loss))
216
print(' Took: {} seconds'.format(time.time() - start_time))
217
start_time = time.time()
218
219
filename = 'outputs/%d.png' % (index)
220
utils.save_image(filename, gen_image)
221
222
if (index + 1) % 20 == 0:
223
###############################
224
## TO DO: save the variables into a checkpoint
225
###############################
226
pass
227
228
if __name__ == '__main__':
229
setup()
230
machine = StyleTransfer('content/deadpool.jpg', 'styles/guernica.jpg', 333, 250)
231
machine.build()
232
machine.train(300)
233