使用深度学习神经风格转移
这个例子展示了如何应用文体的一个图像的场景内容第二图像使用pretrained VGG-19网络。
加载数据
加载图片和内容图片风格。下面的例子使用了独特的梵高油画“星夜”风格形象和灯塔作为图像内容的照片。
styleImage = im2double (imread (“starryNight.jpg”));contentImage = imread (“lighthouse.png”);
显示风格形象和内容蒙太奇形象。
imshow (imtile ({styleImage, contentImage},写成BackgroundColor =“w”));
负载特征提取网络
在本例中,您使用一个修改pretrained VGG-19深层神经网络提取图像内容和风格的特性在不同的层。这些多层功能用于计算各自的内容和风格的损失。网络生成程式化的传输图像使用合并后的损失。
得到一个pretrained VGG-19网络,安装vgg19
。如果你没有安装所需的支持包,然后软件提供一个下载链接。金宝app
网= vgg19;
VGG-19网络适用于特征提取,去除所有的完全从网络层连接。
lastFeatureLayerIdx = 38;层= net.Layers;层=层(1:lastFeatureLayerIdx);
最大的池层VGG-19网络导致衰落效应。减少褪色效果,增加梯度流,替换所有马克斯池层平均池层[1]。
为l = 1: lastFeatureLayerIdx层=层(左);如果isa(层,“nnet.cnn.layer.MaxPooling2DLayer”)层(l) = averagePooling2dLayer (…layer.PoolSize,跨步= layer.Stride Name = layer.Name);结束结束
创建一个层图修改层。
lgraph = layerGraph(层);
可视化特征提取网络在一个阴谋。
情节(lgraph)标题(“特征提取网络”)
训练网络使用一个自定义训练循环和启用自动分化、转换层图dlnetwork
对象。
dlnet = dlnetwork (lgraph);
数据进行预处理
调整图像和内容图像风格为更快的处理小一号。
图象尺寸= [384512];styleImg = imresize (styleImage、图象尺寸);contentImg = imresize (contentImage、图象尺寸);
的pretrained VGG-19网络上执行分类channel-wise意味着减去形象。得到channel-wise意味着从图像输入层,第一层的网络。
imgInputLayer = lgraph.Layers (1);meanVggNet = imgInputLayer.Mean (1 1:);
channel-wise的值意味着适合浮点数据类型的图像像素值的范围[0,255]。样式图片和内容图片转换为数据类型单
与区间[0,255]。然后,减去channel-wise意味着形象和内容形象风格。
styleImg =重新调节(单(styleImg), 0255)——meanVggNet;contentImg =重新调节(单(contentImg), 0255)——meanVggNet;
初始化传输图像
图像是输出图像转移风格转移的结果。您可以初始化传输图像的风格形象,内容图片,或任何随机的形象。初始化的风格图片或内容图像偏差风格转移过程和产生一个传输图像更类似于输入图像。相比之下,初始化与白噪声消除了偏见,但需要更长的时间收敛的程式化形象。为了更好的因袭和更快的收敛,这个例子中初始化输出传输图像的加权组合图像和白噪声图像的内容。
noiseRatio = 0.7;randImage =兰迪([-20,20],[图象尺寸3]);transferImage = noiseRatio。* randImage + (1-noiseRatio)。* contentImg;
定义损失函数和风格传递参数
内容丢失
内容损失的目的是使传输图像的特征匹配图像内容的特征。内容计算损失的均方区别内容图像特性和传输图像特征为每个功能层[1]。 是传输图像和预测功能映射 是内容的预测功能映射图像。 内容层的重量吗 层。 高度,宽度,分别和渠道的特征图谱。
指定的内容特征提取层的名字。从这些层提取的特征用于计算损失的内容。VGG-19网络,培训更有效利用深层的特性而不是从浅层次的特性。因此,指定内容特征提取层作为第四卷积层。
styleTransferOptions。contentFeatureLayerNames =“conv4_2”;
指定内容特征提取层的权重。
styleTransferOptions。contentFeatureLayerWeights = 1;
风格的损失
风格损失的目的是使传输图像的纹理匹配风格的纹理图像。的风格表示图像表示为格拉姆矩阵。因此,风格损失计算是均方区别风格的格拉姆矩阵图像的格拉姆矩阵传输图像[1]。 和 是风格和转移的预测特征图图像,分别。 和 克风格特性和传输特性的矩阵,分别。 风格层的重量吗 层风格。
指定的名字风格特征提取层。特征提取这些层用于计算风格损失。
styleTransferOptions。年代tyleFeatureLayerNames = […“conv1_1”,“conv2_1”,“conv3_1”,“conv4_1”,“conv5_1”];
指定的风格特征提取层的权重。指定小的重量对于简单的风格图片,增加权重对于复杂的风格图片。
styleTransferOptions。年代tyleFeatureLayerWeights = [0.5,1.0,1.5,3.0,4.0];
全部损失
总损失的加权组合内容和风格损失损失。 和 是内容和风格的损失,损失的重量因素分别。
指定的重量因素α
和β
内容和风格损失损失。的比例α
来β
应该在1 e - 3或1的军医[1]。
styleTransferOptions。α= 1;styleTransferOptions。β= 1 e3;
指定培训选项
2500年火车迭代。
numIterations = 2500;
指定的选项为亚当的优化。组2的学习速率更快的收敛。你可以尝试学习速率通过观察你的输出图像和损失。初始化后平均梯度和拖曳gradient-square平均衰减率[]
。
learningRate = 2;trailingAvg = [];trailingAvgSq = [];
培训网络
转换的风格形象,内容图片和传输图像dlarray
对象与基本类型单
和尺寸标签”SSC”
。
dlStyle = dlarray (styleImg,“SSC”);dlContent = dlarray (contentImg,“SSC”);dlTransfer = dlarray (transferImage,“SSC”);
火车在GPU如果一个是可用的。使用GPU需要并行计算工具箱™和CUDA NVIDIA GPU®®启用。有关更多信息,请参见GPU计算的需求(并行计算工具箱)。GPU培训,将数据转换成一个gpuArray
。
如果canUseGPU dlContent = gpuArray (dlContent);dlStyle = gpuArray (dlStyle);dlTransfer = gpuArray (dlTransfer);结束
提取图像内容特征的内容。
numContentFeatureLayers =元素个数(styleTransferOptions.contentFeatureLayerNames);contentFeatures =细胞(1、numContentFeatureLayers);[contentFeatures{}): =前进(dlnet dlContent,输出= styleTransferOptions.contentFeatureLayerNames);
提取图像风格的风格特征。
numStyleFeatureLayers =元素个数(styleTransferOptions.styleFeatureLayerNames);styleFeatures =细胞(1、numStyleFeatureLayers);[styleFeatures{}): =前进(dlnet dlStyle,输出= styleTransferOptions.styleFeatureLayerNames);
火车模型使用自定义训练循环。每一次迭代:
计算损失的内容和风格损失使用图像内容的特征,风格形象,传输图像。计算损失和渐变,使用helper函数
imageGradients
(定义在金宝app支持功能这个示例的部分)。使用更新传输图像
adamupdate
函数。选择最好的风格传递图像作为最终的输出图像。
图minimumLoss =正;为迭代= 1:numIterations%计算图像梯度转移和使用dlfeval和状态% imageGradients末尾列出函数的例子(校友,亏损)= dlfeval (@imageGradients、dlnet dlTransfer,…contentFeatures、styleFeatures styleTransferOptions);[dlTransfer, trailingAvg trailingAvgSq] = adamupdate (…毕业生,dlTransfer trailingAvg trailingAvgSq,迭代,learningRate);如果的损失。来t一个llo年代年代< minimumLoss minimumLoss = losses.totalLoss; dlOutput = dlTransfer;结束%显示图像转移后的第一个迭代和每50%的迭代。后处理步骤中描述“后处理%传输图像的显示”一节的例子如果国防部(迭代,50)= = 0 | |(迭代= = 1)transferImage =收集(extractdata (dlTransfer));transferImage = transferImage + meanVggNet;transferImage = uint8 (transferImage);transferImage = imresize (transferImage、大小(contentImage [1 - 2]));图像(transferImage)标题([“转移后图像迭代”num2str(迭代)])轴从图像drawnow结束结束
后处理传输图像的显示
得到更新后的传输图像。
transferImage =收集(extractdata (dlOutput));
添加network-trained意味着传输图像。
transferImage = transferImage + meanVggNet;
一些像素值可以超过原来的范围(0,255年)的内容和风格的形象。你可以剪辑的值范围(0,255年)通过转换数据类型uint8
。
transferImage = uint8 (transferImage);
调整内容的图像传输到原始大小的图像。
transferImage = imresize (transferImage、大小(contentImage [1 - 2]));
显示内容的图像,传输图像,图像和风格的蒙太奇。
imshow (imtile ({contentImage、transferImage styleImage},…GridSize = 3[1],写成BackgroundColor =“w”));
金宝app支持功能
计算图像损失和梯度
的imageGradients
辅助函数返回内容的损失和使用功能梯度图像,风格形象,传输图像。
函数(渐变,亏损)= imageGradients (dlnet dlTransfer,…contentFeatures、styleFeatures params)%初始化容器传输图像特征numContentFeatureLayers =元素个数(params.contentFeatureLayerNames);numStyleFeatureLayers =元素个数(params.styleFeatureLayerNames);transferContentFeatures =细胞(1、numContentFeatureLayers);transferStyleFeatures =细胞(1、numStyleFeatureLayers);%提取传输图像的内容特征[transferContentFeatures{}): =前进(dlnet dlTransfer,…输出= params.contentFeatureLayerNames);%提取传输图像的风格特征[transferStyleFeatures{}): =前进(dlnet dlTransfer,…输出= params.styleFeatureLayerNames);%计算内容丢失克洛斯= contentLoss (transferContentFeatures contentFeatures,…params.contentFeatureLayerWeights);%计算风格损失斯洛斯已经分居= styleLoss (transferStyleFeatures styleFeatures,…params.styleFeatureLayerWeights);%计算最终损失的加权组合内容和风格的损失= (params损失。α* cLoss) + (params.beta * sLoss);%计算梯度对传输图像梯度= dlgradient(损失、dlTransfer);%提取各种损失的损失。来t一个llo年代年代=gather(extractdata(loss)); losses.contentLoss = gather(extractdata(cLoss)); losses.styleLoss = gather(extractdata(sLoss));结束
计算内容丢失
的contentLoss
helper函数计算的加权均方区别图像特性和传输图像的内容特征。
函数损失= contentLoss (transferContentFeatures contentFeatures contentWeights)损失= 0;为i = 1:元素个数(contentFeatures) temp = 0.5 . *意味着((transferContentFeatures {1,} -contentFeatures {1,}) ^ 2,。“所有”);损失=损失+ (contentWeights (i) *临时);结束结束
计算风格损失
的styleLoss
helper函数计算加权均方不同风格的格拉姆矩阵图像特性和转移的格拉姆矩阵图像特征。
函数损失= styleLoss (transferStyleFeatures styleFeatures styleWeights)损失= 0;为i = 1:元素个数(styleFeatures) tsf = transferStyleFeatures {1,};科幻小说= styleFeatures {1,};[w h, c] =大小(sf);gramStyle = calculateGramMatrix (sf);gramTransfer = calculateGramMatrix (tsf);斯洛斯已经分居=意味着((gramTransfer - gramStyle) ^ 2,。“所有”)/ ((h * w * c) ^ 2);损失=损失+ (styleWeights (i) *斯洛斯已经分居);结束结束
格拉姆矩阵计算
的calculateGramMatrix
使用helper函数styleLoss
helper函数计算的格拉姆矩阵特征映射。
函数gramMatrix = calculateGramMatrix (featureMap) [W H, C] =大小(featureMap);reshapedFeatures =重塑(featureMap H * W C);gramMatrix = reshapedFeatures ' * reshapedFeatures;结束
引用
[1]利昂·a . Gatys亚历山大·s·艾克尔和马提亚陆慈。“神经算法艺术风格”。Preprint, submitted September 2, 2015. https://arxiv.org/abs/1508.06576
另请参阅
vgg19
|trainNetwork
|trainingOptions
|dlarray