主要内容

基于深度学习的语义分割

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

语义分割网络对图像中的每个像素进行分类,从而对图像进行分类。语义分割的应用包括用于自动驾驶的道路分割和用于医疗诊断的癌细胞分割。想要了解更多,请看入门语义分割使用Deep学习

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

本示例使用CamVid数据集(2)来自剑桥大学的训练。该数据集是一个包含在驾驶时获得的街道级视图的图像集合。该数据集为包括汽车、行人和道路的32个语义类提供像素级标签。

设置

这个例子创建了Deeplab v3+网络,权值由预先训练的Resnet-18网络初始化。ResNet-18是一个高效的网络,非常适合处理资源有限的应用程序。根据应用需求,还可以使用其他预先训练过的网络,如MobileNet v2或ResNet-50。有关详细信息,请参见预训练深层神经网络(深度学习工具箱)

安装一个预先训练过的Resnet-18resnet18(深度学习工具箱).安装完成后,运行以下代码来验证安装是否正确。

resnet18 ();

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

pretrainedURL ='//www.tatmou.com/金宝appsupportfiles/vision/data/deeplabv3plusResnet18CamVid.mat';pretrainedFolder = fullfile (tempdir,'pretrainedNetwork');pretrainedNetwork = fullfile (pretrainedFolder,'deeplabv3plusResnet18CamVid.mat');如果〜存在(pretrainedNetwork,'文件'mkdir (pretrainedFolder);disp (“预训练下载网(58 MB)......”);websave (pretrainedNetwork pretrainedURL);终止

强烈推荐使用支持cuda的NVIDIA™GPU来运行此示例。使用GPU需要并行计算工具箱™。有关支持的计算能力的信息,请参见金宝appGPU支金宝app持情况(并行计算工具箱)

下载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(输出文件夹)显示(“下载16层MB CamVid数据集的标签......”);websave(labelsZip,labelURL);解压缩(labelsZip,fullfile)(outputFolder,'标签'));disp (“下载557 MB CamVid数据集图像……”);websave(imagesZip,imageURL);解压(imagesZip,fullfile)(outputFolder,“图片”));终止

注意:资料下载时间视乎阁下的互联网连接情况而定。上面使用的命令阻塞MATLAB,直到下载完成。或者,您可以使用web浏览器先将数据集下载到本地磁盘。要使用从网上下载的文件,请更改输出文件夹变量设置为下载文件的位置。

加载CamVid图片

使用imageDatastore加载CamVid图像。的imageDatastore使您能够在磁盘上高效地加载大量图像。

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

显示其中一个图像。

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

加载CamVid像素标记的图像

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

我们使培训更容易,我们将CamVid中的32个原始课程分为11个课程。指定这些类。

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

为了将32个类减少为11个,将原始数据集中的多个类分组在一起。例如,“Car”是“Car”、“SUVPickupTruck”、“Truck_Bus”、“Train”和“OtherMoving”的组合。使用支持函数返回分组的标签ID金宝app摄像机像素标签,在本例的最后列出。

labelIDs = camvidPixelLabelIDs ();

使用类和标签ID创建pixelLabelDatastore。

labelDir=fullfile(outputFolder,'标签');pxds=像素LabelDataStore(labelDir,类,LabelId);

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

C = readimage (pxds, 559);提出= 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);bar(1:numel(classes),frequency) xticks(1:numel(classes)) xticklabels(tbl.Name) xtickangle(45) ylabel('频率'

理想情况下,所有类别的观测值都是相等的。但是,CamVid中的类别是不平衡的,这是街道场景的汽车数据集中的一个常见问题。此类场景比行人和骑自行车的像素具有更多的天空、建筑和道路像素,因为天空、建筑和道路在图像中覆盖更多的区域。如果不进行处理,则坦率地说,这种不平衡可能对学习过程有害,因为学习偏向于占主导地位的类。在本例后面,您将使用类权重来处理此问题。

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

准备培训,验证和测试集

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

[imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = partioncamviddata (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。

%指定网络镜像大小。这通常与训练图像的大小相同。图像大小=[720 960 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⋮

指定使用的类权重像素分类层

pxLayer = pixelClassificationLayer(“名字”'标签'“班级”,tbl.Name,“类权重”, classWeights);lgraph = replaceLayer (lgraph,“分类”,px层);

选择培训选项

用于训练的优化算法为随动量随机梯度下降算法(SGDM)。使用trainingOptions(深度学习工具箱)来指定用于SGDM的超参数。

%定义验证数据。dsVal=联合收割机(imdsVal、pxdsVal);定义培训选项。选项= trainingOptions(“个”...“LearnRateSchedule”“分段”...'LearnRateDropPeriod'10,...“LearnRateDropFactor”,0.3,...“动力”,0.9,...“初始学习率”,1E-3,...“L2Regularization”, 0.005,...'ValidationData',dsVal,...'MaxEpochs'30,...“MiniBatchSize”8...“洗牌”“每个历元”...'CheckpointPath'tempdir,...“VerboseFrequency”,2,...“阴谋”“训练进度”...“ValidationPatience”4);

学习率采用分段计划。学习率每10个纪元降低0.3倍。这使得网络能够以较高的初始学习率快速学习,同时一旦学习率下降,就能够找到接近局部最优的解。

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

8个小批量用于减少训练时的内存使用。你可以根据你系统上的GPU内存数量增加或减少这个值。

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

数据增加

在训练过程中,通过随机变换原始数据来提高网络的精度。通过使用数据增广,可以在不增加已标记训练样本数量的情况下向训练数据添加更多种类。要对图像和像素标签数据应用相同的随机变换,请使用数据存储结合转变.首先,联合收割机imdsTrainpxdsTrain

dsTrain =结合(imdsTrain,pxdsTrain);

下一步,使用数据存储转变应用在支持函数中定义的所需数据增强金宝appaugmentImageAndLabel这里,随机左/右反射和+/-10像素的随机X/Y平移用于数据增强。

xTrans = [-10 10];yTrans = [-10 10];dsTrain = transform(dsTrain, @(数据)augmentImageAndLabel(数据,xTrans,yTrans));

注意,数据扩充并不适用于测试和验证数据。理想情况下,测试和验证数据应该能够代表原始数据,并且不作任何修改,以便进行公正的评估。

开始训练

开始培训使用列车网络(深度学习工具箱)如果溺爱国旗是正确的。否则,加载预训练的网络。

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

doTraining = FALSE;如果doTraining[net,info]=列车网络(dsTrain,lgraph,options);其他的数据=负荷(预训练网络);net=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指数。使用杰卡德用于测量IoU的函数。

借据= jaccard (C, expectedResult);表(类、借据)
ans =11×2表class iou ____________ _______“Sky”0.91837“Building”0.84479“Pole”0.31203“Road”0.93698“Pavement”0.82838“Tree”0.89636“SignSymbol”0.57644“Fence”0.71046“Car”0.66688“Pedestrian”0.48417“Bicyclist”0.68431

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

评估培训网络

为了测量多个测试图像,运行精度语义词组在整个测试集中。一个小批大小为4用于减少内存使用,而分割图像。你可以根据你系统上的GPU内存数量增加或减少这个值。

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

语义词组将测试集的结果作为pixelLabelDatastore目的。在每一个测试图像的实际像素标签数据IMD测试写入磁盘的位置由“WriteLocation”参数使用evaluateSemanticSegmentation度量测试集结果上的语义分割度量。

度量=评估语义分段(pxdsResults,pxdsTest,“详细”,错误的);

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

metrics.DataSetMetrics
ans =表1×5GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU MeanBFScore  ______________ ____________ _______ ___________ ___________ 0.87695 0.85392 0.6302 0.80851 0.65051

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

metrics.ClassMetrics
ans =11×3表精度借条MeanBFScore ________ _______ ___________天空0.93112 0.90209 0.8952大厦0.78453 0.76098 0.58511极0.71586 0.21477 0.51439路0.93024 0.91465 0.76696路面0.88466 0.70571 0.70919树0.87377 0.76323 0.70875 SignSymbol 0.79358 0.39309 0.48302栅栏0.81507 0.46484 0.48566汽车0.90956 0.76799 0.69233步行0.87629 0.4366 0.60792自行车运动员0.87844 0.60829 0.55089

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

金宝app支持功能

功能labelIDs=camvidPixelLabelIDs()%返回对应于每一类的标签的ID。CamVid数据集有32个类。将他们分成11个班%原始的SegNet培训方法[1]。%的11类是:%的“天空”“建筑”,“极”,“路”,“路面”、“树”、“SignSymbol”,%“栅栏”,“汽车”,“行人”和“自行车”。%CamVid像素标签ID作为RGB颜色值提供。把他们分成几个小组% 11类并将它们作为m × 3矩阵的单元格数组返回。的%原始CamVid类名在每个RGB值旁边列出。请注意%表示Other/Void类被排除在下面。labelIDs = {...%的“天空”[128 128 128;...%的“天空”% “建筑”[000 128 064;...% “桥”128 000 000;...% “建筑”064 192 000;...%的“墙”064 000 064;...%的“隧道”192 000 128;...%的“拱门”%“极点”[192 192 128;...%”Column_Pole”000 000 064;...% “交通拥挤”%的道路[128 064 128;...%“道路”128 000 192;...% “LaneMkgsDriv”192 000 064;...%”LaneMkgsNonDriv”%“路面”[000 000 192;...%“人行道”064 192 128;...% “ParkingBlock”128 128 192;...%”RoadShoulder”%的“树”[128 128 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;...%“卡车和公共汽车”192 064 128;...%“训练”128 064 064;...%“其他移动”%“行人”[064 064 000;...%“行人”192 128 064;...%的“孩子”064 000 192;...% “CartLuggagePram”064 128 064;...%的“动物”%“自行车”[000 128 192;...%“自行车”192 000 192;...% “MotorcycleScooter”]};终止
功能一会pixelLabelColorbar(提出)%添加一个颜色条到当前轴。颜色栏被格式化%以显示带有颜色的类名。颜色表(GCA,CMAP)%将颜色栏添加到当前图形。c = colorbar (“对等”,GCA);%用途类名的刻度线。c.TickLabels =一会;numClasses =大小(提出,1);%中心打勾标签。c、 Ticks=1/(numclass*2):1/numclass:1;%删除勾号。c.TickLength = 0;终止
功能cmap=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%骑自行车];% Normalize between[0 1]。cmap=cmap./255;终止
功能[imdsTrain,imdsVal,imdsTest,pxdsTrain,pxdsVal,pxdsTest]=分区摄像机数据(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=像素标签数据存储(培训标签、类、标签ID);pxdsVal=像素标签数据存储(标签、类、标签ID);pXDTest=像素标签数据存储(测试标签、类、标签ID);终止
功能data = augmentImageAndLabel(data, xTrans, yTrans)%增加图像和像素标签图像使用随机反射和%的翻译。对于i=1:大小(数据,1)t形式=随机仿射2d(...'XReflection',真的,...'XTranslation'xTrans,...“YTranslation”, yTrans);%将视图置于输出空间中图像的中心%允许平移将输出图像移出视图。rout = affineOutputView(size(data{i,1})), tform,“BoundsStyle”“中心输出”);%使用相同的变换扭曲图像和像素标签。Data {i,1} = imwarp(Data {i,1}, tform,)“OutputView”,溃败);Data {i,2} = imwarp(Data {i,2}, tform,)“OutputView”,溃败);终止终止

参考文献

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

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

另请参阅

||||||||(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)

相关话题