使用深度学习的语义分割

这个例子说明了如何使用深学习培养了语义分割网络。

语义分割网络对图像中的每个像素进行分类,从而得到按类分割的图像。语义分割的应用包括用于自主驾驶的道路分割和用于医学诊断的癌细胞分割。想了解更多,请看开始使用语义分割使用深度学习(计算机视觉工具箱)。

为了说明训练过程,本实施例列车Deeplab V3 + [1],一种类型的卷积神经网络的(CNN)设计用于语义的图像分割。其他类型的网络对语义分割的包括完全卷积网络(FCN),SegNet,和U-Net的。这里显示的训练过程可以被应用到这些网络了。

本例使用CamVid数据集[2]从剑桥大学进行培训。此数据集是包含在驾驶时获得的街道级视图的图像的集合。该数据集提供了像素级标签32个语义类别包括汽车,行人和道路。

设置

这个例子创建了一个Deeplab v3+网络,它的权值是由一个预先训练好的Resnet-18网络初始化的。ResNet-18是一种高效的网络,非常适合处理资源有限的应用程序。其他预训练的网络,如MobileNet v2或ResNet-50,也可以根据应用需求使用。有关更多细节,请参见预训练深层神经网络

要获得预培训的Resnet-18,请安装针对Resnet-18网络的深度学习工具箱™模型。安装完成后,运行以下代码以验证安装是否正确。

resnet18 ();

另外,下载一个预训练版本的DeepLab v3+。预训练的模型允许您运行整个示例,而不必等待训练完成。

pretrainedURL ='//www.tianjin-qmedu.com/万博1manbetxsupportfiles/vision/data/deeplabv3plusResnet18CamVid.mat';pretrainedFolder = fullfile (tempdir,'pretrainedNetwork');pretrainedNetwork = fullfile (pretrainedFolder,'deeplabv3plusResnet18CamVid.mat');如果〜存在(pretrainedNetwork,'文件'mkdir (pretrainedFolder);disp (“预训练下载网(58 MB)......”);websave (pretrainedNetwork pretrainedURL);结束

强烈建议使用具有计算能力3.0或更高的cuda能力的NVIDIA™GPU来运行此示例。使用GPU需要并行计算工具箱™。

下载CamVid数据集

从以下url下载CamVid数据集。

imageURL =“http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/files/701_StillsRaw_full.zip”;labelURL =“http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/LabeledApproved_full.zip”;outputFolder =完整文件(TEMPDIR,“CamVid”);labelsZip = fullfile (outputFolder,'labels.zip');imagesZip = fullfile (outputFolder,“images.zip”);如果〜存在(labelsZip,'文件')| | ~存在(imagesZip'文件'mkdir (outputFolder) disp (“下载16层MB CamVid数据集的标签......”);websave(labelsZip,labelURL);解压缩(labelsZip,完整文件(outputFolder,'标签'));disp (“正在下载557 MB的CamVid数据集图像……”);websave(imagesZip,IMAGEURL);解压缩(imagesZip,完整文件(outputFolder,“图片”));结束

注:下载时间视乎阁下的互联网连线而定。上面使用的命令会阻塞MATLAB,直到下载完成。或者,您可以使用web浏览器首先将数据集下载到本地磁盘。若要使用从web下载的文件,请更改outputFolder以上变量指定下载文件的位置。

加载CamVid图片

使用imageDatastore加载视频图像。的imageDatastore使您能够有效地在磁盘上加载大量映像。

imgDir = fullfile (outputFolder,“图片”,'701_StillsRaw_full');imd = imageDatastore (imgDir);

显示其中一个图像。

I = readimage (imd, 1);I = histeq(我);imshow(我)

加载CamVid像素标记的图像

使用pixelLabelDatastore来加载CamVid像素标签图像数据。一个pixelLabelDatastore将像素标签数据和标签ID封装到类名映射中。

我们让培训变得更容易,我们把原来的32个班级分成了11个班级。指定这些类。

类= [“天空”“建筑”“极”“路”“路面”“树”“SignSymbol”“篱笆”“汽车”“行人”“自行车”];

为了将32个类减少到11个,将原始数据集中的多个类分组在一起。例如,“Car”是“Car”、“SUVPickupTruck”、“Truck_Bus”、“Train”和“OtherMoving”的组合。使用支持函数返回分组的标签id万博1manbetxcamvidPixelLabelIDs,它列在本例的末尾。

labelIDs = camvidPixelLabelIDs ();

使用类和标签的ID创建pixelLabelDatastore。

labelDir = fullfile (outputFolder,'标签');pxds = pixelLabelDatastore(labelDir,类,labelIDs);

读取并通过覆盖其上的图像的顶部的像素标记的图像的显示之一。

C = readimage (pxds, 1);提出= camvidColorMap;我= labeloverlay (C“ColorMap”,CMAP);imshow(B)pixelLabelColorbar(CMAP,班);

没有颜色覆盖的区域没有像素标签,也不会在训练中使用。

分析数据集统计数据

若要查看CamVid数据集,使用类标签的分发countEachLabel。这个函数根据类标签来计算像素的数量。

台= countEachLabel (pxds)
台=11×3表名称PixelCount ImagePixelCount ______________ __________ _______________ { '天空'} 7.6801e + 07 4.8315e + 08 { '大厦'} 1.1737e + 08 4.8315e + 08 { '极'} 4.7987e + 06 4.8315e + 08 { '道'}1.4054e + 08 4.8453e + 08 { '路面'} 3.3614e + 07 4.7209e + 08 { '树'} 5.4259e + 07 4.479e + 08 { 'SignSymbol'} 5.2242e + 06 4.6863e + 08 {'栅栏'} 6.9211e + 06 2.516e + 08 {' 汽车”} 2.4437e + 07 4.8315e + 08 { '行人'} 3.4029e + 06 4.4444e + 08 { '自行车运动员'} 2.5912e + 06 2.6196e + 08

根据类可视化像素计数。

频率= tbl.PixelCount /笔(tbl.PixelCount);(1:numel(类),频率)xticks(1:numel(类))xticklabel (tbl.Name) xtickangle(45) ylabel('频率')

理想情况下,所有的类都应该有相同数量的观察值。然而,在CamVid的类是不平衡的,这是一个常见的问题,在汽车数据集的街道场景。这类场景的天空、建筑物和道路像素比行人和自行车像素更多,因为天空、建筑物和道路在图像中覆盖的面积更大。如果处理不当,这种不平衡会对学习过程产生不利影响,因为学习是偏向于优势阶级的。稍后,在这个示例中,您将使用类加权来处理这个问题。

CamVid数据集中的图像大小是720×960。图像大小的选择使得在NVIDIA™Titan X上进行训练时,可以在内存中容纳足够大的一批图像,而NVIDIA™Titan X的内存为12gb。如果你的GPU没有足够的内存或减少训练批大小,你可能需要调整图像到更小的尺寸。

准备培训、验证和测试集

Deeplab v3+使用数据集中60%的图像进行训练。剩下的图像平均分成20%和20%分别进行验证和测试。下面的代码将图像和像素标签数据随机分成训练、验证和测试集。

[imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = partitionCamVidData(imds,pxds);

60/20/20分割结果如下图所示:

numTrainingImages =元素个数(imdsTrain.Files)
numTrainingImages = 421
numValImages = numel(imdsVal.Files)
numValImages = 140
numTestingImages = numel(imdsTest.Files)
numTestingImages = 140

创建网络

使用deeplabv3plusLayers函数创建一个基于ResNet-18的DeepLab v3+网络。为您的应用程序选择最佳网络需要经验分析,这是超参数调优的另一个层次。例如,您可以尝试使用不同的基础网络,如ResNet-50或MobileNet v2,或者您可以尝试其他语义分割网络架构,如SegNet、全卷积网络(FCN)或U-Net。

%指定网络映像大小。这通常与训练图像的大小相同。imageSize = [720960 3];%指定类的数目。numClasses =元素个数(类);%创建DeepLab v3+。lgraph = deeplabv3plusLayers(imageSize, numClasses,“resnet18”);

使用类加权来平衡类

如图所示早些时候,在CamVid类不均衡。为了提高训练,你可以使用类的权重,以平衡类。使用前面与计算的像素数的标签countEachLabel并计算出中位数频率类的权重。

imageFreq = tbl.PixelCount ./ tbl.ImagePixelCount;classWeights =中间值(imageFreq)./ imageFreq
classWeights =11×10.3182 0.2082 5.0924 0.1744 0.7103 0.4175 4.5371 1.8386 1.0000 6.6059⋮

指定使用的类权重pixelClassificationLayer

pxLayer = pixelClassificationLayer(“名字”,'标签',“类”,tbl.Name,“ClassWeights”,classWeights);lgraph = replaceLayer (lgraph,“分类”,pxLayer);

选择培训选项

用于训练的优化算法是带动量的随机梯度下降法(SGDM)。使用trainingOptions指定用于SGDM的超参数。

定义验证数据。pximdsVal = pixelLabelImageDatastore (imdsVal pxdsVal);定义培训选项。选项= trainingOptions(“个”,...“LearnRateSchedule”,“分段”,...'LearnRateDropPeriod'10...“LearnRateDropFactor”,0.3,...“动量”,0.9,...“InitialLearnRate”,1E-3,...“L2Regularization”,0.005,...'ValidationData',pximdsVal,...'MaxEpochs'30,...“MiniBatchSize”8...“洗牌”,“每个历元”,...'CheckpointPath'tempdir,...“VerboseFrequency”2,...“阴谋”,“训练进步”,...“ValidationPatience”4);

学习速度采用分段计划。学习率每10个epoch减少0.3倍。这使得网络能够以更高的初始学习速率快速学习,同时能够在学习速率下降时找到接近于局部最优的解决方案。

网络不受验证数据每历元通过设置测试'ValidationData'参数。的“ValidationPatience”设置为4,以便在验证精度收敛时尽早停止训练。这可以防止网络对训练数据集进行过度拟合。

小批处理大小为8,用于减少训练时的内存使用。你可以增加或减少这个值的基础上的GPU内存量你的系统。

此外,'CheckpointPath'被设置为一个临时位置。此名称 - 值对使网络检查站的保存在每个训练时代的结束。如果培训是系统故障或停电中断的原因,您可以继续从已保存的检查点的训练。确保位置的指定'CheckpointPath'有足够的空间存储网络检查点。例如,节省100个Deeplab v3+检查点需要大约6 GB的磁盘空间,因为每个检查点是61 MB。

数据增加

在训练中使用数据扩充来为网络提供更多的例子,因为它有助于提高网络的准确性。这里使用随机的左/右反射和随机的X/Y平移+/- 10像素来增加数据。使用imageDataAugmenter指定这些数据增强参数。

增量= imageDataAugmenter (“RandXReflection”,真正,...“RandXTranslation”-10年[10],“RandYTranslation”,-10年[10]);

imageDataAugmenter万博1manbetx支持其他几种类型的数据扩充。在它们之间进行选择需要进行实证分析,这是超参数调整的另一个层次。

开始训练

结合使用的训练数据和数据扩充选择pixelLabelImageDatastore。的pixelLabelImageDatastore读取批量训练数据,应用数据扩充,并将扩充后的数据发送给训练算法。

pximds = pixelLabelImageDatastore (imdsTrain pxdsTrain,...“DataAugmentation”、增压器);

开始培训使用trainNetwork如果doTraining国旗是正确的。否则,加载一个预先训练好的网络。

注:培训,验证上的英伟达™泰坦X具有12 GB GPU内存中。如果您的GPU具有较少的内存,你可以的记忆训练中跑出来。如果发生这种情况,可以尝试设置“MiniBatchSize”1在trainingOptions或降低了网络的输入和调整用的训练数据“OutputSize”参数pixelLabelImageDatastore。训练这个网络大约需要5个小时。根据你的GPU硬件,它可能会花费更长的时间。

doTraining = FALSE;如果doTraining [net, info] = trainNetwork(pximds,lgraph,options);其他的data =负载(pretrainedNetwork);网= data.net;结束

在一个映像上测试网络

作为一个快速的完整性检查,在一个测试映像上运行这个训练好的网络。

I = readimage (imdsTest 35);C = semanticseg(I, net);

显示结果。

我= labeloverlay (C“Colormap”提出,“透明”,0.4);imshow (B) pixelLabelColorbar(提出、类);

比较结果C与预期的地面真相储存在pxdsTest。绿色和洋红色区域突出了分割结果与期望地面真相不同的区域。

expectedResult = readimage (pxdsTest 35);实际= uint8 (C);预期= uint8 (expectedResult);预计imshowpair(实际)

在视觉上,语义分割结果在道路、天空和建筑物等类中重叠良好。然而,像行人和汽车这样的小物体就不那么精确了。每个类的重叠量可以使用相交-过并集(IoU)度量,也称为Jaccard索引。使用jaccard功能,以衡量欠条。

借据= jaccard (C, expectedResult);表(类、借据)
ans =11×2表学校下设“天”字0.91837“楼”字0.84479“路”字0.31203“路”字0.83698“路”字0.82838“树”字0.89636“标志”字0.57644“栅栏”字0.71046“车”字0.66688“行人”字0.48417“自行车”字0.68431

IoU度量确认了可视化结果。道路、天空和建筑类的IoU得分较高,而行人和汽车类的IoU得分较低。其他常见的细分指标包括骰子bfscore轮廓匹配分数。

评估培训网络

为了测量多个测试图像,运行精度semanticseg在整个测试集上。最小批处理大小为4,用于在分割图像时减少内存使用量。你可以增加或减少这个值的基础上的GPU内存量你的系统。

pxdsResults = semanticseg (imdsTest净,...“MiniBatchSize”4...“WriteLocation”tempdir,...“详细”,假);

semanticseg将测试集的结果返回为pixelLabelDatastore宾语。在每一个测试图像的实际像素标签数据imdsTest方法指定的位置写入磁盘“WriteLocation”参数。使用evaluateSemanticSegmentation对测试集结果进行语义分割度量。

度量= evaluateSemanticSegmentation(pxdsResults,pxdsTest,“详细”,假);

evaluateSemanticSegmentation返回整个数据集、单个类和每个测试图像的各种指标。要查看数据集级别指标,请查看metrics.DataSetMetrics

metrics.DataSetMetrics
ans =表1×5_______ GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU MeanBFScore * * *…………0.87695 0.85392 - 0.6302 0.80851 - 0.65051

数据集指标提供了网络性能的高级概览。要查看每个类对总体性能的影响,请使用以下工具查看每个类的指标metrics.ClassMetrics

metrics.ClassMetrics
ans =11×3表准确的IoU意思是分数为“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”、“天空”

尽管整个数据集的性能相当高,但是类指标显示,代表性不足的类,比如行人,骑自行车不分段以及类,如,天空建筑。它包括的代表性不足的班级可能会帮助更多的样品附加数据改善的结果。

万博1manbetx支持功能

功能labelIDs = camvidPixelLabelIDs ()%返回对应于每一类的标签的ID。%CamVid数据集有32个类。把他们分成11个班%原SegNet训练方法[1]。%% 11类是:%的“天空”“建筑”,“极”,“路”,“路面”、“树”、“SignSymbol”,“栅栏”、“汽车”、“行人”和“骑自行车的人”。%% CamVid像素标签id作为RGB颜色值提供。集团成% 11类,并将其作为m×3矩阵的单元数组返回。的每个RGB值旁边都列出了%原始的CamVid类名。请注意%,其他/Void类被排除在下面。labelIDs = {...%的“天空”[128 128 128;...%的“天空”]% “建造”[000 128064;...%“桥”128 000 000;...% “建造”064 192 000;...%的“墙”064 000 064;...%的“隧道”192 000 128;...%的“拱门”]%“极点”[192 192 128;...%”Column_Pole”000 000 064;...% “交通拥挤”]%的道路[128064 128;...%的“路”128 000 192;...% “LaneMkgsDriv”192 000 064;...%”LaneMkgsNonDriv”]%“路面”[100万192;...%“人行道”064 192 128;...% “ParkingBlock”128 128 192;...%”RoadShoulder”]%的“树”[128128 000;...%的“树”192 192 000;...%”VegetationMisc”]%”SignSymbol”[192 128 128;...%”SignSymbol”128 128 064;...%”Misc_Text”000 064 064;...%”TrafficLight”]%“篱笆”[064 064 128;...%“篱笆”]%的“汽车”[064 000 128;...%的“汽车”064 128 192;...%”SUVPickupTruck”192 128 192;...%”Truck_Bus”192 064 128;...%“训练”128 064 064;...%”OtherMoving”]%“行人”[064 064 000;...%“行人”192 128 064;...%的“孩子”064 000 192;...% “CartLuggagePram”064 128 064;...%的“动物”]%“自行车”[000 128192;...%“自行车”192 000 192;...% “MotorcycleScooter”]};结束
功能一会pixelLabelColorbar(提出)向当前轴添加一个颜色栏。颜色栏被格式化了%以显示类名的颜色。颜色表(GCA,CMAP)%添加颜色栏到当前的数字。c = colorbar (“对等”,GCA);%用途类名的刻度线。c。TickLabels =一会;numClasses =大小(提出,1);%中心标记标签。c。蜱虫= 1 / (numClasses * 2): 1 / numClasses: 1;清除标记。c。TickLength = 0;结束
功能提出= camvidColorMap ()%定义被CamVid数据集使用的颜色映射。cmap = [128,128,128]%的天空128 0 0% 建造192 192 192%极128 64 128%的道路60 40 222%的人行道上128 128 0%的树192 128 128% SignSymbol64 64 128%的栅栏64 0 128%的车64 64 0%行人0 128 192%骑自行车];%在[0 1]之间正常化。cmap = cmap ./ 255;结束
功能[imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = partitionCamVidData(imds,pxds)通过随机选择60%的数据进行训练,%分割CamVid数据。的% rest用于测试。设定初始随机状态,例如再现性。rng (0);numFiles =元素个数(imds.Files);shuffledIndices = randperm (numFiles);%使用60%的图像进行训练。numTrain = round(0.60 * numFiles);trainingIdx = shuffledIndices (1: numTrain);%使用20%的图像进行验证numVal = round(0.20 * numFiles);valIdx = shuffledIndices (numTrain + 1: numTrain + numVal);%剩余的用于测试。testIdx = shuffledIndices(numTrain + numVal + 1:结束);创建用于培训和测试的图像数据存储。trainingImages = imds.Files (trainingIdx);valImages = imds.Files (valIdx);testImages = imds.Files (testIdx);imdsTrain = imageDatastore (trainingImages);imdsVal = imageDatastore (valImages);imdsTest = imageDatastore (testImages);提取类和标签id信息。类= pxds.ClassNames;labelIDs = camvidPixelLabelIDs ();创建用于培训和测试的像素标签数据存储。trainingLabels = pxds.Files (trainingIdx);valLabels = pxds.Files (valIdx);testLabels = pxds.Files (testIdx);pxdsTrain = pixelLabelDatastore(训练标签、类、标签);pxdsVal = pixelLabelDatastore(valLabels, classes, labelid);pxdsTest = pixelLabelDatastore(testlabel, classes, labelid);结束

参考文献

[1]陈,梁杰等。“编码器 - 解码器与Atrous可分离卷积语义图像分割”。ECCV(2018)。

[2] Brostow, G. J., J. Fauqueur,和R. Cipolla。“视频中的语义对象类:高清地面真实数据库。”模式识别的字母。第30卷,2009年第2期,第88-97页。

另请参阅

||||||||||

相关话题