pixelLabelImageDatastore

Datastore для семантических сетей сегментации

Описание

Используйте pixelLabelImageDatastore, чтобы создать datastore для обучения семантическая сеть сегментации использование глубокого обучения.

Создание

Синтаксис

pximds = pixelLabelImageDatastore(gTruth)
pximds = pixelLabelImageDatastore(imds,pxds)
pximds = pixelLabelImageDatastore(___,Name,Value)

Описание

пример

pximds = pixelLabelImageDatastore(gTruth) возвращает datastore для того, чтобы обучить семантическую сеть сегментации на основе объекта входа groundTruth или массива объектов groundTruth. Используйте объект вывода pixelLabelImageDatastore с функцией Deep Learning Toolbox™ trainNetwork, чтобы обучить сверточные нейронные сети для семантической сегментации.

pximds = pixelLabelImageDatastore(imds,pxds) возвращает datastore на основе входного datastore изображений и пиксельных объектов datastore метки. imds является объектом ImageDatastore, который представляет учебный вход сети. pxds является объектом PixelLabelDatastore, который представляет необходимый сетевой вывод.

pximds = pixelLabelImageDatastore(___,Name,Value) дополнительно пары "имя-значение" использования, чтобы установить свойства DispatchInBackground и OutputSizeMode. Для 2D данных можно также использовать пары "имя-значение", чтобы задать ColorPreprocessing, DataAugmentation и свойства увеличения OutputSize. Можно задать несколько пар "имя-значение". Заключите каждое имя свойства в кавычки.

Например, pixelLabelImageDatastore(gTruth,'PatchesPerImage',40) создает пиксельный datastore метки изображений, который случайным образом генерирует 40 закрашенных фигур от каждого наземного объекта истины в gTruth.

Входные параметры

развернуть все

Оснуйте данные об истине, заданные как объект groundTruth или как массив объектов groundTruth. Каждый объект groundTruth содержит информацию об источнике данных, списке определений метки и всех отмеченных метках для набора заземляющих меток истины.

Набор изображений, заданных как объект ImageDatastore.

Набор пикселя маркировал изображения, заданные как объект PixelLabelDatastore. Объект содержит пиксель маркированные изображения для каждого изображения, содержавшегося во входном объекте imds.

Свойства

развернуть все

Это свойство доступно только для чтения.

Имена файла образа, используемые в качестве источника для наземных изображений истины, заданных как вектор символов или массив ячеек из символьных векторов.

Это свойство доступно только для чтения.

Имена файла данных метки Pixel, используемые в качестве источника для наземной истины, маркируют изображения, заданные как символ или массив ячеек символов.

Это свойство доступно только для чтения.

Имена классов, заданные как массив ячеек из символьных векторов.

Предварительная обработка цветового канала для 2D данных, заданных как 'none', 'gray2rgb' или 'rgb2gray'. Используйте это свойство, когда вам нужны данные изображения, созданные по условию, источник должен быть только цветной или шкалой полутонов, но набор обучающих данных включает обоих. Предположим, что необходимо обучить сеть, которая ожидает цветные изображения, но некоторые учебные изображения являются шкалой полутонов. Установите ColorPreprocessing на 'gray2rgb' реплицировать цветовые каналы полутоновых изображений во входном наборе изображений. Используя 'gray2rgb' опция создает M-by-N-by-3 выходные изображения.

Свойство ColorPreprocessing не поддержано для 3-D данных. Чтобы выполнить предварительную обработку цветового канала 3-D данных, используйте функцию transform.

Предварительная обработка примененного к входным изображениям, заданным как объект imageDataAugmenter или 'none'. Когда DataAugmentation является 'none', никакая предварительная обработка не применяется, чтобы ввести изображения. Данные тренировки могут быть увеличены в режиме реального времени во время обучения.

Свойство DataAugmentation не поддержано для 3-D данных. Чтобы предварительно обработать 3-D данные, используйте функцию transform.

Диспетчеризируйте наблюдения в фоновом режиме во время обучения, прогноза и классификации, заданной как false или true. Чтобы использовать фоновую диспетчеризацию, у вас должен быть Parallel Computing Toolbox™. Если DispatchInBackground является true, и у вас есть Parallel Computing Toolbox, то pixelLabelImageDatastore асинхронно читает закрашенные фигуры, добавляет шум, и очереди исправляют пары.

Это свойство доступно только для чтения.

Количество наблюдений, которые возвращены в каждом пакете. Для обучения, прогноза или классификации, свойство MiniBatchSize установлено в мини-пакетный размер, заданный в trainingOptions.

Это свойство доступно только для чтения.

Общее количество наблюдений в шумоподавлении отображает datastore. Количество наблюдений является продолжительностью одной учебной эпохи.

Это свойство доступно только для чтения.

Размер выходных изображений, заданных как вектор двух положительных целых чисел. Первый элемент задает количество строк в выходных изображениях, и второй элемент задает количество столбцов. Когда вы задаете OutputSize, размеры изображения настроены по мере необходимости. По умолчанию это свойство пусто, что означает, что изображения не настроены.

Свойство OutputSize не поддержано для 3-D данных. Чтобы установить выходной размер 3-D данных, используйте функцию transform.

Метод раньше изменял размер выходных изображений, заданных как одно из следующих. Это свойство применяется только, когда вы устанавливаете OutputSize на значение кроме [].

  • 'resize' — Масштабируйте изображение, чтобы соответствовать выходному размеру. Для получения дополнительной информации смотрите imresize.

  • 'centercrop' — Возьмите обрезку из центра учебного изображения. Обрезка имеет тот же размер как выходной размер.

  • 'randcrop' — Возьмите случайную обрезку из учебного изображения. Случайная обрезка имеет тот же размер как выходной размер.

Типы данных: char | string

Функции объекта

combineОбъедините данные от нескольких datastores
countEachLabelСчитайте вхождение пиксельной метки для изображений источника данных
hasdataОпределите, доступны ли данные для чтения
partitionByIndexРаздел pixelLabelImageDatastore согласно индексам
previewПодмножество данных в datastore
readСчитайте данные из pixelLabelImageDatastore
readallСчитывайте все данные в datastore
readByIndexСчитайте данные, заданные индексом от pixelLabelImageDatastore
resetСброс Datastore к начальному состоянию
shuffleПереставьте данные в pixelLabelImageDatastore
transformПреобразуйте datastore

Примеры

свернуть все

Загрузите данные тренировки.

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageDir = fullfile(dataSetDir,'trainingImages');
labelDir = fullfile(dataSetDir,'trainingLabels');

Создайте datastore изображений для изображений.

imds = imageDatastore(imageDir);

Создайте pixelLabelDatastore для заземляющих пиксельных меток истины.

classNames = ["triangle","background"];
labelIDs   = [255 0];
pxds = pixelLabelDatastore(labelDir,classNames,labelIDs);

Визуализируйте учебные изображения и заземляющие пиксельные метки истины.

I = read(imds);
C = read(pxds);

I = imresize(I,5);
L = imresize(uint8(C),5);
imshowpair(I,L,'montage')

Создайте семантическую сеть сегментации. Эта сеть использует простую семантическую сеть сегментации на основе субдискретизации и повышающей дискретизации проекта.

numFilters = 64;
filterSize = 3;
numClasses = 2;
layers = [
    imageInputLayer([32 32 1])
    convolution2dLayer(filterSize,numFilters,'Padding',1)
    reluLayer()
    maxPooling2dLayer(2,'Stride',2)
    convolution2dLayer(filterSize,numFilters,'Padding',1)
    reluLayer()
    transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);
    convolution2dLayer(1,numClasses);
    softmaxLayer()
    pixelClassificationLayer()
    ]
layers = 
  10x1 Layer array with layers:

     1   ''   Image Input                  32x32x1 images with 'zerocenter' normalization
     2   ''   Convolution                  64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     3   ''   ReLU                         ReLU
     4   ''   Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     5   ''   Convolution                  64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     6   ''   ReLU                         ReLU
     7   ''   Transposed Convolution       64 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
     8   ''   Convolution                  2 1x1 convolutions with stride [1  1] and padding [0  0  0  0]
     9   ''   Softmax                      softmax
    10   ''   Pixel Classification Layer   Cross-entropy loss 

Опции обучения Setup.

opts = trainingOptions('sgdm', ...
    'InitialLearnRate',1e-3, ...
    'MaxEpochs',100, ...
    'MiniBatchSize',64);

Создайте пиксельный datastore метки изображений, который содержит данные тренировки.

trainingData = pixelLabelImageDatastore(imds,pxds);

Обучите сеть.

net = trainNetwork(trainingData,layers,opts);
Training on single GPU.
Initializing image normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       31.86% |       0.6934 |          0.0010 |
|      17 |          50 |       00:00:03 |       94.52% |       0.5564 |          0.0010 |
|      34 |         100 |       00:00:07 |       95.25% |       0.4415 |          0.0010 |
|      50 |         150 |       00:00:11 |       95.14% |       0.3722 |          0.0010 |
|      67 |         200 |       00:00:14 |       94.52% |       0.3336 |          0.0010 |
|      84 |         250 |       00:00:18 |       95.25% |       0.2931 |          0.0010 |
|     100 |         300 |       00:00:21 |       95.14% |       0.2708 |          0.0010 |
|========================================================================================|

Считайте и отобразите тестовое изображение.

testImage = imread('triangleTest.jpg');
imshow(testImage)

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

C = semanticseg(testImage,net);
B = labeloverlay(testImage,C);
imshow(B)

Улучшите результаты

Сеть не удалась сегментировать треугольники и классифицировала каждый пиксель как "фон". Обучение, казалось, подходило к учебной точности, больше, чем 90%. Однако сеть только училась классифицировать фоновый класс. Чтобы понять, почему это произошло, можно считать вхождение каждой пиксельной метки через набор данных.

tbl = countEachLabel(trainingData)
tbl=2×3 table
        Name        PixelCount    ImagePixelCount
    ____________    __________    _______________

    'triangle'           10326       2.048e+05   
    'background'    1.9447e+05       2.048e+05   

Большинство пиксельных меток для фона. Плохие результаты происходят из-за неустойчивости класса. Неустойчивость класса смещает процесс обучения в пользу доминирующего класса. Вот почему каждый пиксель классифицируется как "фон". Чтобы зафиксировать это, используйте взвешивание класса, чтобы сбалансировать классы. Существует несколько методов для вычислительных весов класса. Одна общепринятая методика является обратным взвешиванием частоты, где веса класса являются инверсией частот класса. Это увеличивает вес, данный недостаточно представленным классам.

totalNumberOfPixels = sum(tbl.PixelCount);
frequency = tbl.PixelCount / totalNumberOfPixels;
classWeights = 1./frequency
classWeights = 2×1

   19.8334
    1.0531

Веса класса могут быть заданы с помощью pixelClassificationLayer. Обновите последний слой, чтобы использовать pixelClassificationLayer с обратными весами класса.

layers(end) = pixelClassificationLayer('Classes',tbl.Name,'ClassWeights',classWeights);

Обучите сеть снова.

net = trainNetwork(trainingData,layers,opts);
Training on single GPU.
Initializing image normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       47.50% |       0.6925 |          0.0010 |
|      17 |          50 |       00:00:04 |       19.67% |       0.6837 |          0.0010 |
|      34 |         100 |       00:00:08 |       75.77% |       0.4433 |          0.0010 |
|      50 |         150 |       00:00:12 |       85.00% |       0.4018 |          0.0010 |
|      67 |         200 |       00:00:16 |       87.00% |       0.3568 |          0.0010 |
|      84 |         250 |       00:00:20 |       88.03% |       0.3153 |          0.0010 |
|     100 |         300 |       00:00:24 |       90.42% |       0.2890 |          0.0010 |
|========================================================================================|

Попытайтесь сегментировать тестовое изображение снова.

C = semanticseg(testImage,net);
B = labeloverlay(testImage,C);
imshow(B)

Используя взвешивание класса, чтобы сбалансировать классы привел к лучшему результату сегментации. Дополнительные шаги, чтобы улучшить результаты включают увеличение числа эпох, используемых для обучения, добавления большего количества данных тренировки или изменения сети.

Сконфигурируйте пиксельный datastore метки изображений, чтобы увеличить данные в то время как обучение.

Загрузите учебные изображения и пиксельные метки.

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageDir = fullfile(dataSetDir,'trainingImages');
labelDir = fullfile(dataSetDir,'trainingLabels');

Создайте объект imageDatastore содержать учебные изображения.

imds = imageDatastore(imageDir);

Задайте имена классов и их связанную метку IDs.

classNames = ["triangle","background"];
labelIDs   = [255 0];

Создайте объект pixelLabelDatastore содержать заземляющие пиксельные метки истины для учебных изображений.

pxds = pixelLabelDatastore(labelDir, classNames, labelIDs);

Создайте объект imageDataAugmenter случайным образом вращаться и данные о зеркальном отображении.

augmenter = imageDataAugmenter('RandRotation',[-10 10],'RandXReflection',true)
augmenter = 
  imageDataAugmenter with properties:

           FillValue: 0
     RandXReflection: 1
     RandYReflection: 0
        RandRotation: [-10 10]
           RandScale: [1 1]
          RandXScale: [1 1]
          RandYScale: [1 1]
          RandXShear: [0 0]
          RandYShear: [0 0]
    RandXTranslation: [0 0]
    RandYTranslation: [0 0]

Создайте объект pixelLabelImageDatastore обучить сеть с увеличенными данными.

plimds = pixelLabelImageDatastore(imds,pxds,'DataAugmentation',augmenter)
plimds = 
  pixelLabelImageDatastore with properties:

                  Images: {200x1 cell}
          PixelLabelData: {200x1 cell}
              ClassNames: {2x1 cell}
        DataAugmentation: [1x1 imageDataAugmenter]
      ColorPreprocessing: 'none'
              OutputSize: []
          OutputSizeMode: 'resize'
           MiniBatchSize: 1
         NumObservations: 200
    DispatchInBackground: 0

Этот пример показывает, как задать и создать пользовательский слой классификации пикселей, который использует потерю Игры в кости.

Этот слой может использоваться, чтобы обучить семантические сети сегментации. Чтобы узнать больше о создании пользовательских слоев глубокого обучения, смотрите, Задают Пользовательские Слои Глубокого обучения (Deep Learning Toolbox).

Поставьте на карту потерю

Потеря Игры в кости основана на коэффициенте подобия Sørensen-игры-в-кости для измерения перекрытия между двумя сегментированными изображениями. Обобщенная потеря Игры в кости [1,2], L, поскольку между одним изображением Y и соответствующая наземная истина T дают

L=1-2k=1Kwkm=1MYкмTкмk=1Kwkm=1MYкм2+Tкм2 ,

где K количество классов, M число элементов по первым двум измерениям Y, иwk класс определенный фактор взвешивания, который управляет вкладом, который каждый класс делает к потере. wk обычно обратная область ожидаемой области:

wk=1(m=1MTкм)2

Это взвешивание помогает противостоять влиянию более крупных областей на счете Игры в кости, облегчающем для сети изучить, как сегментировать меньшие области.

Шаблон слоя классификации

Скопируйте шаблон слоя классификации в новый файл в MATLAB®. Этот шаблон обрисовывает в общих чертах структуру слоя классификации и включает функции, которые задают поведение слоя. Остальная часть примера показывает, как завершить dicePixelClassificationLayer.

classdef dicePixelClassificationLayer < nnet.layer.ClassificationLayer

   properties
      % Optional properties
   end

   methods

        function loss = forwardLoss(layer, Y, T)
            % Layer forward loss function goes here.
        end
        
        function dLdY = backwardLoss(layer, Y, T)
            % Layer backward loss function goes here.
        end
    end
end

Объявите свойства слоя

По умолчанию пользовательские выходные слои имеют следующие свойства:

  • Имя Имя слоя, заданное как вектор символов или скаляр строки. Чтобы включать этот слой в график слоя, необходимо задать непустое уникальное имя слоя. Если вы обучаете серийную сеть с этим слоем, и Name установлен в '', то программное обеспечение автоматически присваивает имя в учебное время.

  • Описание Короткое описание слоя, заданного как вектор символов или скаляр строки. Это описание появляется, когда слой отображен в массиве Layer. Если вы не задаете описание слоя, то программное обеспечение отображает имя класса слоя.

  • Ввод Тип слоя, заданного как вектор символов или скаляр строки. Значение Type появляется, когда слой отображен в массиве Layer. Если вы не задаете тип слоя, то программное обеспечение отображает 'Classification layer' или 'Regression layer'.

Пользовательские слои классификации также имеют следующее свойство:

  • Классы Классы выходного слоя, заданного как категориальный вектор, массив строк, массив ячеек из символьных векторов или 'auto'. Если Classes является 'auto', то программное обеспечение автоматически устанавливает классы в учебное время. Если вы задаете массив строк или массив ячеек из символьных векторов str, то программное обеспечение устанавливает классы выходного слоя к categorical(str,str). Значением по умолчанию является 'auto'.

Если слой не имеет никаких других свойств, то можно не использовать раздел properties.

Потеря Игры в кости требует, чтобы маленькое постоянное значение предотвратило деление на нуль. Задайте свойство, Epsilon, чтобы содержать это значение.

classdef dicePixelClassificationLayer < nnet.layer.ClassificationLayer

    properties(Constant)
       % Small constant to prevent division by zero. 
       Epsilon = 1e-8;

    end

    ...
end

Создайте функцию конструктора

Создайте функцию, которая создает слой и инициализирует свойства слоя. Задайте любые переменные, требуемые создать слой как входные параметры к функции конструктора.

Задайте дополнительное имя входного параметра, чтобы присвоить свойству Name при создании.

        function layer = dicePixelClassificationLayer(name)
            % layer =  dicePixelClassificationLayer(name) creates a Dice
            % pixel classification layer with the specified name.
            
            % Set layer name.          
            layer.Name = name;
            
            % Set layer description.
            layer.Description = 'Dice loss';
        end

Создайте прямую функцию потерь

Создайте функцию с именем forwardLoss, который возвращает взвешенную перекрестную энтропийную потерю между прогнозами, сделанными сетью и учебными целями. Синтаксисом для forwardLoss является loss = forwardLoss(layer, Y, T), где Y является вывод предыдущего слоя, и T представляет учебные цели.

Для семантических проблем сегментации размерности T совпадают с размерностью Y, где Y является 4-D массивом размера H-by-W-by-K-by-N, где K является количеством классов, и N является мини-пакетным размером.

Размер Y зависит от вывода предыдущего слоя. Чтобы гарантировать, что Y одного размера как T, необходимо включать слой, который выводит правильный размер перед выходным слоем. Например, чтобы гарантировать, что Y является 4-D массивом музыки прогноза к классам K, можно включать полносвязный слой размера K или сверточный слой с фильтрами K, сопровождаемыми softmax слоем перед выходным слоем.

        function loss = forwardLoss(layer, Y, T)
            % loss = forwardLoss(layer, Y, T) returns the Dice loss between
            % the predictions Y and the training targets T.   

            % Weights by inverse of region size.
            W = 1 ./ sum(sum(T,1),2).^2;
            
            intersection = sum(sum(Y.*T,1),2);
            union = sum(sum(Y.^2 + T.^2, 1),2);          
            
            numer = 2*sum(W.*intersection,3) + layer.Epsilon;
            denom = sum(W.*union,3) + layer.Epsilon;
            
            % Compute Dice score.
            dice = numer./denom;
            
            % Return average Dice loss.
            N = size(Y,4);
            loss = sum((1-dice))/N;
            
        end

Создайте обратную функцию потерь

Создайте обратную функцию потерь, которая возвращает производные потери Игры в кости относительно прогнозов Y. Синтаксисом для backwardLoss является loss = backwardLoss(layer, Y, T), где Y является вывод предыдущего слоя, и T представляет учебные цели.

Размерности Y и T совпадают с входными параметрами в forwardLoss.

        function dLdY = backwardLoss(layer, Y, T)
            % dLdY = backwardLoss(layer, Y, T) returns the derivatives of
            % the Dice loss with respect to the predictions Y.
            
            % Weights by inverse of region size.
            W = 1 ./ sum(sum(T,1),2).^2;
            
            intersection = sum(sum(Y.*T,1),2);
            union = sum(sum(Y.^2 + T.^2, 1),2);
     
            numer = 2*sum(W.*intersection,3) + layer.Epsilon;
            denom = sum(W.*union,3) + layer.Epsilon;
            
            N = size(Y,4);
      
            dLdY = (2*W.*Y.*numer./denom.^2 - 2*W.*T./denom)./N;
        end

Завершенный слой

Завершенный слой обеспечивается в dicePixelClassificationLayer.m.

classdef dicePixelClassificationLayer < nnet.layer.ClassificationLayer
    % This layer implements the generalized dice loss function for training
    % semantic segmentation networks.
    
    properties(Constant)
        % Small constant to prevent division by zero. 
        Epsilon = 1e-8;
    end
    
    methods
        
        function layer = dicePixelClassificationLayer(name)
            % layer =  dicePixelClassificationLayer(name) creates a Dice
            % pixel classification layer with the specified name.
            
            % Set layer name.          
            layer.Name = name;
            
            % Set layer description.
            layer.Description = 'Dice loss';
        end
        
        
        function loss = forwardLoss(layer, Y, T)
            % loss = forwardLoss(layer, Y, T) returns the Dice loss between
            % the predictions Y and the training targets T.   

            % Weights by inverse of region size.
            W = 1 ./ sum(sum(T,1),2).^2;
            
            intersection = sum(sum(Y.*T,1),2);
            union = sum(sum(Y.^2 + T.^2, 1),2);          
            
            numer = 2*sum(W.*intersection,3) + layer.Epsilon;
            denom = sum(W.*union,3) + layer.Epsilon;
            
            % Compute Dice score.
            dice = numer./denom;
            
            % Return average Dice loss.
            N = size(Y,4);
            loss = sum((1-dice))/N;
            
        end
        
        function dLdY = backwardLoss(layer, Y, T)
            % dLdY = backwardLoss(layer, Y, T) returns the derivatives of
            % the Dice loss with respect to the predictions Y.
            
            % Weights by inverse of region size.
            W = 1 ./ sum(sum(T,1),2).^2;
            
            intersection = sum(sum(Y.*T,1),2);
            union = sum(sum(Y.^2 + T.^2, 1),2);
     
            numer = 2*sum(W.*intersection,3) + layer.Epsilon;
            denom = sum(W.*union,3) + layer.Epsilon;
            
            N = size(Y,4);
      
            dLdY = (2*W.*Y.*numer./denom.^2 - 2*W.*T./denom)./N;
        end
    end
end

Совместимость графического процессора

Для совместимости графического процессора функции уровня должны поддержать входные параметры и возвратить выходные параметры типа gpuArray. Любые другие функции, используемые слоем, должны сделать то же самое.

Функции MATLAB использовали в forwardLoss и backwardLoss в dicePixelClassificationLayer вся поддержка входные параметры gpuArray, таким образом, слоем является совместимый графический процессор.

Проверяйте Выходную валидность слоя

Создайте экземпляр слоя.

layer = dicePixelClassificationLayer('dice');

Проверяйте валидность слоя слоя с помощью checkLayer. Задайте допустимый входной размер, чтобы быть размером одного наблюдения за типичным входом к слою. Слой ожидает H-by-W-by-K-by-N входные параметры массивов, где K является количеством классов, и N является количеством наблюдений в мини-пакете.

numClasses = 2;
validInputSize = [4 4 numClasses];
checkLayer(layer,validInputSize, 'ObservationDimension',4)
Running nnet.checklayer.OutputLayerTestCase
.......... .......
Done nnet.checklayer.OutputLayerTestCase
__________

Test Summary:
	 17 Passed, 0 Failed, 0 Incomplete, 0 Skipped.
	 Time elapsed: 1.6227 seconds.

Тестовые сводные отчеты количество переданных, отказавших, неполные, и пропущенные тесты.

Используйте пользовательский слой в семантической сети сегментации

Создайте семантическую сеть сегментации, которая использует dicePixelClassificationLayer.

layers = [
    imageInputLayer([32 32 1])
    convolution2dLayer(3,64,'Padding',1)
    reluLayer
    maxPooling2dLayer(2,'Stride',2)
    convolution2dLayer(3,64,'Padding',1)
    reluLayer
    transposedConv2dLayer(4,64,'Stride',2,'Cropping',1)
    convolution2dLayer(1,2)
    softmaxLayer
    dicePixelClassificationLayer('dice')]
layers = 
  10x1 Layer array with layers:

     1   ''       Image Input              32x32x1 images with 'zerocenter' normalization
     2   ''       Convolution              64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     3   ''       ReLU                     ReLU
     4   ''       Max Pooling              2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     5   ''       Convolution              64 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     6   ''       ReLU                     ReLU
     7   ''       Transposed Convolution   64 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
     8   ''       Convolution              2 1x1 convolutions with stride [1  1] and padding [0  0  0  0]
     9   ''       Softmax                  softmax
    10   'dice'   Classification Output    Dice loss

Загрузите данные тренировки для семантической сегментации с помощью imageDatastore и pixelLabelDatastore.

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageDir = fullfile(dataSetDir,'trainingImages');
labelDir = fullfile(dataSetDir,'trainingLabels');

imds = imageDatastore(imageDir);

classNames = ["triangle" "background"];
labelIDs = [255 0];
pxds = pixelLabelDatastore(labelDir, classNames, labelIDs);

Сопоставьте изображение и пиксельные данные о метке с помощью pixelLabelImageDatastore.

ds = pixelLabelImageDatastore(imds,pxds);

Установите опции обучения и обучите сеть.

options = trainingOptions('sgdm', ...
    'InitialLearnRate',1e-2, ...
    'MaxEpochs',100, ...
    'LearnRateDropFactor',1e-1, ...
    'LearnRateDropPeriod',50, ...
    'LearnRateSchedule','piecewise', ...
    'MiniBatchSize',128);

net = trainNetwork(ds,layers,options);
Training on single GPU.
Initializing image normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:03 |       27.89% |       0.8346 |          0.0100 |
|      50 |          50 |       00:00:34 |       89.67% |       0.6384 |          0.0100 |
|     100 |         100 |       00:01:09 |       94.35% |       0.5024 |          0.0010 |
|========================================================================================|

Оцените обучивший сеть путем сегментации тестового изображения и отображения результата сегментации.

I = imread('triangleTest.jpg');

[C,scores] = semanticseg(I,net);

B = labeloverlay(I,C);
figure
imshow(imtile({I,B}))

Ссылки

  1. Crum, Уильям Р., Оскар Камара и Дерек ЛГ Хилл. "Обобщенное перекрытие измеряется для оценки и валидации в медицинском анализе изображения". Транзакции IEEE на медицинской обработке изображений 25.11 (2006): 1451-1461.

  2. Sudre, Кэрол Х., и др. "Обобщенные Игры в кости накладываются как функция потерь глубокого обучения для очень несбалансированных сегментаций". Глубокое обучение в Медицинском Анализе изображения и Многомодальном Изучении для Клинической Поддержки принятия решений. Спрингер, Хан, 2017. 240-248.

Этот пример показывает, как обучить семантическую сеть сегментации использование расширенных сверток.

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

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

Загрузите данные тренировки

Пример использует простой набор данных 32x32 треугольные изображения в целях рисунка. Набор данных включает сопроводительные пиксельные наземные данные об истине метки. Загрузите данные тренировки с помощью imageDatastore и pixelLabelDatastore.

dataFolder = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageFolderTrain = fullfile(dataFolder,'trainingImages');
labelFolderTrain = fullfile(dataFolder,'trainingLabels');

Создайте datastore изображений для изображений.

imdsTrain = imageDatastore(imageFolderTrain);

Создайте pixelLabelDatastore для заземляющих пиксельных меток истины.

classNames = ["triangle" "background"];
labels = [255 0];
pxdsTrain = pixelLabelDatastore(labelFolderTrain,classNames,labels)
pxdsTrain = 
  PixelLabelDatastore with properties:

                       Files: {200×1 cell}
                  ClassNames: {2×1 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;

Создайте сеть для пикселя classificaiton с входным слоем изображений с входным размером, соответствующим размеру входных изображений. Затем, задайте три блока свертки, обработайте в пакетном режиме нормализацию и слои 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)];

Обучение сети

Задайте опции обучения. Используя решатель SGDM, обучайтесь в течение 100 эпох, мини-пакетный размер 64, и изучите уровень 0.001.

options = trainingOptions('sgdm', ...
    'MaxEpochs', 100, ...
    'MiniBatchSize', 64, ... 
    'InitialLearnRate', 1e-3);

Обучите сеть с помощью trainNetwork.

net = trainNetwork(pximdsTrain,layers,options);
Training on single GPU.
Initializing image normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       67.54% |       0.7098 |          0.0010 |
|      17 |          50 |       00:00:03 |       84.60% |       0.3851 |          0.0010 |
|      34 |         100 |       00:00:06 |       89.85% |       0.2536 |          0.0010 |
|      50 |         150 |       00:00:09 |       93.39% |       0.1959 |          0.0010 |
|      67 |         200 |       00:00:11 |       95.89% |       0.1559 |          0.0010 |
|      84 |         250 |       00:00:14 |       97.29% |       0.1188 |          0.0010 |
|     100 |         300 |       00:00:18 |       98.28% |       0.0970 |          0.0010 |
|========================================================================================|

Тестирование сети

Загрузите тестовые данные. Создайте datastore изображений для изображений. Создайте pixelLabelDatastore для заземляющих пиксельных меток истины.

imageFolderTest = fullfile(dataFolder,'testImages');
imdsTest = imageDatastore(imageFolderTest);
labelFolderTest = fullfile(dataFolder,'testLabels');
pxdsTest = pixelLabelDatastore(labelFolderTest,classNames,labels);

Сделайте прогнозы с помощью тестовых данных, и обучил сеть.

pxdsPred = semanticseg(imdsTest,net,'WriteLocation',tempdir);
Running semantic segmentation network
-------------------------------------
* Processing 100 images.
* Progress: 100.00%

Оцените точность прогноза с помощью evaluateSemanticSegmentation.

metrics = evaluateSemanticSegmentation(pxdsPred,pxdsTest);
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: global accuracy, class accuracy, IoU, weighted IoU, BF score.
* Processing 100 images...
[==================================================] 100%
Elapsed time: 00:00:00
Estimated time remaining: 00:00:00
* Finalizing... Done.
* Data set metrics:

    GlobalAccuracy    MeanAccuracy    MeanIoU    WeightedIoU    MeanBFScore
    ______________    ____________    _______    ___________    ___________

       0.98334          0.99107       0.85869      0.97109        0.68197  

Для получения дополнительной информации об оценке семантических сетей сегментации смотрите evaluateSemanticSegmentation.

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

Читайте и отобразитесь, тест отображают triangleTest.jpg.

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

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

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

Ссылки

  1. Чен, Лян-Чие, Георгиос Папандреу, Iasonas Kokkinos, Кевин Мерфи и Алан Л. Юилл. "Deeplab: Семантическая сегментация изображений с глубокими сверточными сетями, atrous свертка и полностью соединенный crfs". Транзакции IEEE согласно анализу шаблона и искусственному интеллекту 40, № 4 (2018): 834-848.

Советы

  • pxds pixelLabelDatastore и imds imageDatastore хранят файлы, которые расположены в папке в лексикографическом порядке. Например, если у вас есть двенадцать файлов с именем 'file1.jpg', 'file2.jpg', …, 'file11.jpg' и 'file12.jpg', затем файлы хранятся в этом порядке:

    'file1.jpg'
    'file10.jpg'
    'file11.jpg'
    'file12.jpg'
    'file2.jpg'
    'file3.jpg'
    ...
    'file9.jpg'
    Файлы, которые хранятся в массиве ячеек, читаются в том же порядке, как они хранятся.

    Если порядок файлов в pxds и imds не является тем же самым, то можно столкнуться с несоответствием, когда вы читаете наземное изображение истины и соответствующие данные о метке с помощью pixelLabelImageDatastore. Если это происходит, то переименуйте пиксельные файлы метки так, чтобы у них был правильный порядок. Например, переименуйте 'file1.jpg', …, 'file9.jpg' к 'file01.jpg', …, 'file09.jpg'.

  • Чтобы извлечь семантические данные о сегментации из объекта groundTruth, сгенерированного Video Labeler или Ground Truth Labeler, используйте функцию pixelLabelTrainingData.

Введенный в R2018a

Для просмотра документации необходимо авторизоваться на сайте