加载训练数据
该示例使用 32×32 三角形图像的简单数据集进行说明。该数据集包括附带的像素标签真实值数据。使用 imageDatastore 和 pixelLabelDatastore 加载训练数据。
dataFolder = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageFolderTrain = fullfile(dataFolder,'trainingImages');
labelFolderTrain = fullfile(dataFolder,'trainingLabels');
为图像创建一个 imageDatastore。
imdsTrain = imageDatastore(imageFolderTrain);
为真实值像素标签创建一个 pixelLabelDatastore。
classNames = ["triangle" "background"];
labels = [255 0];
pxdsTrain = pixelLabelDatastore(labelFolderTrain,classNames,labels)
pxdsTrain =
PixelLabelDatastore with properties:
Files: {200x1 cell}
ClassNames: {2x1 cell}
ReadSize: 1
ReadFcn: @readDatastoreImage
AlternateFileSystemRoots: {}
创建语义分割网络
此示例使用一个基于扩张卷积的简单语义分割网络。
创建一个用于训练数据的数据源,并获取每个标签的像素计数。
pximdsTrain = pixelLabelImageDatastore(imdsTrain,pxdsTrain);
tbl = countEachLabel(pximdsTrain)
tbl=2×3 table
Name PixelCount ImagePixelCount
______________ __________ _______________
{'triangle' } 10326 2.048e+05
{'background'} 1.9447e+05 2.048e+05
大多数像素标签用于背景。这种类不平衡使学习过程偏向主导类。要解决此问题,请使用类权重来平衡各类。您可以使用几种方法来计算类权重。一种常见的方法是逆频率加权,其中类权重是类频率的倒数。此方法会增加指定给表示不足的类的权重。使用逆频率加权计算类权重。
numberPixels = sum(tbl.PixelCount);
frequency = tbl.PixelCount / numberPixels;
classWeights = 1 ./ frequency;
使用输入大小对应于输入图像大小的图像输入层创建一个用于像素分类的网络。接下来,指定对应于卷积层、批量归一化层和 ReLU 层的三个块。对于每个卷积层,指定 32 个具有递增扩张系数的 3×3 过滤器,并通过将 'Padding' 选项设置为 'same' 来填充输入以使输入的大小与输出相同。要对像素进行分类,请包括一个具有 K 个 1×1 卷积的卷积层(其中 K 是类的数量),其后是一个 softmax 层和一个具有逆类权重的 pixelClassificationLayer。
inputSize = [32 32 1];
filterSize = 3;
numFilters = 32;
numClasses = numel(classNames);
layers = [
imageInputLayer(inputSize)
convolution2dLayer(filterSize,numFilters,'DilationFactor',1,'Padding','same')
batchNormalizationLayer
reluLayer
convolution2dLayer(filterSize,numFilters,'DilationFactor',2,'Padding','same')
batchNormalizationLayer
reluLayer
convolution2dLayer(filterSize,numFilters,'DilationFactor',4,'Padding','same')
batchNormalizationLayer
reluLayer
convolution2dLayer(1,numClasses)
softmaxLayer
pixelClassificationLayer('Classes',classNames,'ClassWeights',classWeights)];
训练网络
指定训练选项。
options = trainingOptions('sgdm', ...
'MaxEpochs', 100, ...
'MiniBatchSize', 64, ...
'InitialLearnRate', 1e-3);
使用 trainNetwork 训练网络。
net = trainNetwork(pximdsTrain,layers,options);
Training on single CPU.
Initializing input data normalization.
|========================================================================================|
| Epoch | Iteration | Time Elapsed | Mini-batch | Mini-batch | Base Learning |
| | | (hh:mm:ss) | Accuracy | Loss | Rate |
|========================================================================================|
| 1 | 1 | 00:00:00 | 91.62% | 1.6825 | 0.0010 |
| 17 | 50 | 00:00:10 | 88.56% | 0.2393 | 0.0010 |
| 34 | 100 | 00:00:19 | 92.08% | 0.1672 | 0.0010 |
| 50 | 150 | 00:00:30 | 93.17% | 0.1472 | 0.0010 |
| 67 | 200 | 00:00:39 | 94.15% | 0.1313 | 0.0010 |
| 84 | 250 | 00:00:47 | 94.47% | 0.1167 | 0.0010 |
| 100 | 300 | 00:00:55 | 95.04% | 0.1100 | 0.0010 |
|========================================================================================|
测试网络
加载测试数据。为图像创建一个 imageDatastore。为真实值像素标签创建一个 pixelLabelDatastore。
imageFolderTest = fullfile(dataFolder,'testImages');
imdsTest = imageDatastore(imageFolderTest);
labelFolderTest = fullfile(dataFolder,'testLabels');
pxdsTest = pixelLabelDatastore(labelFolderTest,classNames,labels);
使用测试数据和经过训练的网络进行预测。
pxdsPred = semanticseg(imdsTest,net,'MiniBatchSize',32,'WriteLocation',tempdir);
Running semantic segmentation network
-------------------------------------
* Processed 100 images.
使用 evaluateSemanticSegmentation 评估预测准确度。
metrics = evaluateSemanticSegmentation(pxdsPred,pxdsTest);
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: global accuracy, class accuracy, IoU, weighted IoU, BF score.
* Processed 100 images.
* Finalizing... Done.
* Data set metrics:
GlobalAccuracy MeanAccuracy MeanIoU WeightedIoU MeanBFScore
______________ ____________ _______ ___________ ___________
0.95237 0.97352 0.72081 0.92889 0.46416
有关评估语义分割网络的详细信息,请参阅evaluateSemanticSegmentation(Computer Vision Toolbox)。
分割新图像
读取并显示测试图像 triangleTest.jpg。
imgTest = imread('triangleTest.jpg');
figure
imshow(imgTest)
使用 semanticseg 分割测试图像,并使用 labeloverlay 显示结果。
C = semanticseg(imgTest,net);
B = labeloverlay(imgTest,C);
figure
imshow(B)