Этот пример показывает, как классифицировать гиперспектральные изображения с помощью пользовательской спектральной сверточной нейронной сети (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.
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.
Вычислите точность классификации для тестовых данных набора. Здесь точность является частью правильной классификации пикселей по всем классам.
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)
colorize
| hypercube
| hyperpca
| imageDatastore
| augmentedImageDatastore
(Deep Learning Toolbox) | classify
(Deep Learning Toolbox) | trainingOptions
(Deep Learning Toolbox) | trainNetwork
(Deep Learning Toolbox)