Этот пример показывает, как обучить сверточную нейронную сеть 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 метки, которые содержат наземные изображения истины и пиксельные данные о метке. Исправление является общим методом, чтобы предотвратить исчерпывание памяти для больших изображений и эффективно увеличить сумму доступных данных тренировки.
Начните путем хранения учебных изображений от '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 начальные серии сверточных слоев вкраплены макс. слоями объединения, последовательно уменьшив разрешение входного изображения. Эти слои сопровождаются серией сверточных слоев, вкрапленных повышающей дискретизацией операторов, последовательно увеличивая разрешение входного изображения [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
Обучите сеть с помощью стохастического спуска градиента с импульсом (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.
evaluateSemanticSegmentation
| histeq
| imageDatastore
| pixelLabelDatastore
| randomPatchExtractionDatastore
| semanticseg
| trainNetwork
| trainingOptions
| unetLayers