Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

使用扩张卷积进行语义分割

使用扩张卷积训练语义分割网络。

语义分割网络对图像中的每个像素进行分类,从而生成按类分割的图像。语义分割的应用包括自动驾驶中的道路分割以及医疗诊断中的癌细胞分割。要了解详细信息,请参阅Getting Started with Semantic Segmentation Using Deep Learning (Computer Vision Toolbox)

像 DeepLab [1] 这样的语义分割网络广泛使用扩张卷积(也称为空洞卷积),因为它们可以增加层的感受野(层可以看到的输入区域),而不增加参数或计算量。

加载训练数据

该示例使用 32×32 三角形图像的简单数据集进行说明。该数据集包括附带的像素标签真实值数据。使用 imageDatastorepixelLabelDatastore 加载训练数据。

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: {}

创建语义分割网络

此示例使用一个基于扩张卷积的简单语义分割网络。

创建一个用于训练数据的数据源,并获取每个标签的像素计数。

ds = combine(imdsTrain,pxdsTrain);
tbl = countEachLabel(pxdsTrain)
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(ds,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:01 |       91.62% |       1.6825 |          0.0010 |
|      17 |          50 |       00:00:16 |       88.56% |       0.2393 |          0.0010 |
|      34 |         100 |       00:00:30 |       92.08% |       0.1672 |          0.0010 |
|      50 |         150 |       00:00:42 |       93.17% |       0.1472 |          0.0010 |
|      67 |         200 |       00:00:54 |       94.15% |       0.1313 |          0.0010 |
|      84 |         250 |       00:01:13 |       94.47% |       0.1167 |          0.0010 |
|     100 |         300 |       00:01:32 |       95.04% |       0.1100 |          0.0010 |
|========================================================================================|
Training finished: Max epochs completed.

测试网络

加载测试数据。为图像创建一个 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)

Figure contains an axes object. The axes object contains an object of type image.

使用 semanticseg 分割测试图像,并使用 labeloverlay 显示结果。

C = semanticseg(imgTest,net);
B = labeloverlay(imgTest,C);
figure
imshow(B)

Figure contains an axes object. The axes object contains an object of type image.

另请参阅

(Computer Vision Toolbox) | (Computer Vision Toolbox) | (Computer Vision Toolbox) | (Image Processing Toolbox) | (Computer Vision Toolbox) | (Computer Vision Toolbox) | | | (Computer Vision Toolbox) |

相关主题