# 风格转换

1. 将风格转换变成优化问题的求解，构建T,C$T,C$之间的损失Lc$L_c$以及T,S$T,S$之间的损失Ls$L_s$，同时增加图片平滑的损失Lv$L_v$。通过求解minTiLi$\min_T \sum_i L_i$的优化问题求解。
2. 不直接把目标图片T$T$当做求解变量，而是构建一个transform network把内容图片C$C$转化成目标图片T$T$，以类似1中的方法构建损失函数，通过求解transform network的参数求解该问题。

# 优化问题

## 综述

• Ls$L_s$T$T$S$S$风格上的距离
• Lc$L_c$T$T$C$C$内容上的距离
• Lv$L_v$T$T$不平滑的度量

minTαsLs(T,S)+αcLc(T,C)+αvLv(T)

## 损失函数

Lc(Tl,Cl)=||TlCl||

Ls(Tl,Sl)=||G(Tl)G(Sl)||

Lv(T)=||TT1||+||TT1||

## 训练

minTαsLs(T,S)+αcLc(T,C)+αvLv(T)

## 代码

from __future__ import print_function

import time
from PIL import Image
import numpy as np

from keras import backend
from keras.models import Model
from keras.applications.vgg16 import VGG16

from scipy.optimize import fmin_l_bfgs_b
from scipy.misc import imsave

# Load and preprocess the content and style images
height = 512
width = 512

content_image_path = 'images/hugo.jpg'
content_image = Image.open(content_image_path)
content_image = content_image.resize((height, width))
content_image

style_image_path = 'images/styles/wave.jpg'
style_image = Image.open(style_image_path)
style_image = style_image.resize((height, width))
style_image

content_array = np.asarray(content_image, dtype='float32')
content_array = np.expand_dims(content_array, axis=0)
print(content_array.shape)

style_array = np.asarray(style_image, dtype='float32')
style_array = np.expand_dims(style_array, axis=0)
print(style_array.shape)

content_array[:, :, :, 0] -= 103.939
content_array[:, :, :, 1] -= 116.779
content_array[:, :, :, 2] -= 123.68
content_array = content_array[:, :, :, ::-1]

style_array[:, :, :, 0] -= 103.939
style_array[:, :, :, 1] -= 116.779
style_array[:, :, :, 2] -= 123.68
style_array = style_array[:, :, :, ::-1]

content_image = backend.variable(content_array)
style_image = backend.variable(style_array)
combination_image = backend.placeholder((1, height, width, 3))

input_tensor = backend.concatenate([content_image,
style_image,
combination_image], axis=0)

# Reuse a model pre-trained for image classification to define loss functions
model = VGG16(input_tensor=input_tensor, weights='imagenet',
include_top=False)
layers = dict([(layer.name, layer.output) for layer in model.layers])

content_weight = 0.025
style_weight = 5.0
total_variation_weight = 1.0

# Loss
loss = backend.variable(0.)
# The content loss
def content_loss(content, combination):
return backend.sum(backend.square(combination - content))

layer_features = layers['block2_conv2']
content_image_features = layer_features[0, :, :, :]
combination_features = layer_features[2, :, :, :]

loss += content_weight * content_loss(content_image_features,
combination_features)
# The style loss
def gram_matrix(x):
features = backend.batch_flatten(backend.permute_dimensions(x, (2, 0, 1)))
gram = backend.dot(features, backend.transpose(features))
return gram
def style_loss(style, combination):
S = gram_matrix(style)
C = gram_matrix(combination)
channels = 3
size = height * width
return backend.sum(backend.square(S - C)) / (4. * (channels ** 2) * (size ** 2))

feature_layers = ['block1_conv2', 'block2_conv2',
'block3_conv3', 'block4_conv3',
'block5_conv3']
for layer_name in feature_layers:
layer_features = layers[layer_name]
style_features = layer_features[1, :, :, :]
combination_features = layer_features[2, :, :, :]
sl = style_loss(style_features, combination_features)
loss += (style_weight / len(feature_layers)) * sl
# The total variation loss
def total_variation_loss(x):
a = backend.square(x[:, :height-1, :width-1, :] - x[:, 1:, :width-1, :])
b = backend.square(x[:, :height-1, :width-1, :] - x[:, :height-1, 1:, :])
return backend.sum(backend.pow(a + b, 1.25))

loss += total_variation_weight * total_variation_loss(combination_image)

# Define needed gradients and solve the optimisation problem
outputs = [loss]
f_outputs = backend.function([combination_image], outputs)

x = x.reshape((1, height, width, 3))
outs = f_outputs([x])
loss_value = outs[0]

class Evaluator(object):

def __init__(self):
self.loss_value = None

def loss(self, x):
assert self.loss_value is None
self.loss_value = loss_value
return self.loss_value

assert self.loss_value is not None
self.loss_value = None

evaluator = Evaluator()

# Train
x = np.random.uniform(0, 255, (1, height, width, 3)) - 128.

iterations = 10

for i in range(iterations):
print('Start of iteration', i)
start_time = time.time()
x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x.flatten(),
print('Current loss value:', min_val)
end_time = time.time()
print('Iteration %d completed in %ds' % (i, end_time - start_time))

# Evaluation
x = x.reshape((height, width, 3))
x = x[:, :, ::-1]
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
x = np.clip(x, 0, 255).astype('uint8')

Image.fromarray(x)

# 网络转换

## 结构

• 每来一张新图片，都需要重新求解优化问题。如果需要将大量图片转换成同一风格的话效率会很低

## 训练

ŷ minw=fW(x)αsLs(ŷ ,ys)+αcLc(ŷ ,yc)+αvLv(ŷ )

# 参考

• 本文已收录于以下专栏：

## 可视化CNN卷积神经网络-- 之一

• u012968002
• 2016年08月16日 19:38
• 1451

## CNTK API文档翻译(19)——艺术风格转变

• zxhm001
• 2017年09月03日 19:29
• 429

## 【Deep Learning】YOLO_v1 的 TensorFlow 源码分析

• qq_34784753
• 2017年12月14日 20:32
• 633

• xiuyuxuanchen
• 2016年11月13日 14:39
• 479

## 基于深度学习的图像风格转换

• u013805360
• 2017年06月21日 13:35
• 2585

## 图像处理（九）人物肖像风格转换-Siggraph 2014

• hjimce
• 2015年05月06日 12:25
• 5097

## layerUI+Ajax打开页面执行操作后关闭问题

layerUI+Ajax打开页面执行操作后关闭问题
• qq_36476972
• 2017年05月06日 11:10
• 363

## Keras文档翻译--2.FAQ

1.我该怎样引用Keras？ 如果Keras在你的研究中起到了作用，请在你的公开发表作品中以如下形式引用Keras： @misc{chollet2015keras,  author = ...
• wenwu2016
• 2016年02月17日 15:16
• 2235

## 图片风格转换（附TensorFlow代码）

• hwj_wayne
• 2017年10月18日 22:39
• 628

## 基于tensorflow实现图像风格的变换

Leon A. Gatys, Alexander S. Ecker, 和 Matthias Bethge 等人的论文“A Neural Algorithm of Artistic Style”开...
• sparkexpert
• 2017年04月15日 20:53
• 1574

举报原因： 您举报文章：风格转换简介 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)