Семантическая Сегментация с Использованием Расширенных Сверток

Обучите сеть семантической сегментации с помощью расширенных сверток.

Семантическая сеть сегментации классифицирует каждый пиксель в изображении, получая к изображение, которое сегментировано по классам. Приложения для семантической сегментации включают сегментацию дорог для автономного управления автомобилем и сегментацию раковой клетки для медицинского диагностирования. Чтобы узнать больше, смотрите Начало работы с Семантической Сегментацией Используя Глубокое обучение.

Сети семантической сегментации как DeepLab [1] делают широкое применение расширенных сверток (также известный atrous свертки), потому что они могут увеличить восприимчивое поле слоя (область входа, который слои видят), не увеличивая число параметров или расчетов.

Загрузите обучающие данные

Пример использует простой набор данных 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.

Сегмент новое изображение

Считывание и отображение тестового изображения triangleTest.jpg.

imgTest = imread('triangleTest.jpg');
figure
imshow(imgTest)

Сегментируйте тестовое изображение с помощью semanticseg и отобразите результаты с помощью labeloverlay.

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