风格迁移

风格转换

风格转换就是将现实的图片转换成带有艺术风格的照片,比如把你自己的照片转换成梵高的星空风格等等 这样人人都可以变成梵高了,可以进行你想要的艺术创作。

Gatys于2015年提出了一篇论文,A Neural Algorithm of Artistic Style,实现了基于深度学习的艺术风格转换, 这是真正意义上的第一篇深度学习实现艺术风格转换的论文,后来又出现了很多更优秀的论文,转换速度更快,效率和质量更好。 但是很多都是基于这篇论文的。因此下面我将详细的解读这篇论文,以及在pytorch上实现相关代码,代码参考pytorch官网。

网络的选择

关于网络结构的选择,作者进行了相关的分析,主要采用卷积神经网络,这也无可厚非,毕竟卷积神经网络在处理图像, 提取特征方面有着巨大的优势,卷积网络除此之外还有几个特点:

  • 低层次的网络提取边缘和基础的轮廓特点
  • 高层次的网络提取更加复杂的特征
  • 网络的更高层捕捉了物体在高层的内容和在输入图片的应用,但是不含重构的精确的像素值

总之,随着卷积网络的深入,网络越来越关注更加实际的内容,而忽略像素值,因为需要保存更高层次的内容。

论文中具体采用的是VGG-19网络,去掉了最后的全连接层,只是用了16层卷积和5个池化层,关于池化层, 作者用平均池化代替了最大池化,因为实际操作来看,这样的效果更佳。

效果的查看

这里的效果查看主要指的是查看网络层的内容和风格重建情况,并且可视化,这样才能直观的看出是否真的提取到了特征 还是内容。

如上图所示,论文给出了VGG网络5层中的内容重建和风格重建情况,从内容重建可以看出, 底层的特征激活图还是可以轻松重建原图的,但是高层的就很难做到了,正如前面所说,他丢弃了像素值,为了保存更高层次的内容。 再看风格重建,风格表示部分先简单提一下,后面会具体说到,注意到它是越来越大的,这是因为Gram矩阵是越来越大的,随着卷积核的数量增加而增加, 然后根据风格表示重建的风格可以看出,低层次重建的风格规模很小,高层次的风格规模变大。 沿着处理的层次,输入图片局部的图片结构的大小和复杂性增加,这可以解释为增长的感受野的大小和特征的复杂性。 所以论文使用了多规模尺度的呈现作为风格表达。而相比之下,内容重现则只选择一层即可。

论文贡献

本篇论文的最主要贡献还是实现了风格和内容的分离,他证明了风格和内容是可以独立的进行操作的。 因此才有了这篇论文的主题—进行风格转换。 因为是可分离的,所以我们可以把一张图片的内容和另一张图片的风格结合起来,这样就创造了前面说的艺术画。

如图所示,这些就是风格转换的效果,A是原图,下面的图的左下角是风格图,主体就是转换后的图。 可以看到效果很好,每张图既保留的内容也加入了艺术的风格。

权重的设置和风格的尺度

当然,图片内容和风格不能被完全分离.当合成一张结合了某张图片的内容和另一张图片的风格时, 通常不存在一个图片能同时完美的匹配这两张图片.然而,这个我们在合成过程中要最小化的loss函数 包含了我们很好分离开的两个方面,内容和风格.因此我们可以平滑地调节在重构内容或者是风格时的重点。 着重强调风格产生的图片可以匹配艺术作品的表现,实际上也就是给了一个纹理化的版本,但是几乎不能表现任何照片的内容. 当把比重放在内容上时,结果可以很清晰得确认到照片,但是画作的风格就不能很好地匹配。 对于一特定的源图片我们可以调节在内容和风格间的协调来产生视觉上有感染力的图片

如图所示,我们从行和列分开来看。

  • 先从列开始看

从上往下,它们的区别是风格的尺度不同,也就是说风格表示的尺度不同, 第一行只用了conv1_1的的风格表示来表示整个的风格损失,第二行加入conv2_1,以此类推, 可以看到最后一行融合了5个风格表示,风格表示的效果也最好,因此论文也采用这样方法, 也就是前面提到的多尺度表示风格。

  • 从行开始看

从左往后,区别是权重的设置不同,权重是风格的权重和内容的权重,第一列内容权重和风格权重之比为10-5, 意味着风格的权重是内容的100000倍,网络十分看重风格,因此忽略了内容,可以看到几乎看不出原图的痕迹。 随着比值的缩小,风格所占比重变小,内容越来越被关注,最后一列中可以看到,风格和内容达到了很好的平衡。 10-3也是常用的一个比值,包括我的代码中也是这个数字。

具体方法

下面开始具体说明方法,以及损失的含义和表示。 事实上网络的每一层都定义了一个非线性的过滤器组,它的复杂性随着在网络中所在层的位置而增加. 因此一个给定的输入图片x在CNN的每一层的编码的过滤器是响应图片的.一个有着Nl个不同的过滤器的层有Nl个特征图谱, 每个图谱的大小Ml,Ml是特征图谱的长与宽的乘积.所以对于层L的响应可以被存储在矩阵中Fl中, Fij表示第i个过滤器在层L中的第j个位置的激活.为了可视化由不同层次编码的图片信息。 我们对一个白噪声图片进行坡度下降来找到另外一张可以匹配原图的特征反应的图片。

内容损失就是我们要最小化白噪声图片和原始图片在某一层上的激活图的方差即可。为什么是一层就行了? 前面已经提到过,内容一般在前几层被表示,后面的层次表达更高级的内容,也可以说是特征。所以一般取一层就够了, 而风格表示则需要取多尺度,就像前面的图中表示的一样。 因此内容损失定义如下:

p是原始图片,x是白噪声图片,P和X未对应的激活图。

Gram 矩阵

论文用Gram矩阵表示风格,利用两个Gram矩阵的均方差表示风格的损失,那么Gram矩阵是什么? 先给出定义。

解释一下,其中的Gream的尺寸为C* C,也就是l层激活图的通道数乘以通道数。为每一个Gij就是 第i个卷积核的激活图和第j个卷积核激活图的内积,算出来是一个数值。 为什么它可以表示风格呢?因为他不仅可以表示自己的特征在原始图中出现的量,还可以表示不同特征之间的相关性, 相关性包括同增减,此消彼长之类,我们就称之为它把握了风格。

因此风格损失的计算就很明确了,不同层次卷积核的激活图的Gram矩阵的均方误差。

上面计算的是L层的风格损失。

上式计算的是各个层的风格损失之和,wl是特定层的贡献度,一般采用5层的话,就取5分之一, 采用几层就取几分之一,意思是每层的风格损失贡献一样。那么其它层就取0,比如VGG-19,论文风格损失 只采用的conv1_1,conv2_1,conv3_1,conv4_1,conv5_1,因此这几层wl取1/5,其他像conv1_2,conv2_2,conv3_2之类的 因为没用到,所以都取0。

所以总的损失就如下所示:

其中的alpha和beta就是前面说的权重,一般取alpha/beta 为10-3左右。

效果展示

具体代码参考我的github

下面给出代码运行的效果,推荐使用GPU加速,本人首先在没有GPU的Ubuntu上跑此代码大约4-5个小时,后来用了GPU只需要2分钟不到。 初始的内容图片为:

风格图片为:

输出转换后的效果为:

换成梵高星空的风格图和转换后的图如下:

最后在自己的照片上实现一波: