赞
踩
代码:https://github.com/MONI-JUAN/Tensorflow_Study/tree/master/TensorFlow/ch07-图像风格迁移
内容损失和风格损失
用途
利用内容损失还原图像内容;
利用封给说你是还原图像风格;
风格迁移:还原图像的时候还原令一张图像的风格。
原始图像风格迁移 对比 快速图像风格
原始:
L t o t a l ( p → , a → , x → ) L_{total}(\overrightarrow{p},\overrightarrow{a},\overrightarrow{x}) Ltotal(p ,a ,x ) 衡量 x → \overrightarrow{x} x 是否成功组合了 p → \overrightarrow{p} p 和 a → \overrightarrow{a} a 的风格,以 L t o t a l L_{total} Ltotal 为目标进行梯度下降迭代 x → \overrightarrow{x} x ,速度慢。
快速:
使用神经网络直接生成
x
→
\overrightarrow{x}
x
,速度快。
类型 | 损失定义 | 是否需要训练新网络 | 生成图像的方法 |
---|---|---|---|
原始 | 内容损失
L
c
o
n
t
e
n
t
L_{content}
Lcontent 风格损失 L s t y l e L_{style} Lstyle | 否,只需要预训练好的VGGNet | 利用损失,通过梯度下降计算合适的图像 |
快速 | 内容损失
L
c
o
n
t
e
n
t
L_{content}
Lcontent 风格损失 L s t y l e L_{style} Lstyle | 是,除了预训练好的VGGNet还需要训练图像生成网络 | 利用训练好的图像生成网络直接生成 |
百度云链接:https://pan.baidu.com/s/11t5Vs3GHryyF1EHwow0dkA
提取码:amka
新建一个文件夹models
,把七个model放进去
cubist.ckpt-done
denoised_starry.ckpt-done
feathers.ckpt-done
mosaic.ckpt-done
scream.ckpt-done
udnie.ckpt-done
wave.ckpt-done
eval.py:
def main():
#输出res的时候记录模型和原图的名字
name_model = FLAGS.model_file.split('/')[-1].split('.')[0]
name_img = FLAGS.image_file.split('/')[-1].split('.')[0]
'''
'''
generated_file = 'generated/res_[%s]_[%s].jpg' % (name_model, name_img)
model.py:
def conv2d(x, input_filters, output_filters, kernel, strides, mode='REFLECT'):
with tf.variable_scope('conv'):
shape = [kernel, kernel, input_filters, output_filters]
weight = tf.Variable(tf.truncated_normal(shape, stddev=0.1), name='weight')
# kernel 是float类型的,在新版本的tensorflow需要np.int()一下才行
x_padded = tf.pad(x, [[0, 0], [np.int(kernel / 2), np.int(kernel / 2)], [np.int(kernel / 2), np.int(kernel / 2)], [0, 0]], mode=mode)
return tf.nn.conv2d(x_padded, weight, strides=[1, strides, strides, 1], padding='VALID', name='conv')
python eval.py --model_file models/wave.ckpt-done --image_file img/test.jpg
例子中还有四个原始图
其中风格分别为:
cubist
denoised_starry
feathers
mosaic
scream
udnie
wave
这里列出了五张图片在七种模型下的所有结果
python eval.py --model_file models/wave.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/wave.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/wave.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/wave.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/wave.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/cubist.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/cubist.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/cubist.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/cubist.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/cubist.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/denoised_starry.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/denoised_starry.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/denoised_starry.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/denoised_starry.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/denoised_starry.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/feathers.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/feathers.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/feathers.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/feathers.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/feathers.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/mosaic.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/mosaic.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/mosaic.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/mosaic.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/mosaic.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/scream.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/scream.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/scream.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/scream.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/scream.ckpt-done --image_file img/test5.jpg python eval.py --model_file models/udnie.ckpt-done --image_file img/test1.jpg python eval.py --model_file models/udnie.ckpt-done --image_file img/test2.jpg python eval.py --model_file models/udnie.ckpt-done --image_file img/test3.jpg python eval.py --model_file models/udnie.ckpt-done --image_file img/test4.jpg python eval.py --model_file models/udnie.ckpt-done --image_file img/test5.jpg
下载VGG16模型
地址: http://download.tensorflow.org/models/vgg_16_2016_08_28.tar.gz
百度云链接:https://pan.baidu.com/s/11t5Vs3GHryyF1EHwow0dkA
提取码:amka
新建文件夹 pretrained
,把 vgg_16.ckpt
放进去
下载COCO数据集,有12.6G
地址: http://msvocds.blob.core.windows.net/coco2014/train2014.zip
解压放到文件夹 train2014
Linux可以不用移动,直接建立连接:
ln -s <到 train2014 文件路径> train2014
python train.py -c conf/wave.yml
其中 conf/wave.yml
是配置文件:
## Basic configuration style_image: img/wave.jpg # 输入原始风格图像的文件名 naming: "wave" # 风格/模型的名字 model_path: models # checkpoint 和 events 文件保存的根目录 ## Weight of the loss content_weight: 1.0 # 内容损失的权重 style_weight: 220.0 # 风格损失的权重 tv_weight: 0.0 # total variation loss ## The size, the iter number to run image_size: 256 # 原始图片的大小 batch_size: 4 # 一次 batch 的样本数 epoch: 2 # epoch 的运行次数 ## Loss Network loss_model: "vgg_16" # 使用 vgg_16 的模型 content_layers: # 使用 conv3_3 定义内容损失 - "vgg_16/conv3/conv3_3" style_layers: # 使用 conv1_2、conv2_2、conv3_3、conv4_3 定义风格损失 - "vgg_16/conv1/conv1_2" - "vgg_16/conv2/conv2_2" - "vgg_16/conv3/conv3_3" - "vgg_16/conv4/conv4_3" checkpoint_exclude_scopes: "vgg_16/fc" # 只需要卷积层,不需要fc层 loss_model_file: "pretrained/vgg_16.ckpt" # 预训练对应的位置
读者如果希望训练新的“风格”,可以选取一张风格图片,并编写新的 yml 配置文件。其中,需要把 style_image 修改为新图片所在的位置,并修改对应的 naming 。 这样就可以进行训练了。最后可以使用训练完成的 checkpoint 生成图片。
在训练 、新的“风格”时,有可能会需要调整各个损失之间的权重。
tensorboard --logdir models/wave/
但是因为数据集太大,一直都下不下来,这里就先放弃了。只看了看代码
有百度云资源的可以发一下!感激涕零!
models.py
def net(image, training): # 图片加上一圈边框,消除边缘效应 image = tf.pad(image, [[0, 0], [10, 10], [10, 10], [0, 0]], mode='REFLECT') # 三层卷积层 with tf.variable_scope('conv1'): conv1 = relu(instance_norm(conv2d(image, 3, 32, 9, 1))) with tf.variable_scope('conv2'): conv2 = relu(instance_norm(conv2d(conv1, 32, 64, 3, 2))) with tf.variable_scope('conv3'): conv3 = relu(instance_norm(conv2d(conv2, 64, 128, 3, 2))) # 仿照 ResNet 定义一些跳过的链接 with tf.variable_scope('res1'): res1 = residual(conv3, 128, 3, 1) with tf.variable_scope('res2'): res2 = residual(res1, 128, 3, 1) with tf.variable_scope('res3'): res3 = residual(res2, 128, 3, 1) with tf.variable_scope('res4'): res4 = residual(res3, 128, 3, 1) with tf.variable_scope('res5'): res5 = residual(res4, 128, 3, 1) # print(res5.get_shape()) # 定义反卷积,先放大再卷积可以消除噪声 with tf.variable_scope('deconv1'): # deconv1 = relu(instance_norm(conv2d_transpose(res5, 128, 64, 3, 2))) #不直接转置 deconv1 = relu(instance_norm(resize_conv2d(res5, 128, 64, 3, 2, training))) with tf.variable_scope('deconv2'): # deconv2 = relu(instance_norm(conv2d_transpose(deconv1, 64, 32, 3, 2))) #不直接转置 deconv2 = relu(instance_norm(resize_conv2d(deconv1, 64, 32, 3, 2, training))) with tf.variable_scope('deconv3'): # deconv_test = relu(instance_norm(conv2d(deconv2, 32, 32, 2, 1))) #不直接转置 deconv3 = tf.nn.tanh(instance_norm(conv2d(deconv2, 32, 3, 9, 1))) # 经过了 tanh 激活,将[-1,1]缩放到[0,255]像素值范围 y = (deconv3 + 1) * 127.5 # 去除边框 height = tf.shape(y)[1] width = tf.shape(y)[2] y = tf.slice(y, [0, 10, 10, 0], tf.stack([-1, height - 20, width - 20, -1])) return y
train.py
"""Build Network""" # 损失网络 network_fn = nets_factory.get_network_fn( FLAGS.loss_model, num_classes=1, is_training=False) # 不需要对损失函数训练 # 图像和与处理函数,不需要训练 image_preprocessing_fn, image_unprocessing_fn = preprocessing_factory.get_preprocessing( FLAGS.loss_model, is_training=False) # 读入训练图像 processed_images = reader.image(FLAGS.batch_size, FLAGS.image_size, FLAGS.image_size, 'train2014/', image_preprocessing_fn, epochs=FLAGS.epoch) # 引用生成网络,生成图像,这里需要训练 generated = model.net(processed_images, training=True) # 将生成图像使用 image_preprocessing_fn 处理 processed_generated = [ image_preprocessing_fn(image, FLAGS.image_size, FLAGS.image_size) for image in tf.unstack(generated, axis=0, num=FLAGS.batch_size) ] processed_generated = tf.stack(processed_generated) # 将原始图和生成图送到损失网络,加快速度 _, endpoints_dict = network_fn(tf.concat([processed_generated, processed_images], 0), spatial_squeeze=False) # Log the structure of loss network tf.logging.info('Loss network layers(You can define them in "content_layers" and "style_layers"):') for key in endpoints_dict: tf.logging.info(key)
loss.py
# endpoints_dict 是损失网络各层的计算结果
# content_layers 是定义使用哪些层的差距计算损失
def content_loss(endpoints_dict, content_layers):
content_loss = 0
for layer in content_layers:
generated_images, content_images = tf.split(endpoints_dict[layer], 2, 0)# 把生成图像分开
size = tf.size(generated_images)
# 生成图片的激活 与 原始图片的激活 的L^2距离
content_loss += tf.nn.l2_loss(generated_images - content_images) * 2 / tf.to_float(size)
return content_loss
loss.py
# endpoints_dict 是损失网络各层的计算结果
# style_features_t 是利用原始的风格图片计算的层的激活
# style_layers 是定义使用哪些层计算损失
def style_loss(endpoints_dict, style_features_t, style_layers):
style_loss = 0
style_loss_summary = {} # 为tensorboard服务的
for style_gram, layer in zip(style_features_t, style_layers):
generated_images, _ = tf.split(endpoints_dict[layer], 2, 0) # 计算风格损失
size = tf.size(generated_images)
# 计算 Gram 矩阵, L^2(Loss)
layer_style_loss = tf.nn.l2_loss(gram(generated_images) - style_gram) * 2 / tf.to_float(size)
style_loss_summary[layer] = layer_style_loss
style_loss += layer_style_loss
return style_loss, style_loss_summary
train.py
"""Build Losses"""
# 定义内容损失
content_loss = losses.content_loss(endpoints_dict, FLAGS.content_layers)
# 定义风格损失
style_loss, style_loss_summary = losses.style_loss(endpoints_dict, style_features_t, FLAGS.style_layers)
# 定义tv损失,但是因为tv_weight=0,所以没用
tv_loss = losses.total_variation_loss(generated)
# 总损失
loss = FLAGS.style_weight * style_loss + FLAGS.content_weight * content_loss + FLAGS.tv_weight * tv_loss
train.py
"""Prepare to Train""" global_step = tf.Variable(0, name="global_step", trainable=False) variable_to_train = [] # 找出需要训练的变量,append进去 for variable in tf.trainable_variables(): if not(variable.name.startswith(FLAGS.loss_model)): variable_to_train.append(variable) # 定义, global_step=global_step 不会训练损失网络 train_op = tf.train.AdamOptimizer(1e-3).minimize(loss, global_step=global_step, var_list=variable_to_train) variables_to_restore = [] # 找出需要保存的变量,append进去 for v in tf.global_variables(): if not(v.name.startswith(FLAGS.loss_model)): variables_to_restore.append(v) # 定义,只保存 variables_to_restore saver = tf.train.Saver(variables_to_restore, write_version=tf.train.SaverDef.V1) sess.run([tf.global_variables_initializer(), tf.local_variables_initializer()])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。