主要内容

使用单位无监督Day-to-Dusk形象翻译

这个例子展示了如何将图像从白天到黄昏光线条件使用一个无监督image-to-image翻译网络(单位)。

领域翻译的任务是将图像从一个域到另一个风格和特征。这种技术可以扩展到其他image-to-image学习操作,如图像增强、图像彩色化,缺陷的一代,和医学图像分析。

单位[1]是一种生成对抗网络(GAN)由一个发电机网络和两个鉴别器网络训练同时最大化的整体性能。有关单位的更多信息,请参阅开始与甘斯Image-to-Image翻译(图像处理工具箱)

下载数据集

下面的例子使用了CamVid数据集[2]剑桥大学的培训。这个数据集的集合包含街道开车时视图获得701张图片。

指定dataDir的期望位置数据。下载CamVid数据集使用helper函数downloadCamVidImageData。这个函数是附加到例子作为支持文件。金宝app

dataDir = fullfile (tempdir,“CamVid”);downloadCamVidImageData (dataDir);imgDir = fullfile (dataDir,“图片”,“701 _stillsraw_full”);

天,黄昏数据加载

CamVid图像数据集包括497个图像在日间和124年获得的图像获得了黄昏。培训单位网络的性能是有限的,因为CamVid训练图像的数量相对较小,这限制了训练网络的性能。此外,一些图像属于图像序列,因此与其他图像数据集。尽量减少这些限制的影响,本例中手动分区数据训练和测试数据集的方式最大化训练数据的可变性。

得到一天的文件名和黄昏图像进行训练和测试通过加载该文件camvidDayDuskDatasetFileNames.mat。训练数据集包括107年263天的图像和黄昏的图片。234天的测试数据集包含图片和17日黄昏图片。

负载(“camvidDayDuskDatasetFileNames.mat”);

创建imageDatastore管理的对象和黄昏图像进行训练和测试。

imdsDayTrain = imageDatastore (fullfile (imgDir trainDayNames));imdsDuskTrain = imageDatastore (fullfile (imgDir trainDuskNames));imdsDayTest = imageDatastore (fullfile (imgDir testDayNames));imdsDuskTest = imageDatastore (fullfile (imgDir testDuskNames));

预览的训练图像的一天,傍晚训练数据集。

一天=预览(imdsDayTrain);黄昏=预览(imdsDuskTrain);蒙太奇({天,黄昏})

预处理和增加训练数据

指定源和目标图像大小输入图像。

inputSize = (256256 3);

通过使用增强和预处理的训练数据变换函数与自定义的helper函数指定的预处理操作augmentDataForDayToDusk。这个函数是附加到例子作为支持文件。金宝app

augmentDataForDayToDusk函数执行这些操作:

  1. 调整图像大小指定输入使用双立方插值。

  2. 随机翻转图像在水平方向上。

  3. 规模的图像范围[1]。这个范围匹配最后的范围tanhLayer用于发电机。

imdsDayTrain =变换(imdsDayTrain @ (x) augmentDataForDayToDusk (x, inputSize));imdsDuskTrain =变换(imdsDuskTrain @ (x) augmentDataForDayToDusk (x, inputSize));

创建生成器网络

创建一个单元发生器网络使用unitGenerator(图像处理工具箱)函数。源和目标发生器的编码器部分由两个将采样块和五个残块。编码器部分有两个五残块。同样,源和目标的解码器部分发电机由两个downsampling块和5个残块,和解码器部分份额的两个五残块。

创= unitGenerator (inputSize NumResidualBlocks = 5, NumSharedBlocks = 2);

可视化发电机网络。

analyzeNetwork(创)

创建鉴别器网络

创建两个鉴别器网络,一个用于每一个源和目标域,使用patchGANDiscriminator(图像处理工具箱)函数。天是源域和黄昏是目标域。

discDay = patchGANDiscriminator (inputSize NumDownsamplingBlocks = 4, FilterSize = 3,ConvolutionWeightsInitializer =“narrow-normal”NormalizationLayer =“没有”);discDusk = patchGANDiscriminator (inputSize NumDownsamplingBlocks = 4, FilterSize = 3,ConvolutionWeightsInitializer =“narrow-normal”NormalizationLayer =“没有”);

可视化鉴别器网络。

analyzeNetwork (discDay);analyzeNetwork (discDusk);

定义模型梯度和损失函数

modelGradientDiscmodelGradientGen辅助函数的梯度和损失计算鉴别器和生成器,分别。这些函数中定义金宝app支持功能这个例子。

每一个鉴别器的目的是正确区分真实图像(1)和翻译图像(0)图像域。每一个鉴别器只有一个损失函数。

发电机的目的是生成翻译图片的鉴别器分类一样真实。发电机损失是一个加权和五个类型的损失:self-reconstruction损失,周期一致性损失,隐藏KL损失,周期隐藏KL损失,和敌对的损失。

指定的重量因素的各种损失。

lossWeights。自我ReconLossWeight = 10; lossWeights.hiddenKLLossWeight = 0.01; lossWeights.cycleConsisLossWeight = 10; lossWeights.cycleHiddenKLLossWeight = 0.01; lossWeights.advLossWeight = 1; lossWeights.discLossWeight = 0.5;

指定培训选项

指定的选项为亚当的优化。35时代列车网络。发电机和鉴别器网络指定相同的选项。

  • 指定一个平等的学习速率为0.0001。

  • 初始化后平均梯度和拖曳gradient-square平均衰减率[]

  • 使用渐变衰减系数的0.5和0.999平方梯度衰减系数。

  • 使用体重衰变正则化因子为0.0001。

  • 使用mini-batch大小为1进行训练。

learnRate = 0.0001;gradDecay = 0.5;sqGradDecay = 0.999;weightDecay = 0.0001;genAvgGradient = [];genAvgGradientSq = [];discDayAvgGradient = [];discDayAvgGradientSq = [];discDuskAvgGradient = [];discDuskAvgGradientSq = []; miniBatchSize = 1; numEpochs = 35;

批训练数据

创建一个minibatchqueue观察的对象管理mini-batching定制培训循环。的minibatchqueue对象也投下数据dlarray在深度学习应用程序对象,使自动分化。

指定mini-batch数据提取格式为“SSCB”(空间、空间、通道、批)。设置DispatchInBackground名称-值参数返回的布尔值canUseGPU。如果一个支金宝app持GPU用于计算,然后minibatchqueue对象进行预处理mini-batches背景在一个平行的池训练。

mbqDayTrain = minibatchqueue (imdsDayTrain MiniBatchSize = MiniBatchSize,MiniBatchFormat =“SSCB”DispatchInBackground = canUseGPU);mbqDuskTrain = minibatchqueue (imdsDuskTrain MiniBatchSize = MiniBatchSize,MiniBatchFormat =“SSCB”DispatchInBackground = canUseGPU);

列车网络的

默认情况下,示例下载pretrained版本的单元发生器CamVid pretrained网络数据集。使您能够运行整个示例没有等待培训完成。

训练网络,设置doTraining变量在下面的代码真正的。火车模型在一个定制的训练循环。每一次迭代:

  • 读取数据为当前mini-batch使用下一个函数。

  • 评估模型梯度使用dlfeval函数和modelGradientDiscmodelGradientGen辅助功能。

  • 更新网络参数使用adamupdate函数。

  • 显示输入和翻译图像的源和目标域后,每一个时代。

火车在GPU如果一个是可用的。使用GPU需要并行计算工具箱™和CUDA NVIDIA GPU®®启用。有关更多信息,请参见GPU计算的需求(并行计算工具箱)。培训在NVIDIA泰坦RTX大约需要88个小时。

doTraining = false;如果doTraining%创建一个图来显示结果图(单位=“归一化”);iPlot ax = 1:4 (iPlot) =次要情节(2,2,iPlot);结束迭代= 0;%循环时代时代= 1:numEpochs%洗牌数据每一时代重置(mbqDayTrain);洗牌(mbqDayTrain);重置(mbqDuskTrain);洗牌(mbqDuskTrain);%运行循环直到mini-batch队列中的所有图片% mbqDayTrain处理hasdata (mbqDayTrain)迭代=迭代+ 1;%从天读取数据域imDay =下一个(mbqDayTrain);%从黄昏读取数据域如果hasdata (mbqDuskTrain) = = 0重置(mbqDuskTrain);洗牌(mbqDuskTrain);结束imDusk =下一个(mbqDuskTrain);%计算鉴别器梯度和损失[discDayGrads, discDuskGrads discDayLoss disDuskLoss] = dlfeval (创,@modelGradientDisc discDay、discDusk imDay, imDusk,lossWeights.discLossWeight);重量%应用衰减正规化天鉴频器梯度discDayGrads = dlupdate (@ (g, w) g + weightDecay * w,discDayGrads discDay.Learnables);%更新天鉴频器的参数[discDay, discDayAvgGradient discDayAvgGradientSq] = adamupdate (discDay、discDayGrads discDayAvgGradient discDayAvgGradientSq,迭代,learnRate、gradDecay sqGradDecay);重量%应用衰减在黄昏鉴别器梯度正则化discDuskGrads = dlupdate (@ (g, w) g + weightDecay * w,discDuskGrads discDusk.Learnables);%更新黄昏鉴别器的参数[discDusk, discDuskAvgGradient discDuskAvgGradientSq] = adamupdate (discDusk、discDuskGrads discDuskAvgGradient discDuskAvgGradientSq,迭代,learnRate、gradDecay sqGradDecay);%计算发电机梯度和损失(genGrad、genLoss、图像)= dlfeval (创,@modelGradientGen discDay、discDusk imDay, imDusk, lossWeights);%重量衰变正规化适用于发电机梯度genGrad = dlupdate (@ (g, w) g + weightDecay * w, genGrad, gen.Learnables);%更新参数的发电机(创genAvgGradient genAvgGradientSq] = adamupdate (创,genGrad genAvgGradient genAvgGradientSq,迭代,learnRate、gradDecay sqGradDecay);结束%显示结果updateTrainingPlotDayToDusk (ax,图片{:});结束%保存训练网络modelDateTime =字符串(datetime (“现在”格式=“yyyy-MM-dd-HH-mm-ss”));保存(fullfile (dataDir“trainedDayDuskUNITGeneratorNet——”+ modelDateTime +“.mat”),“创”);其他的net_url =“https://ssd.mathworks.com/金宝appsupportfiles/”+“视觉/数据/ trainedDayDuskUNITGeneratorNet.zip”;downloadTrainedNetwork (net_url dataDir);负载(fullfile (dataDir“trainedDayDuskUNITGeneratorNet.mat”));结束

评估源到目标的翻译

源到目标图像翻译使用单元发生器来生成一个图像在目标域(黄昏)从源域的图像(一天)。

从数据存储读取图像的测试图像。

idxToTest = 1;dayTestImage = readimage (imdsDayTest idxToTest);

将图像转换为数据类型和规范化的图像范围[1]。

dayTestImage = im2single (dayTestImage);dayTestImage = (dayTestImage - 0.5) / 0.5;

创建一个dlarray对象,输入数据生成器。如果一个支金宝app持GPU用于计算,然后进行推理将数据转化为GPUgpuArray对象。

dlDayImage = dlarray (dayTestImage,“SSCB”);如果canUseGPU dlDayImage = gpuArray (dlDayImage);结束

将输入图像黄昏域使用unitPredict(图像处理工具箱)函数。

dlDayToDuskImage = unitPredict(创,dlDayImage);dayToDuskImage = extractdata(收集(dlDayToDuskImage));

最后一层的发电机网络产生的激活范围[1]。显示,重新调节激活范围[0,1]。同时,重新调节图像显示之前输入的一天。

dayToDuskImage =重新调节(dayToDuskImage);dayTestImage =重新调节(dayTestImage);

显示输入图像和其翻译黄昏版本蒙太奇。

图蒙太奇({dayTestImage dayToDuskImage})标题(“天测试图像”+ num2str (idxToTest) +“翻译黄昏形象”)

评估Target-to-Source翻译

Target-to-source图像翻译使用单元发生器来生成一个图像在源域(天)从一个图像在目标域(黄昏)。

读取图像数据存储的黄昏测试图像。

idxToTest = 1;duskTestImage = readimage (imdsDuskTest idxToTest);

将图像转换为数据类型和规范化的图像范围[1]。

duskTestImage = im2single (duskTestImage);duskTestImage = (duskTestImage - 0.5) / 0.5;

创建一个dlarray对象,输入数据生成器。如果一个支金宝app持GPU用于计算,然后进行推理将数据转化为GPUgpuArray对象。

dlDuskImage = dlarray (duskTestImage,“SSCB”);如果canUseGPU dlDuskImage = gpuArray (dlDuskImage);结束

一天黄昏翻译输入图像域使用unitPredict(图像处理工具箱)函数。

dlDuskToDayImage = unitPredict (gen、dlDuskImage OutputType =“TargetToSource”);duskToDayImage = extractdata(收集(dlDuskToDayImage));

显示,重新调节激活范围[0,1]。同时,重新调节输入黄昏前图像显示。

duskToDayImage =重新调节(duskToDayImage);duskTestImage =重新调节(duskTestImage);

显示输入黄昏形象及其翻译版本在蒙太奇。

蒙太奇({duskTestImage duskToDayImage})标题(“测试黄昏形象”+ num2str (idxToTest) +“形象”翻译)

金宝app支持功能

模型梯度函数

modelGradientDischelper函数的梯度和损失计算两个鉴别器。

函数[discAGrads, discBGrads discALoss discBLoss] = modelGradientDisc(创,discA、discB ImageA、ImageB discLossWeight) [~, fakeA、fakeB ~] =前进(创,ImageA ImageB);%计算X_A鉴别器的损失一=前进(discA ImageA);outfA =前进(discA fakeA);outfA discALoss = discLossWeight * computeDiscLoss(一);%更新参数鉴别器的XdiscAGrads = dlgradient (discALoss discA.Learnables);%计算X_B鉴别器的损失outB =前进(discB ImageB);outfB =前进(discB fakeB);discBLoss = discLossWeight * computeDiscLoss (outB outfB);%更新参数鉴别器的YdiscBGrads = dlgradient (discBLoss discB.Learnables);% dlarray数据类型转换成单discALoss = extractdata (discALoss);discBLoss = extractdata (discBLoss);结束

modelGradientGenhelper函数计算发电机的梯度和损失。

函数(genGrad、genLoss、图像)= modelGradientGen(创,discA、discB ImageA、ImageB lossWeights) [ImageAA、ImageBA ImageAB, ImageBB] =前进(创,ImageA ImageB);隐藏=前进(gen、ImageA ImageB,输出=“encoderSharedBlock”);[~,ImageABA ImageBAB ~] =前进(创,ImageBA ImageAB);cycle_hidden =前进(gen、ImageBA ImageAB,输出=“encoderSharedBlock”);%计算不同的损失selfReconLoss = computeReconLoss (ImageA ImageAA) + computeReconLoss (ImageB ImageBB);hiddenKLLoss = computeKLLoss(隐藏);cycleReconLoss = computeReconLoss (ImageA ImageABA) + computeReconLoss (ImageB ImageBAB);cycleHiddenKLLoss = computeKLLoss (cycle_hidden);一=前进(discA ImageBA);outB =前进(discB ImageAB);advLoss = computeAdvLoss(一)+ computeAdvLoss (outB);%计算发电机的全损的加权和五个损失genTotalLoss =selfReconLoss * lossWeights。selfReconLossWeight +hiddenKLLoss * lossWeights。hiddenKLLossWeight +cycleReconLoss * lossWeights。cycleConsisLossWeight +cycleHiddenKLLoss * lossWeights。cycleHiddenKLLossWeight +advLoss * lossWeights.advLossWeight;%更新发电机的参数genGrad = dlgradient (genTotalLoss gen.Learnables);% dlarray数据类型转换成单genLoss = extractdata (genTotalLoss);图像= {ImageA, ImageAB、ImageB ImageBA};结束

损失函数

computeDiscLosshelper函数计算鉴别器的损失。每个鉴别器损失一笔两个组件:

  • 方区别向量的和预测的鉴频器在实际图像, Y 真正的

  • 零的平方区别向量和鉴频器的预测生成的图像, Y ˆ 翻译

discriminatorLoss = ( 1 - - - - - - Y 真正的 ) 2 + ( 0 - - - - - - Y ˆ 翻译 ) 2

函数discLoss = computeDiscLoss (Yreal Ytranslated) discLoss =意味着(((1-Yreal) ^ 2),“所有”)+意思是(((0-Ytranslated) ^ 2),“所有”);结束

computeAdvLosshelper函数计算发电机的对抗性的损失。敌对的损失是平方区别向量的和翻译图片上的鉴别器的预测。

adversarialLoss = ( 1 - - - - - - Y ˆ 翻译 ) 2

函数advLoss = computeAdvLoss (Ytranslated) advLoss =意味着(((Ytranslated-1) ^ 2),“所有”);结束

computeReconLosshelper函数计算self-reconstruction损失和cycle-consistency发电机损失。Self-reconstruction损失是 l 1 输入图像及其self-reconstructed版本之间的距离。Cycle-consistency损失是 l 1 输入图像及其cycle-reconstructed版本之间的距离。

selfReconstructionLoss = ( Y 真正的 - - - - - - Y 自我 - - - - - - 重建 ) 1

cycleConsistencyLoss = ( Y 真正的 - - - - - - Y 周期 - - - - - - 重建 ) 1

函数reconLoss = computeReconLoss (Yreal Yrecon) reconLoss =意味着(abs (Yreal-Yrecon),“所有”);结束

computeKLLosshelper函数计算隐藏KL损失和cycle-hidden KL发电机损失。隐藏KL损失方零矢量和的区别encoderSharedBlock激活self-reconstruction流。Cycle-hidden KL损失是平方零矢量和的区别encoderSharedBlock激活cycle-reconstruction流。

hiddenKLLoss = ( 0 - - - - - - Y encoderSharedBlockActivation ) 2

cycleHiddenKLLoss = ( 0 - - - - - - Y encoderSharedBlockActivation ) 2

函数klLoss = computeKLLoss(隐藏)klLoss =意味着(abs(隐藏。^ 2),“所有”);结束

引用

[1]Liu Ming-Yu托马斯·Breuel和Jan Kautz“无监督image-to-image翻译网络”。在神经信息处理系统的进步,2017年。https://arxiv.org/abs/1703.00848

加布里埃尔·[2]Brostow J。,Julien Fauqueur, and Roberto Cipolla. "Semantic Object Classes in Video: A High-Definition Ground Truth Database."模式识别的字母。问题2卷。30日,2009年,页88 - 97。

另请参阅

|(图像处理工具箱)|(图像处理工具箱)|||||(图像处理工具箱)

相关的话题