Семантическая сегментация многоспектральных изображений Используя глубокое обучение

Этот пример показывает, как обучить сверточную нейронную сеть U-Net, чтобы выполнить семантическую сегментацию многоспектрального изображения с семью каналами: три цветовых канала, три почти инфракрасных канала и маска.

Пример показывает, как обучить сеть U-Net и также обеспечивает предварительно обученную сеть U-Net. Если вы принимаете решение обучить сеть U-Net, использование CUDA-способного графического процессора NVIDIA™ с вычисляют возможность 3.0, или выше настоятельно рекомендован (требует Parallel Computing Toolbox™).

Введение

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

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

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

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

Этот пример использует многоспектральный набор данных с высоким разрешением, чтобы обучить сеть [1]. Набор изображений был получен с помощью беспилотника по Хэмлин-Бич-Стэйт-Парк, Нью-Йорк. Данные содержат маркированное обучение, валидацию и наборы тестов, с 18 метками класса объекта. Размер файла данных составляет ~3.0 Гбайт.

Загрузите версию MAT-файла набора данных с помощью функции помощника downloadHamlinBeachMSIData. Эта функция присоединена к примеру как к вспомогательному файлу.

imageDir = tempdir;
url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat';
downloadHamlinBeachMSIData(url,imageDir);

Кроме того, загрузите предварительно обученную версию U-Net для этого набора данных с помощью функции помощника downloadTrainedUnet (присоединенный к примеру как вспомогательный файл). Предварительно обученная модель позволяет вам запустить целый пример, не имея необходимость ожидать обучения завершиться.

trainedUnet_url = 'https://www.mathworks.com/supportfiles/vision/data/multispectralUnet.mat';
downloadTrainedUnet(trainedUnet_url,imageDir);

Осмотрите данные тренировки

Загрузите набор данных в рабочую область.

load(fullfile(imageDir,'rit18_data','rit18_data.mat'));

Исследуйте структуру данных.

whos train_data val_data test_data
  Name            Size                         Bytes  Class     Attributes

  test_data       7x12446x7654            1333663576  uint16              
  train_data      7x9393x5642              741934284  uint16              
  val_data        7x8833x6918              855493716  uint16              

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

train_data = switchChannelsToThirdPlane(train_data);
val_data   = switchChannelsToThirdPlane(val_data);
test_data  = switchChannelsToThirdPlane(test_data);

Подтвердите, что данные имеют правильную структуру.

whos train_data val_data test_data
  Name                Size                     Bytes  Class     Attributes

  test_data       12446x7654x7            1333663576  uint16              
  train_data       9393x5642x7             741934284  uint16              
  val_data         8833x6918x7             855493716  uint16              

Цветовые каналы RGB являются 4-ми, 5-ми, и 6-ми каналами изображений. Отобразите компонент цвета обучения, валидации, и протестируйте изображения как монтаж. Чтобы заставить изображения казаться более яркими на экране, компенсируйте их гистограммы при помощи функции histeq.

figure
montage(...
    {histeq(train_data(:,:,4:6)), ...
    histeq(val_data(:,:,4:6)), ...
    histeq(test_data(:,:,4:6))}, ...
    'BorderSize',10,'BackgroundColor','white')
title('RGB Component of Training Image (Left), Validation Image (Center), and Test Image (Right)')

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

figure
montage(...
    {histeq(train_data(:,:,1)), ...
    histeq(train_data(:,:,2)), ...
    histeq(train_data(:,:,3))}, ...
    'BorderSize',10,'BackgroundColor','white')
title('IR Channels 1 (Left), 2, (Center), and 3 (Right) of Training Image')

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

figure
montage(...
    {train_data(:,:,7), ...
    val_data(:,:,7), ...
    test_data(:,:,7)}, ...
    'BorderSize',10,'BackgroundColor','white')
title('Mask of Training Image (Left), Validation Image (Center), and Test Image (Right)')

Маркированные изображения содержат наземные данные об истине для сегментации с каждым пикселем, присвоенным одному из этих 18 классов. Получите список классов с их соответствующими идентификаторами.

disp(classes)
0. Other Class/Image Border      
1. Road Markings                 
2. Tree                          
3. Building                      
4. Vehicle (Car, Truck, or Bus)  
5. Person                        
6. Lifeguard Chair               
7. Picnic Table                  
8. Black Wood Panel              
9. White Wood Panel              
10. Orange Landing Pad           
11. Water Buoy                   
12. Rocks                        
13. Other Vegetation             
14. Grass                        
15. Sand                         
16. Water (Lake)                 
17. Water (Pond)                 
18. Asphalt (Parking Lot/Walkway)

Создайте вектор имен классов.

classNames = [ "RoadMarkings","Tree","Building","Vehicle","Person", ...
               "LifeguardChair","PicnicTable","BlackWoodPanel",...
               "WhiteWoodPanel","OrangeLandingPad","Buoy","Rocks",...
               "LowLevelVegetation","Grass_Lawn","Sand_Beach",...
               "Water_Lake","Water_Pond","Asphalt"]; 

Наложите метки на компенсируемом гистограммой изображении обучения RGB. Добавьте шкалу палитры в изображение.

cmap = jet(numel(classNames));
B = labeloverlay(histeq(train_data(:,:,4:6)),train_labels,'Transparency',0.8,'Colormap',cmap);

figure
title('Training Labels')
imshow(B)
N = numel(classNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(cmap)

Сохраните данные тренировки как файл MAT и учебные метки как файл PNG.

save('train_data.mat','train_data');
imwrite(train_labels,'train_labels.png');

Создайте случайный Datastore экстракции закрашенной фигуры для обучения

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

Начните путем хранения учебных изображений от 'train_data.mat' в imageDatastore. Поскольку формат файла MAT является нестандартным форматом изображения, необходимо использовать средство чтения файлов MAT, чтобы позволить читать данные изображения. Можно использовать средство чтения файлов MAT помощника, matReader, который извлекает первые шесть каналов от данных тренировки и не использует последний канал, содержащий маску. Эта функция присоединена к примеру как к вспомогательному файлу.

imds = imageDatastore('train_data.mat','FileExtensions','.mat','ReadFcn',@matReader);

Создайте pixelLabelDatastore, чтобы сохранить закрашенные фигуры метки, содержащие 18 маркированных областей.

pixelLabelIds = 1:18;
pxds = pixelLabelDatastore('train_labels.png',classNames,pixelLabelIds);

Создайте randomPatchExtractionDatastore из datastore изображений и пиксельного datastore метки. Каждый мини-пакет содержит 16 закрашенных фигур размера 256 256 пиксели. Одна тысяча мини-пакетов извлечена в каждой итерации эпохи.

dsTrain = randomPatchExtractionDatastore(imds,pxds,[256,256],'PatchesPerImage',16000);

Случайный datastore экстракции закрашенной фигуры dsTrain обеспечивает мини-пакеты данных к сети в каждой итерации эпохи. Предварительно просмотрите datastore, чтобы исследовать данные.

inputBatch = preview(dsTrain);
disp(inputBatch)
        InputImage        ResponsePixelLabelImage
    __________________    _______________________

    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 
    [256×256×6 uint16]     [256×256 categorical] 

Создайте сетевые слои U-Net

Этот пример использует изменение сети U-Net. В U-Net начальные серии сверточных слоев вкраплены макс. слоями объединения, последовательно уменьшив разрешение входного изображения. Эти слои сопровождаются серией сверточных слоев, вкрапленных повышающей дискретизацией операторов, последовательно увеличивая разрешение входного изображения [2]. U-Net имени прибывает из того, что сеть может чертиться с симметричной формой как буква U.

Этот пример изменяет U-Net, чтобы использовать дополнение нуля в свертках, так, чтобы вход и вывод к сверткам имели тот же размер. Используйте функцию помощника, createUnet, чтобы создать U-Net с несколькими предварительно выобранными гиперпараметрами. Эта функция присоединяется как вспомогательный файл к примеру.

inputTileSize = [256,256,6];
lgraph = createUnet(inputTileSize);
disp(lgraph.Layers)
  58x1 Layer array with layers:

     1   'ImageInputLayer'                        Image Input                  256x256x6 images with 'zerocenter' normalization
     2   'Encoder-Section-1-Conv-1'               Convolution                  64 3x3x6 convolutions with stride [1  1] and padding [1  1  1  1]
     3   'Encoder-Section-1-ReLU-1'               ReLU                         ReLU
     4   'Encoder-Section-1-Conv-2'               Convolution                  64 3x3x64 convolutions with stride [1  1] and padding [1  1  1  1]
     5   'Encoder-Section-1-ReLU-2'               ReLU                         ReLU
     6   'Encoder-Section-1-MaxPool'              Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     7   'Encoder-Section-2-Conv-1'               Convolution                  128 3x3x64 convolutions with stride [1  1] and padding [1  1  1  1]
     8   'Encoder-Section-2-ReLU-1'               ReLU                         ReLU
     9   'Encoder-Section-2-Conv-2'               Convolution                  128 3x3x128 convolutions with stride [1  1] and padding [1  1  1  1]
    10   'Encoder-Section-2-ReLU-2'               ReLU                         ReLU
    11   'Encoder-Section-2-MaxPool'              Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
    12   'Encoder-Section-3-Conv-1'               Convolution                  256 3x3x128 convolutions with stride [1  1] and padding [1  1  1  1]
    13   'Encoder-Section-3-ReLU-1'               ReLU                         ReLU
    14   'Encoder-Section-3-Conv-2'               Convolution                  256 3x3x256 convolutions with stride [1  1] and padding [1  1  1  1]
    15   'Encoder-Section-3-ReLU-2'               ReLU                         ReLU
    16   'Encoder-Section-3-MaxPool'              Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
    17   'Encoder-Section-4-Conv-1'               Convolution                  512 3x3x256 convolutions with stride [1  1] and padding [1  1  1  1]
    18   'Encoder-Section-4-ReLU-1'               ReLU                         ReLU
    19   'Encoder-Section-4-Conv-2'               Convolution                  512 3x3x512 convolutions with stride [1  1] and padding [1  1  1  1]
    20   'Encoder-Section-4-ReLU-2'               ReLU                         ReLU
    21   'Encoder-Section-4-DropOut'              Dropout                      50% dropout
    22   'Encoder-Section-4-MaxPool'              Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
    23   'Mid-Conv-1'                             Convolution                  1024 3x3x512 convolutions with stride [1  1] and padding [1  1  1  1]
    24   'Mid-ReLU-1'                             ReLU                         ReLU
    25   'Mid-Conv-2'                             Convolution                  1024 3x3x1024 convolutions with stride [1  1] and padding [1  1  1  1]
    26   'Mid-ReLU-2'                             ReLU                         ReLU
    27   'Mid-DropOut'                            Dropout                      50% dropout
    28   'Decoder-Section-1-UpConv'               Transposed Convolution       512 2x2x1024 transposed convolutions with stride [2  2] and cropping [0  0  0  0]
    29   'Decoder-Section-1-UpReLU'               ReLU                         ReLU
    30   'Decoder-Section-1-DepthConcatenation'   Depth concatenation          Depth concatenation of 2 inputs
    31   'Decoder-Section-1-Conv-1'               Convolution                  512 3x3x1024 convolutions with stride [1  1] and padding [1  1  1  1]
    32   'Decoder-Section-1-ReLU-1'               ReLU                         ReLU
    33   'Decoder-Section-1-Conv-2'               Convolution                  512 3x3x512 convolutions with stride [1  1] and padding [1  1  1  1]
    34   'Decoder-Section-1-ReLU-2'               ReLU                         ReLU
    35   'Decoder-Section-2-UpConv'               Transposed Convolution       256 2x2x512 transposed convolutions with stride [2  2] and cropping [0  0  0  0]
    36   'Decoder-Section-2-UpReLU'               ReLU                         ReLU
    37   'Decoder-Section-2-DepthConcatenation'   Depth concatenation          Depth concatenation of 2 inputs
    38   'Decoder-Section-2-Conv-1'               Convolution                  256 3x3x512 convolutions with stride [1  1] and padding [1  1  1  1]
    39   'Decoder-Section-2-ReLU-1'               ReLU                         ReLU
    40   'Decoder-Section-2-Conv-2'               Convolution                  256 3x3x256 convolutions with stride [1  1] and padding [1  1  1  1]
    41   'Decoder-Section-2-ReLU-2'               ReLU                         ReLU
    42   'Decoder-Section-3-UpConv'               Transposed Convolution       128 2x2x256 transposed convolutions with stride [2  2] and cropping [0  0  0  0]
    43   'Decoder-Section-3-UpReLU'               ReLU                         ReLU
    44   'Decoder-Section-3-DepthConcatenation'   Depth concatenation          Depth concatenation of 2 inputs
    45   'Decoder-Section-3-Conv-1'               Convolution                  128 3x3x256 convolutions with stride [1  1] and padding [1  1  1  1]
    46   'Decoder-Section-3-ReLU-1'               ReLU                         ReLU
    47   'Decoder-Section-3-Conv-2'               Convolution                  128 3x3x128 convolutions with stride [1  1] and padding [1  1  1  1]
    48   'Decoder-Section-3-ReLU-2'               ReLU                         ReLU
    49   'Decoder-Section-4-UpConv'               Transposed Convolution       64 2x2x128 transposed convolutions with stride [2  2] and cropping [0  0  0  0]
    50   'Decoder-Section-4-UpReLU'               ReLU                         ReLU
    51   'Decoder-Section-4-DepthConcatenation'   Depth concatenation          Depth concatenation of 2 inputs
    52   'Decoder-Section-4-Conv-1'               Convolution                  64 3x3x128 convolutions with stride [1  1] and padding [1  1  1  1]
    53   'Decoder-Section-4-ReLU-1'               ReLU                         ReLU
    54   'Decoder-Section-4-Conv-2'               Convolution                  64 3x3x64 convolutions with stride [1  1] and padding [1  1  1  1]
    55   'Decoder-Section-4-ReLU-2'               ReLU                         ReLU
    56   'Final-ConvolutionLayer'                 Convolution                  18 1x1x64 convolutions with stride [1  1] and padding [0  0  0  0]
    57   'Softmax-Layer'                          Softmax                      softmax
    58   'Segmentation-Layer'                     Pixel Classification Layer   Cross-entropy loss 

Выберите Training Options

Обучите сеть с помощью стохастического спуска градиента с импульсом (SGDM) оптимизация. Задайте гиперустановки параметров для SDGM при помощи функции trainingOptions.

Обучение глубокой сети длительно. Ускорьте обучение путем определения высокого темпа обучения. Однако это может заставить градиенты сети взрываться или расти неудержимо, предотвратив сеть от обучения успешно. Чтобы сохранить градиенты в значимой области значений, включите усечение градиента путем определения 'GradientThreshold' как 0.05 и задайте 'GradientThresholdMethod', чтобы использовать L2-норму градиентов.

initialLearningRate = 0.05;
maxEpochs = 150;
minibatchSize = 16;
l2reg = 0.0001;

options = trainingOptions('sgdm',...
    'InitialLearnRate',initialLearningRate, ...
    'Momentum',0.9,...
    'L2Regularization',l2reg,...
    'MaxEpochs',maxEpochs,...
    'MiniBatchSize',minibatchSize,...
    'LearnRateSchedule','piecewise',...    
    'Shuffle','every-epoch',...
    'GradientThresholdMethod','l2norm',...
    'GradientThreshold',0.05, ...
    'Plots','training-progress', ...
    'VerboseFrequency',20);

Обучите сеть

После конфигурирования опций обучения и случайного datastore экстракции закрашенной фигуры, обучите сеть U-Net при помощи функции trainNetwork. Чтобы обучить сеть, установите параметр doTraining в следующем коде к true. CUDA-способный графический процессор NVIDIA™ с вычисляет возможность 3.0, или выше настоятельно рекомендован для обучения.

Если вы сохраняете параметр doTraining в следующем коде как false, то пример возвращает предварительно обученную сеть U-Net.

Примечание: Обучение занимает приблизительно 20 часов на Титане NVIDIA™ X и может взять еще дольше в зависимости от вашего оборудования графического процессора.

doTraining = false; 
if doTraining
    modelDateTime = datestr(now,'dd-mmm-yyyy-HH-MM-SS');
    [net,info] = trainNetwork(dsTrain,lgraph,options);
    save(['multispectralUnet-' modelDateTime '-Epoch-' num2str(maxEpochs) '.mat'],'net','options');
else 
    load(fullfile(imageDir,'trainedUnet','multispectralUnet.mat'));
end

Можно теперь использовать U-Net, чтобы семантически сегментировать многоспектральное изображение.

Предскажите результаты на тестовых данных

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

predictPatchSize = [1024 1024];
segmentedImage = segmentImage(val_data,net,predictPatchSize);

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

segmentedImage = uint8(val_data(:,:,7)~=0) .* segmentedImage;

figure
imshow(segmentedImage,[])
title('Segmented Image')

Вывод семантической сегментации является шумным. Выполните обработку изображений сообщения, чтобы удалить шум и случайные пиксели. Используйте функцию medfilt2, чтобы удалить шум соли-и-перца из сегментации. Визуализируйте сегментированное изображение с удаленным шумом.

segmentedImage = medfilt2(segmentedImage,[7,7]);
imshow(segmentedImage,[]);
title('Segmented Image  with Noise Removed')

Наложите сегментированное изображение на компенсируемом гистограммой изображении валидации RGB.

B = labeloverlay(histeq(val_data(:,:,4:6)),segmentedImage,'Transparency',0.8,'Colormap',cmap);

figure
imshow(B)
title('Labeled Validation Image')
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(cmap)

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

imwrite(segmentedImage,'results.png');
imwrite(val_labels,'gtruth.png');

Определите количество точности сегментации

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

pxdsResults = pixelLabelDatastore('results.png',classNames,pixelLabelIds);
pxdsTruth = pixelLabelDatastore('gtruth.png',classNames,pixelLabelIds);

Измерьте глобальную точность семантической сегментации при помощи функции evaluateSemanticSegmentation.

ssm = evaluateSemanticSegmentation(pxdsResults,pxdsTruth,'Metrics','global-accuracy');
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: global accuracy.
* Processing 1 images...
[==================================================] 100%
Elapsed time: 00:00:31
Estimated time remaining: 00:00:00
* Finalizing... Done.
* Data set metrics:

    GlobalAccuracy
    ______________

       0.90698    

Глобальный счет точности указывает, что чуть более чем 90% пикселей классифицируются правильно.

Вычислите степень растительного покрова

Итоговая цель этого примера состоит в том, чтобы вычислить степень растительного покрова в многоспектральном изображении.

Найдите количество пикселей маркированной растительностью. Метка IDs 2 ("Деревья"), 13 ("LowLevelVegetation"), и 14 ("Grass_Lawn") является классами растительности. Также найдите общее количество допустимых пикселей путем подведения итогов пикселей в ROI рисунка маски.

vegetationClassIds = uint8([2,13,14]);
vegetationPixels = ismember(segmentedImage(:),vegetationClassIds);
validPixels = (segmentedImage~=0);

numVegetationPixels = sum(vegetationPixels(:));
numValidPixels = sum(validPixels(:));

Вычислите процент растительного покрова путем деления количества пикселей растительности количеством допустимых пикселей.

percentVegetationCover = (numVegetationPixels/numValidPixels)*100;
fprintf('The percentage of vegetation cover is %3.2f%%.',percentVegetationCover);
The percentage of vegetation cover is 51.72%.

Сводные данные

Этот пример показывает, как создать и обучить сеть U-Net для семантической сегментации многоспектрального изображения с семью каналами. Это шаги, чтобы обучить сеть:

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

  • Создайте randomPatchExtractionDatastore, чтобы накормить данными тренировки сеть.

  • Задайте слои сети U-Net.

  • Задайте опции обучения.

  • Обучите сеть с помощью функции trainNetwork.

После обучения сети U-Net или загрузки предварительно обученной сети U-Net, пример выполняет семантическую сегментацию данных о валидации и измеряет точность сегментации.

Ссылки

[1] Kemker, R., К. Сальвагхио и К. Кэнэн. "Многоспектральный Набор данных с высоким разрешением для Семантической Сегментации". CoRR, abs/1703.01918. 2017.

[2] Ronneberger, O., П. Фишер и Т. Брокс. "U-Net: Сверточные Сети для Биомедицинской Сегментации Изображений". CoRR, abs/1505.04597. 2015.

Смотрите также

| | | | | | | |

Похожие темы

Внешние веб-сайты

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