超越fast style transfer----任意风格图和内容图0.1秒出结果

    xiaoxiao2021-03-25  81

    如果不知道风格转换的,移步 http://blog.csdn.net/hungryof/article/details/53981959 ,瞄上一眼再回来。

    1. 以前风格转换速度之尴尬

    如果从得到效果图速度来分的话,可以分为三个阶段。

    阶段一

    最初的用神经网络实现的风格转换是需要不断迭代的,不仅速度慢,而且我要在A图加上B图的风格,就需要分别根据这两幅图进行不断前反向传播,更新输入,效率实在太低。称之为style transfer

    阶段二

    后来人们就想能不能直接一个前向传播搞定啊~,然后他们想出了,先训练一个 G , 这个G可以让输入 I 通过G后得到的 G(I) 是A图加上B图的风格。这个方法还是有很大的问题,那就是我训练的G必须是同一种风格,一般就用一幅风格图B,然后用很多的内容图,不断优化训练G, 最终G有啥用啊,只是“B风格的滤镜”罢了。那我要很多种风格呢?我就要训练很多很多的G,那挺尴尬的。. 代表论文是是 http://blog.csdn.net/hungryof/article/details/53981959 中提到的 Texture Networks: Feed-forward Synthesis of Textures and Stylized Images 和 Perceptual Losses for Real-Time Style Transfer and Super-Resolution . 这也就是网上经常说的 fast style transfer.

    阶段三

    大家就想,我怎么直接输入任意A和B,一次前向出来呢?如果能成功,那么速度就不需要考虑了,因为已经到达顶峰了。 style-swap 就是第三阶段的开始。 0.1秒出结果。

    2. Style-swap的魅力

    效果还是挺不错的嘛~~再放几张。。

    用上面素描画形成的效果:

    别问这人是谁,一个好友的qq头像,有较多的纹理,就直接拿过来试了试效果。。

    3. style-swap浅谈

    论文分为2个部分,第一部分就是常规的迭代方式,第二个是将常规的改成一次前向的方法。

    3.1 style-swap的新方法

    以前不都是认为Gram操作就是相当于“风格”的一种表示嘛,他们认为,如果我要得到C图的内容加上S图的风格,那么我希望我的网络输入 I 在高维度特征ϕ(I)(一般用VGG19的某一层的相应的输出,作为 I 的高维特征)与C图的高维特征ϕ(C)尽量一样,同时希望 ϕ(I) 进行Gram计算后得到的 G(ϕ(I)) G(ϕ(S)) 尽量一样。为什么要用Gram矩阵呢?是否有必要?这些都不知道。 后来Chuan Li的 Combining Markov Random Fields and Convolutional Neural Networks for Image Synthesis将Style loss改成了MRFs Loss Function,依旧保留content loss。这篇论文第一部分工作其实就单纯用第一种loss了,舍弃了content loss。 这篇论文的详细讲了计算这种Loss的高效方法。这篇论文的主要贡献还是第二部分工作,引入了Inverse Net,这使得一次前向传播得到的特征图成为可能。

    3.2 实现方法

    C S分别代表内容图和风格图, ϕ() 代表预训练网络(一般VGG19)的前部分网络。 ϕ(C) 就是 C 传入网络中在某一层出来的特征。

    先提取一系列块ϕi(C) ϕj(S) 。其中 inc , jns ,其中 nc ns 分别是能从 ϕi(C) ϕj(S) 抽取的块数。

    对于每块 ϕi(C) ,我们希望选择其最近的style 块 ϕj(S) , 称之为 ϕssi(C,S) . ϕssi(C,S):=ARGMAXϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕi(C)||||ϕj(S)|| 这步称之为重建 Φss(C,S) 。这时候我们只需要平均一下那些重叠区域的值就行了。这样就可以得到 Φss(C,S) ,称之为 Φss(C,S) 的重建。

    因此总的优化目标是:

    Istylized(C,S)=ARGMINIRh×w×d||Φ(I)Φss(C,S)||2F+λTV(I)

    3.3 高效方法

    这里可能会写的比较啰嗦。。因为要讲的很明白,确实需要啰嗦点。。为了简便,提取的块spatial size就3x3吧, relu3_1层是256个通道。下面的三步统称为style-swap.

    3.3.1 实现方法的第一二步解释

    先看看3.2节实现方法的第一二步干啥:

    ϕssi(C,S):=ARGMAXϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕi(C)||||ϕj(S)|| 对于每一块 ϕi(C) ,从 ns ϕj(S) 中找到与其最匹配的块,称之为 ϕssi(C,S) 。最终我们可以找到 nc ϕssi(C,S) 。 可以发现 <ϕi(C),ϕj(S)> <script id="MathJax-Element-41" type="math/tex"><\phi_i(C),\phi_j(S)></script>是相关操作,也是卷积网络中说的卷积,对于某一块 ϕi(C) ,其和 ns 块分别进行相关,不就是将这 ns 块看成 ns 个卷积核,每个卷积核就是 ϕj(S) (大小是 256×3×3 )。输入是 ϕi(C) , 最终输出是 ϕi(C) ns 个卷积核卷积后的输出,大小为 ns×1×1 。总共有 nc ϕi(C) ,恰恰对应这卷积核在 Φ(C) 上的位置的所有情况,就是卷积核在 Φ(C) 上的卷积操作的移动恰恰就能满足这样。

    3.3.2 高效方法的第一步

    结论:用 Φ(C) 作为输入, ns ϕj(S)ϕj(S) 作为卷积核( ns×256×3×3 )。得到的输出就是所有的 i=1,,nc ϕi(C) 所对应的

    ϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕj(S)|| 论文的写法更为简便: Ka,b,j=ϕa,b(C),ϕj(S)ϕi(S) 输出的大小为: ns×w×h , 显然 w×h 等于 nc 。为了计算速度,省略了 ϕi(C) , 因为这不会影响取哪一个最近style块。 该步称之为 swap_enc。

    3.3.3 高效方法的第二步

    第一步得到的输出 O 到底是什么?记Oa,b O 中以(a,b)为中心点的 ns *1*1大小的输出张量,那么 Oa,b,j ϕa,b(C) ϕj(S) 的卷积的值。因此我们对于每个位置 (a,b) 如果第 j 个通道的值是ns个值中最大的,将该位置记为1,其他 ns1 个通道记为0. 这样就选出了块 ϕi(C) 对应的最匹配的块 ϕj(S) j 值!

    K¯¯¯a,b,j={1,0,if j=argmaxjKa,b,j otherwise 没错,第二步就是通道最大值记录为1,其余为0。 实现结束高效方法的第一第二步,我们要的就是 K¯¯¯ 。 该步称之为Maxcoord

    3.3.4 高效方法的第三步

    K¯¯¯ 作为输入,将 ϕj(S) 作为反卷积核。显然反卷积核与刚才的一样,也是 ns×256×3×3 。 对于每个位置 (a,b) , 只有最匹配的style块才会输出,其他的块都被乘上了0!此时就可以得到 ϕssa,b(C,S) ,比如与 ϕ10,10(C) 相关程度最大的块是第200块,即 max{O10,10,j} 的值为 O10,10,200 ,得到 K¯¯¯10,10,200=1 , 同时 K¯¯¯10,10,j=0,j200 K¯¯¯10,10,j ϕ(S) 反卷积,此时可以提取出 ϕssa,b(C,S) ,就是 ϕ200(S) 。直到这里我们才弄好了所有的 ϕssa,b(C,S) , 反卷积后这些 ϕssa,b(C,S) 是重叠的,重叠部分取平均即可。 此时才真正得到 Φss(C,S) 。 这一步称之为swap_dec。

    4. 训练Inverse网络

    这是第二部分内容,是核心部分。回忆第一部分的优化目标:

    Istylized(C,S)=ARGMINIRh×w×d||Φ(I)Φss(C,S)||2F+λTV(I) 我们希望该Inverse网络 f 无论对于任何输入H (这些输入包括 Φ(C) 或是 Φ(S) 或是 Φss(C,S) ), 我们都能使得f(H)能得到 Istylized(C,S) 。 即 Φ(f(H)) H 尽量一样。因此有: arginff=EH[Φ(f(H))H2F λ(f(H))]

    值得注意的是,如果我们训练好Inverse网络,称之为decoder, 然后进行前向传播是,首先是 Φ(C) 经过style-swap结构后得到 Φss(C,S) ,再输入到decoder中,即可得到 Iˆstylized(C,S)

    至此, 彻底完成一次前向传播出结果的目标!!!!!

    4.1 训练时代码的细节

    在训练时,

    Enc(4,256,64,64)latent_beforeswapLoss(8,256,64,64)latent_after(8,256,64,64)recons_latentdec(8,3,256,256)recons_inputEnc 比如我一下子输入2个content图和2个style图,然后latent_before是(4, 256, 64, 64),经过swap结构,得到latent_after是(8,256,64,64)。注意的是latent_after的前4个仍旧是latent_before, 而后4个是 Φss(C,S) 。更加准确的说: latent_before[1]和latent_before[2]是 Φ(C1)Φ(C2) ,而latent_before[3]和latent_before[4]是 Φ(S1)Φ(S2) 。 然后传入swap中,得到latent_after,latent_after[1:4]与latent-before一致,latent_after[5:8]分别为 Φ(C1,S1),Φ(C1,S2),Φ(C2,S1),Φ(C2,S2) 。得到的Loss是MSE(latent_after, recons_latent)。具体的含义见下图 Enc[Φ(C),Φ(S)]swapLoss[Φ(C),Φ(S),Φss(C,S)][Φ(f(Φ(C))),Φ(f(Φ(S))),Φ(f(Φss(C,S)))]Dec[f(Φ(C)),f(Φ(S)),f(Φss(C,S))]Enc 因此我们当然是希望 Φ(f(Φ(C))) Φ(C) 尽量接近, Φ(f(Φ(S))) Φ(S) 尽量接近, Φ(f(Φss(C,S)) Φss(C,S) 尽量接近,这样才能实现对于 Φ 的反转!

    为什么是用 [Φ(C),Φ(S),Φ(C,S)] [Φ(f(Φ(C))),Φ(f(Φ(S))),Φ(f(Φss(C,S)))] 进行求Loss,再反向传播呢?

    为了方便,直接说为什么是用 Φ(C,S) Φ(f(Φss(C,S))) 。其实我们希望优化Dec,那么最好是希望 f(Φ(C,S)) C 在高层语义上尽量一样。高层语义自然要将f(Φ(C,S)) C 进行升维,所以把f(Φ(C,S))再次输入到 Φ 中,与 Φ(C) 相比,用MSE就行了。 其实这种思想和fast neural style是类似的,或是可以看成是fast neural style的升级版本。fast neural style使用 G 网络生成G(x),使用 D 网络提供Loss形式。希望在高层语义特征上D(G(x)) D(C) 尽量接近,同时希望在高层语义上 Gram(D(G(x))) Gram(D(S)) 尽量接近。那么style-swap也是如此。Enc就是D,而Dec就是G。不过更加准确的说Dec不仅仅是G,而是G的升级版,因为以前的G只是针对一种style进行训练,而这里的Dec是针对大量的style一起训练。

    附录: Fast Patch-based Style Transfer of Arbitrary Style

    转载请注明原文地址: https://ju.6miu.com/read-20312.html

    最新回复(0)