今天和大家分享的这篇论文是实验室一个小学妹正在研究的内容,之前也有过一些讨论,所以就趁着这个机会把论文翻出来和大家共享一下,有些不足之处还请大家多多指正。不了解Neural Style Transfer(NST) 的伙伴们可以结合我们之前专栏里的其他博客一起食用【专栏——深度学习与艺术】。这篇论文发表于2017年CVPR,是Cornell康奈尔大学和Adobe公司联合研究的,据说会在photoshop上加入这个应用(设计师的福音!!!,不过好像至今也没有上线?),不过先放上一张成果图大家来直观感受一下Deep Photo Style Transfer的效果⬇️。
此外,按照老规矩来感受一下大神作者们⬇️的超高能力!
我们就来fellow一下一作吧,Fujun Luan【个人主页】,中国清华大学毕业,在康奈尔大学留学,是Graphics and Vision Group组的PhD,2017年在Adobe Research做实习生,2020年收到了Facebook Reality Labs的实习生offer,大神的实力果真令人瑟瑟发抖。
Paper:Deep Photo Style Transfer
Code:【Torch implementation】(这是原作者公布的代码,up to 9.5k stars)),【TensorFLow implementation】
本文介绍了一种用于摄影风格转换的深度学习方法,该方法可处理多种图像内容,同时忠实地传递参考风格。 我们的方法基于最近的绘画转移工作,该工作通过考虑神经网络的不同层来将样式与图像内容分开。 但是,按原样,此方法不适用于逼真的样式转换。 即使输入图像和参考图像都是照片,输出仍会呈现出画作的失真。 我们的贡献是限制从输入到输出的转换在色彩空间中是局部仿射的,并将此约束表示为自定义的完全可微分的能量项。 我们证明了这种方法可以在多种情况下成功地抑制失真并产生令人满意的逼真的样式转移,包括一天中时间,天气,季节和艺术编辑的转移。(附上原文)
This paper introduces a deep-learning approach to photographic style transfer that handles a large variety of image content while faithfully transferring the reference style. Our approach builds upon the recent work on painterly transfer that separates style from the content of an image by considering different layers of a neural network. However, as is, this approach is not suitable for photorealistic style transfer. Even when both the input and reference images are photographs, the output still exhibits distortions reminiscent of a painting. Our contribution is to constrain the transformation from the input to the output to be locally affine in colorspace, and to express this constraint as a custom fully differentiable energy term. We show that this approach successfully suppresses distortion and yields satisfying photorealistic style transfers in a broad variety of scenarios, including transfer of the time of day, weather, season, and artistic edits.
Introduction的部分就不详细介绍了,主要是作者做了一下NST的review和本篇论文想解决的问题是什么,作者在Introduction中提到了对于相片的风格转化主要面临着两个问题:
根据这两个问题,我们来看一下提出的方法。同大多数的NST算法一样,模型的输入需要一张风格图像和一张内容图像,想得到的是一张具有风格化的内容图像。我们的方法通过引入两个核心思想(与问题是一一对应的) 来增强神经风格算法。
下图是Neural Style在优化过程中的损失函数, L t o t a l L_{total} Ltotal是总损失, L c L_{c} Lc是内容损失Content Loss, L s L_{s} Ls是风格损失Style Loss; F l F_{l} Fl是某一层卷积的特征矩阵Feature Matrix, G l G_{l} Gl是根据特征矩阵计算的Gram Matrix。这样在优化的过程中,基于 α l \alpha_{l} αl和 β l \beta_{l} βl可以得到内容图像和风格图像的tradeoff。
【解决结构保留问题】 这个策略不是直接在输出图像上添加约束来表示,而是在作用到输入图像的变换上。我们的策略是在风格转移的过程中,通过添加一个与图像扭曲相关的惩罚项,确保不会丢失其属性。我们的方案是寻找一个色彩空间的图像局部仿射变换。对于每一个输出区块,存在一个仿射函数将输入图像的RGB值映射到对应的输出对应的位置上去。每个区域的仿射函数都不同,随空间变化。具体可以参考论文:A closed-form solution to natural image matting。
【解决语义精度和迁移保真度问题】 我们知道Gatys提出的Neural Style Transfer的成功之处在于利用Gram Matrix来平衡风格和内容图像之间的差异,但是这样基于整张图像的计算存在一定的缺陷,没有办法约束各层Feature Map的生成,从而造成语义的变化和溢出。我们利用Neural Doodle和生成分割mask的Semantic Segmentation方法中的思想来解决这一问题。在代码中提供了至多九种颜色的分割mask(某一颜色的mask图像虽然为3通道,但是处理为单通道图像)可供选择。Augmented style loss增加的风格损失如下,其中,C表示的是分割mask的通道总数(就是用了几种颜色的mask)。
基于上述的Background和Core ideas,提出了Deep photo style transfer的方法,总体的损失如下, L t o t a l L_{total} Ltotal是总损失, L c l L_{c}^l Lcl是内容损失Content Loss, L s + l L_{s+}^l Ls+l是增加的风格损失Augmented Style Loss, L m L_{m} Lm是图像真实感正则化损失Photorealism regularization,其中, l l l指的是某一层卷积层,对于内容损失选取conv4_2
作为内容特征表示,对于风格损失选取conv1_1,conv2_1,conv3_1,conv4_1,conv5_1
这些层作为风格特征表示。
因为图像文件大小的限制,只截取了一部分的结果作为案例来感受一下Deep photo style transfer的效果,整体来说还是很不错的,性能超过Neural Style、CNNMRF等算法,并且没有语义上的扭曲,能够大体保证语义的完整性。
论文中也给出不同的区域标注不同的seg mask做不同风格迁移的结果,如上图,效果还是很不错的。
因为我不太用torch,所以就和大家分享一下Tensorflow版本的代码吧【TensorFLow implementation】。
需要安装的包和下载的vgg预训练模型在Set中有列出,训练的基本的用法:
python deep_photostyle.py --content_image_path <path_to_content_image>
--style_image_path <path_to_style_image>
--content_seg_path <path_to_content_segmentation>
--style_seg_path <path_to_style_segmentation>
--style_option 2
主文件是deep_photostyle.py
,提供了三种style_option的模式,option 0是生成分割
的中间结果,option 1是利用分割的中间结果来生成最终的结果,option 2是…一步到位,一般来说选择option 2就可以了。
一些比较重要的函数的定义在photo_style.py
文件中,例如content loss,style loss,gram matrix等等。
Content loss就是计算:权重*一个像素平方差的均值:
tf.reduce_mean(tf.squared_difference(const_layer, var_layer)) * weight
Style loss计算步骤:计算风格层的Gram Matrix的平方差的均值,并且乘上mask的均值,形成diff_style_sum;将不同层的diff_style_sum求和形成layer_style_loss,再乘以权重得到Style loss。
diff_style_sum = tf.reduce_mean(tf.squared_difference(gram_matrix_const, gram_matrix_var)) * content_mask_mean
layer_style_loss += diff_style_sum
其中,Gram Matrix的计算如下,activations可以理解为从卷积某一层抽取的Feature Map,是一个4维的数组(batchsize, height, width, channels)
,其中batchsize=1,所以最后得到的gram matrix是一个2维的数组。
def gram_matrix(activations):
height = tf.shape(activations)[1]
width = tf.shape(activations)[2]
num_channels = tf.shape(activations)[3]
gram_matrix = tf.transpose(activations, [0, 3, 1, 2])
gram_matrix = tf.reshape(gram_matrix, [num_channels, width * height])
gram_matrix = tf.matmul(gram_matrix, gram_matrix, transpose_b=True)
return gram_matrix
Deep Photo Style Transfer就分享到这里啦,有理解不到位的地方请伙伴们多多指正,感恩大家一路的支持~