原理
利用的是设计好的VGG19网络模型,VGG19中的5个block,即卷积和池化操作,获得图片的特征,然后构建损失函数进行操作处理超参数,最终生成一张新的图像。
-
输入两张图片(内容图片和风格图片)
-
对图像进行处理,转换成tensor类型
-
将得到的tensor类型放入预训练好的VGG19模型进行处理
-
损失函数的计算,超参数的优化调整
-
生成新的图片内容图片的内容,(风格图片的风格)
照片的直观表示:
VGG19原理
VGG19网络模型分为5个block,总共19层,包括16层卷积层和最后的3层全连接层,由于在风格迁移中不需要进行相应的预测或分类,所以用不到最后的全连接层。因此主要运用到VGG19中5个block由浅入深的卷积操作得到特征图(宽高逐渐缩小,深度逐层增大),并且可以发现,内容图像在进行特征提取时,很大程度保留了原图的信息,但是风格图像基本看不出其特征提取后的特征图与原图内容上的相似性,可以认为是提取了特征。
损失函数设计
1.1 Loss函数的设计
本系统中有三个损失函数:
- 第一个是内容损失函数,通过生成图像G与内容图像C构建的损失函数,用于衡量生成图像与内容图像在内容上有多相似;
这里内容函数采用的是均方误差:
L
c
o
n
t
e
n
t
(
p
⃗
,
x
⃗
,
l
)
=
1
2
∑
i
,
j
(
F
i
j
l
−
P
i
j
l
)
2
L_{content}(\vec{p},\vec{x},l)=\frac{1}{2}\sum_{i,j}(F^{l}_{ij}-P^{l}_{ij})^{2}
Lcontent(p,x,l)=21i,j∑(Fijl−Pijl)2
p是原始内容图片特征图,x是生成图片特征图。即对于每一层,原始图片的特征图(feature map)和生成图片的特征图的一一对应做差值平方和。
- 第二个是风格损失函数:通过生成图像G与风格图像S构建的损失函数,用于衡量生成图像与风格图像在风格上的相似度;
首先需要利用Gram矩阵计算feature map之间的相似性来表示图像风格特征, Gram公式如下:
G
i
j
l
=
∑
k
F
i
k
l
F
j
k
l
G^{l}_{ij} = \sum_{k}F^{l}_{ik}F^{l}_{jk}
Gijl=k∑FiklFjkl
由于Gram的对角线元素提供了不同特征图各自的信息,而其余元素提供了不同特征图之间的相关信息,因此,Gram有助于把握整个图像的大体风格。有了表示风格的Gram矩阵,要度量两个图像风格的差异,只需比较他们Gram矩阵的差异即可。
然后,利用均方误差和归一化进行计算:
E t = 1 4 N 2 M l 2 ∑ i j ( G i j l − A i j l ) 2 E_{t} = \frac{1}{4N^{2}M^{2}_{l}\sum_{ij}(G^{l}_{ij}-A^{l}_{ij})^{2} } Et=4N2Ml2∑ij(Gijl−Aijl)21
上面是第l层的风格损失函数,N是指生成图feature map数量,M是图片宽乘高,G是生成图像的Gram矩阵,A是风格图像的Gram矩阵。
最后计算损失函数:
L
s
t
y
l
e
(
a
⃗
,
x
⃗
)
=
∑
l
=
0
L
w
t
E
t
L_{style}(\vec{a},\vec{x} )=\sum_{l=0}^{L}w_{t}E_{t}
Lstyle(a,x)=l=0∑LwtEt
- 第三个总的损失函数:用两个超参数α和β来衡量内容损失函数和风格损失函数之间的权重。
L t o t a l ( p ⃗ , a ⃗ , x ⃗ ) = α L c o n t e n t ( p ⃗ , x ⃗ ) + β L s t y l e ( a ⃗ , x ⃗ ) L_{total}(\vec{p},\vec{a},\vec{x})=\alpha L_{content}(\vec{p},\vec{x})+\beta L_{style}(\vec{a},\vec{x} ) Ltotal(p,a,x)=αLcontent(p,x)+βLstyle(a,x)
结果
展示效果:
利用python的tkinter生成一个gui界面,并且通过tkinter中的组件对代码中函数的调用。利用已经训练好的vgg19网络框架以及定义的损失函数构建模型,让模型对输入的图像进行200次训练,最后将得到的图片进行保存返回。具体的代码在本人博客资源中的“ 基于VGG的快速风格迁移-附着界面 ”