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

Этот пример показывает, как классифицировать гиперспектральные изображения с помощью пользовательской спектральной сверточной нейронной сети (CSCNN) для классификации.

Гиперспектральная визуализация измеряет пространственные и спектральные функции объекта на разных длинах волн в диапазоне от ультрафиолетового до длинного инфракрасного, включая видимый спектр. В отличие от цветной визуализации, которая использует только три типа датчиков, чувствительных к красным зелёным и синим фрагментам видимого спектра, гиперспектральные изображения могут включать десятки или сотни каналов. Поэтому гиперспектральные изображения могут включать дифференциацию объектов, которые выглядят идентичными в изображении RGB.

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

Загрузка гиперспектрального набора данных

В этом примере используется набор данных Indian Pines, включенный в Image Processing Toolbox™ библиотеку гиперспектральных изображений. Набор данных состоит из одного гиперспектрального изображения размера 145 на 145 пикселей с 220 цветовыми каналами. Набор данных также содержит изображение метки основной истины с 16 классами, такими как Alfalfa, Corn, Grass-pasture, Grass-trees и Stone-Steel-Towers.

Чтение гиперспектрального изображения с помощью hypercube функция.

hcube = hypercube('indian_pines.dat');

Визуализируйте ложноцветную версию изображения с помощью colorize функция.

rgbImg = colorize(hcube,'method','rgb');
imshow(rgbImg)

Загрузите метки основной истины и укажите количество классов.

gtLabel = load('indian_pines_gt.mat');
gtLabel = gtLabel.indian_pines_gt;
numClasses = 16;

Предварительная обработка обучающих данных

Уменьшите количество спектральных полос до 30 с помощью hyperpca функция. Эта функция выполняет анализ основного компонента (PCA) и выбирает спектральные полосы с наиболее уникальными сигнатурами.

dimReduction = 30;
imageData = hyperpca(hcube,dimReduction);

Нормализуйте данные изображения.

sd = std(imageData,[],3);
imageData = imageData./sd;

Разделите гиперспектральное изображение на закрашенные фигуры размера 25 на 25 пикселей с 30 каналами, используя createImagePatchesFromHypercube вспомогательная функция. Эта функция присоединена к примеру как вспомогательный файл. Функция также возвращает одну метку для каждой закрашенной фигуры, которая является меткой центрального пикселя.

windowSize = 25;
inputSize = [windowSize windowSize dimReduction];
[allPatches,allLabels] = createImagePatchesFromHypercube(imageData,gtLabel,windowSize);

indianPineDataTransposed = permute(allPatches,[2 3 4 1]);
dsAllPatches = augmentedImageDatastore(inputSize,indianPineDataTransposed,allLabels);

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

patchesLabeled = allPatches(allLabels>0,:,:,:);
patchLabels = allLabels(allLabels>0);
numCubes = size(patchesLabeled,1);

Преобразуйте числовые метки в категориальные.

patchLabels = categorical(patchLabels);

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

[trainingIndex,validationIndex,testInd] = dividerand(numCubes,0.3,0.7,0);
dataInputTrain = patchesLabeled(trainingIndex,:,:,:);
dataLabelTrain = patchLabels(trainingIndex,1);

Транспонируйте входные данные.

dataInputTransposeTrain = permute(dataInputTrain,[2 3 4 1]); 
dataInputVal = patchesLabeled(validationIndex,:,:,:);
dataLabelVal = patchLabels(validationIndex,1);
dataInputTransposeVal = permute(dataInputVal,[2 3 4 1]);

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

imdsTrain = augmentedImageDatastore(inputSize,dataInputTransposeTrain,dataLabelTrain);
imdsTest = augmentedImageDatastore(inputSize,dataInputTransposeVal,dataLabelVal);

Создание сети классификации CSCNN

Определите архитектуру CSCNN.

layers = [
    image3dInputLayer(inputSize,'Name','Input','Normalization','None')
    convolution3dLayer([3 3 7],8,'Name','conv3d_1')
    reluLayer('Name','Relu_1')
    convolution3dLayer([3 3 5],16,'Name','conv3d_2')
    reluLayer('Name','Relu_2')
    convolution3dLayer([3 3 3],32,'Name','conv3d_3')
    reluLayer('Name','Relu_3')
    convolution3dLayer([3 3 1],8,'Name','conv3d_4')
    reluLayer('Name','Relu_4')
    fullyConnectedLayer(256,'Name','fc1')
    reluLayer('Name','Relu_5')
    dropoutLayer(0.4,'Name','drop_1')
    fullyConnectedLayer(128,'Name','fc2')
    dropoutLayer(0.4,'Name','drop_2')
    fullyConnectedLayer(numClasses,'Name','fc3')
    softmaxLayer('Name','softmax')
    classificationLayer('Name','output')];
lgraph = layerGraph(layers);

Визуализация сети с помощью Deep Network Designer.

deepNetworkDesigner(lgraph)

Настройка опций обучения

Укажите необходимые параметры сети. В данном примере обучите сеть для 100 эпох с начальной скоростью обучения 0,001, размером пакета 256 и оптимизацией Адама.

numEpochs = 100;
miniBatchSize = 256;
initLearningRate = 0.001;
momentum = 0.9;
learningRateFactor = 0.01;

options = trainingOptions('adam', ...
    'InitialLearnRate',initLearningRate, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropPeriod',30, ...
    'LearnRateDropFactor',learningRateFactor, ...
    'MaxEpochs',numEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'GradientThresholdMethod','l2norm', ...
    'GradientThreshold',0.01, ...
    'VerboseFrequency',100, ...
    'ValidationData',imdsTest, ...
    'ValidationFrequency',100);

Обучите сеть

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

Чтобы обучить сеть, установите doTraining переменная в следующем коде, для true. Если вы принимаете решение обучить сеть, настоятельно рекомендуется использовать CUDA NVIDIA™ поддерживающий графический процессор. Для использования графический процессор требуется Parallel Computing Toolbox™. Дополнительные сведения о поддерживаемых устройствах GPU см. в разделе Поддержка GPU по версии (Parallel Computing Toolbox).

doTraining = false;
if doTraining
    modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss"));
    net = trainNetwork(imdsTrain,lgraph,options);
    save(strcat("IndianPinesCSCNN-",modelDateTime,"-Epoch-",num2str(numEpochs),".mat"),'net');
else
    dataFolder = fullfile(tempdir,"indianPines");
    trainedHyperspectralCSCNN_url = 'https://ssd.mathworks.com/supportfiles/image/data/trainedIndianPinesCSCNN.mat';
    downloadTrainedIndianPinesCSCNN(trainedHyperspectralCSCNN_url,dataFolder);
    load(fullfile(dataFolder,'trainedIndianPinesCSCNN.mat'));
end
Pretrained CSCNN network already exists.

Классификация гиперспектрального изображения с помощью обученного CSCNN

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

predictionTest = classify(net,imdsTest);
accuracy = sum(predictionTest == dataLabelVal)/numel(dataLabelVal);
disp(['Accuracy of the test data = ', num2str(accuracy)])
Accuracy of the test data = 0.99359

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

prediction = classify(net,dsAllPatches);
prediction = double(prediction);

Обучение сети осуществляется только на маркированных закрашенных фигурах. Поэтому предсказанная классификация немаркированных пикселей бессмысленна. Найдите немаркированные закрашенные фигуры и установите метку равной 0.

patchesUnlabeled = find(allLabels==0);
prediction(patchesUnlabeled) = 0;

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

[m,n,d] = size(imageData);
indianPinesPrediction = reshape(prediction,[n m]);
indianPinesPrediction = indianPinesPrediction';

Отображение основной истины и предсказанной классификации.

cmap = parula(numClasses);

figure
tiledlayout(1,2,"TileSpacing","Tight")
nexttile
imshow(gtLabel,cmap)
title("Ground Truth Classification")

nexttile
imshow(indianPinesPrediction,cmap)
colorbar
title("Predicted Classification")

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

figure
imshowpair(gtLabel,indianPinesPrediction)

См. также

| | | | (Deep Learning Toolbox) | (Deep Learning Toolbox) | (Deep Learning Toolbox) | (Deep Learning Toolbox)

Похожие темы

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