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

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

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

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

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

Этот пример использует индийский Сосновый набор данных, включенный с Image Processing Toolbox™ Гиперспектральная Библиотека Обработки изображений. Набор данных состоит из одного гиперспектрального изображения размера 145 145 пиксели с 220 цветовыми каналами. Набор данных также содержит изображение метки основной истины с 16 классами, такими как Люцерна, Зерно, пастбище Травы, Травяные деревья и Каменные Стальные Башни.

Считайте гиперспектральное изображение с помощью 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);

Обучите сеть

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

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

Похожие темы