第八章 图像风格迁移实战

简介:本章基于卷积神经网络实现图像风格迁移(Style Transfer)。和之前基于卷积神经网络的图像分类有所不同,这次是神经网络与艺术的碰撞。
1.风格迁移入门
图像风格迁移算法的实现逻辑并不复杂:
首先选取一幅图像作为基准图像,也可以将其叫作内容图像,然后选取另一幅或多幅图像作为我们希望获取相应风格的图像,也可以叫作风格图像。图像风格迁移的算法就是在保证内容图像的内容完整性的前提下,将风格图像的风格融入内容图像中,使得内容图像的原始风格最后发生了转变,最终的输出图像呈现的将是输入的内容图像的内容和风格图像风格之间的理想融合。
风格迁移实现的难点就是如何有效的提取一张图像的风格。
和传统的图像风格提取方法不同,我们在基于神经网络的图像风格迁移算法使用卷积神经网络来完成对图像风格的提取(提取图像特征)。
2.PyTorch图像风格迁移实战
首先,我们需要获取一张内容图片和一张风格图片;然后定义两个度量值,一个度量叫作内容度量值,另一个度量叫作风格度量值,其中的内容度量值用于衡量图片之间的内容差异程度,风格度量值用于衡量图片之间的风格差异程度;最后,建立神经网络模型,对内容图片中的风格和风格图片的风格进行提取,以内容图片为基准将其输入建立的模型中,并不断地调整内容度量值和风格度量值,让它们趋于最小,最后输出的图片就是内容与风格融合的图片。
(1)图像的内容损失
内容度量值可以使用均方误差作为损失函数,在代码中定义的图像内容损失如下:
class Content_loss(torch.nn.Module):
def init(self,weight,target):
super(Content_loss,self).init()
self.weight=weight
self.target=target.detach()*weight
self.loss_fn=torch.nn.MSELoss

def forward(self,input):
    self.loss=self.loss_fn(input*self.weight,self.target)
    return input

def backward(self):
    self.loss.backward(retain_graph=True)
    return self.loss

以上代码中的target是通过卷积获取到的输入图像中的内容;weight是我们设置的一个权重参数,用来控制内容和风格对最后合成图像的影响程度;input代表输入图像,target.detach()用于对提取到的内容进行锁定,不需要进行梯度;forward函数用于计算输入图像和内容图像之间的损失值;backward函数根据计算得到的损失值进行后向传播,并返回损失值。
(2)图像的风格损失
风格度量同样使用均方误差作为损失函数,代码如下:
class Style_loss(torch.nn.Module):
def init(self,weight,target):
super(Style_loss,self).init()
self.weight=weight
self.target=target.detach()*weight
self.loss_fn=torch.nn.MSELoss
self.gram=Gram_matrix()

def forward(self,input):
    self.Gram=self.gram(input.clone())
    self.Gram.mul_(self.weight)
    self.loss=self.loss_fn(self.Gram,self.target)
    return input

def backward(self):
    self.loss.backward(retain_graph=True)
    return self.loss

风格损失计算的代码基本和内容损失计算的代码相似,不同之处是在代码中引入了一个Gram_matrix类定义的实例参与风格损失的计算,这个类的代码如下:
class Gram_matrix(torch.nn.Module):
def forward(self,input):
a,b,c,d=input.size()
feature=input.view(ab,cd)
gram=torch.mm(feature,feature.t())
return gram.div(abc*d)
以上代码实现的是格拉姆矩阵(Gram matrix)的功能。我们通过卷积神经网络提取了风格图片的风格,这些风格其实是由数字组成的,数字的大小代表图片中风格的突出程度,而Gram矩阵是矩阵的内积运算,在运算过后输入到该矩阵的特征图中的大的数字会变得更大,这就相当于图片的风格被放大了,放大的风格再参与损失计算,便能够对最后的合成图片产生更大的影响。
(3)模型搭建和参数优化
在定义好内容损失和风格损失的计算方法之后,我们还需要搭建一个自定义的模型,并将这两部分内容融入模型中。
我们首先要做的是迁移一个卷积神经网络的特征提取部分,即卷积相关的部分,代码如下:
cnn=models.vgg6(pretrained=True).features

content_layer=[“Conv_3”]

style_layer=[“Conv_1”,“Conv_2”,“Conv_3”,“Conv_4”]

content_losses=[]
style_losses=[]

content_weight=1
style_weight=1000
在以上代码中首先迁移了一个VGG16架构的卷积神经网络模型的特征提取部分,然后定义了content_layer和style_layer,分别指定了我们需要在整个卷积过程中的哪一层提取内容,以及在哪一层提取风格。content_losses和style_losses是两个用于保存内容损失和风格损失的列表;content_weight和style_weight指定了内容损失和风格损失对我们最后得到的融合图片的影响权重。
搭建图像迁移模型;
for layer in list(model)[:8]指明了我们仅仅用到迁移模型特征提取部分的前8层,因为我们的内容提取和风格提取在前8层就已经完成了。然后建立一个空的模型,使用torch.nn.Module类的add_module方法向空的模型中加入知道的层析模块,最后得到我们自定义的图像风格迁移模型。add_module方法传递的参数分别是层次的名字和模块,该模块是使用isinstance实例检测函数得到的,而名字是对应的层次。
接下来就是参数优化部分;
使用的优化函数是torch.optim.LBFGS,原因是在这个模型中需要优化的损失值有多个并且规模较大,使用该优化函数可以取得更好的效果。
(4)训练新定义的卷积神经网络
在完成模型的搭建和优化函数的定义后,就可以开始模型的训练和参数的优化了。
这里定义了训练次数为300次,使用sl.backward和cl.backward实现了前向传播和后向传播算法。
**总结:**本章展示的是比较基础的图像风格迁移算法。
缺点:每次训练只能对其中一种风格进行迁移,如果需要进行其他风格的迁移,则还需要再重新对模型进行训练,而且需要通过对内容和风格设置不同的权重来控制风格调节的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值