Подготовьте Datastore к регрессии от изображения к изображению

В этом примере показано, как подготовить datastore к обучению сеть регрессии от изображения к изображению использование transform и combine функции ImageDatastore.

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

Подготовка данных Используя предварительную обработку конвейера

Этот пример использует соль и перечную модель шума, в которой часть входных пикселей изображения установлены в любой 0 или 1 (черный и белый, соответственно). Шумные изображения действуют как сетевой вход. Нетронутые изображения действуют как ожидаемый сетевой ответ. Сеть учится обнаруживать и удалять перечный шум и соль.

Загрузите нетронутые изображения в наборе данных цифры как imageDatastore. Datastore содержит 10 000 синтетических изображений цифр от 0 до 9. Изображения сгенерированы путем применения случайных преобразований к изображениям цифры, созданным с различными шрифтами. Каждое изображение цифры является 28 28 пикселями. Datastore содержит равное количество изображений на категорию.

digitDatasetPath = fullfile(matlabroot,'toolbox','nnet', ...
    'nndemos','nndatasets','DigitDataset');
imds = imageDatastore(digitDatasetPath, ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames');

Задайте большой размер чтения, чтобы минимизировать стоимость файлового ввода-вывода.

imds.ReadSize = 500;

Установите seed глобального генератора случайных чисел помогать в воспроизводимости результатов.

rng(0)

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

imds = shuffle(imds);

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

[imdsTrain,imdsVal,imdsTest] = splitEachLabel(imds,0.95,0.025);

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

dsTrainNoisy = transform(imdsTrain,@addNoise);
dsValNoisy = transform(imdsVal,@addNoise);
dsTestNoisy = transform(imdsTest,@addNoise);

Используйте combine функционируйте, чтобы объединить шумные изображения и нетронутые изображения в один datastore, который кормит данными trainNetwork. Этот объединенный datastore читает пакеты данных в массив 2D ячейки столбца как ожидалось trainNetwork. Выход combine функцией является CombinedDatastore.

dsTrain = combine(dsTrainNoisy,imdsTrain);
dsVal = combine(dsValNoisy,imdsVal);
dsTest = combine(dsTestNoisy,imdsTest);

Используйте transform функция, чтобы выполнить дополнительные операции предварительной обработки, которые характерны и для входа и для хранилищ данных ответа. commonPreprocessing функция помощника (заданный в конце этого примера) изменяет размер входа и изображений ответа к 32 32 пикселям, чтобы совпадать с входным размером сети, и нормирует данные в каждом изображении к области значений [0, 1].

dsTrain = transform(dsTrain,@commonPreprocessing);
dsVal = transform(dsVal,@commonPreprocessing);
dsTest = transform(dsTest,@commonPreprocessing);

Наконец, используйте transform функция, чтобы добавить рандомизированное увеличение в набор обучающих данных. augmentImages функция помощника (заданный в конце этого примера) применяется рандомизированный 90 вращений степени к данным. Идентичные вращения применяются к сетевому входу и соответствующим ожидаемым ответам.

dsTrain = transform(dsTrain,@augmentImages);

Увеличение уменьшает сверхподбор кривой и добавляет робастность в присутствие вращений в обучившем сеть. Рандомизированное увеличение не нужно для наборов тестовых данных или валидации.

Предварительно просмотрите предварительно обработанные данные

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

Визуализируйте примеры парных шумных и нетронутых изображений с помощью montage (Image Processing Toolbox) функция. Обучающие данные выглядят правильными. Шум соли и перца появляется во входных изображениях в левом столбце. Кроме сложения шума, входное изображение и изображение ответа являются тем же самым. Рандомизированный 90 вращений степени применяются и к входному и к изображениям ответа таким же образом.

exampleData = preview(dsTrain);
inputs = exampleData(:,1);
responses = exampleData(:,2);
minibatch = cat(2,inputs,responses);
montage(minibatch','Size',[8 2])
title('Inputs (Left) and Responses (Right)')

Задайте сверточную сеть автоэнкодера

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

Этот пример задает сверточную сеть автоэнкодера использование слоев от Deep Learning Toolbox™, включая:

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

imageLayer = imageInputLayer([32,32,1]);

Создайте слои кодирования. Субдискретизация в энкодере достигается макс. объединением с размером пула 2 и шагом 2.

encodingLayers = [ ...
    convolution2dLayer(3,16,'Padding','same'), ...
    reluLayer, ...
    maxPooling2dLayer(2,'Padding','same','Stride',2), ...
    convolution2dLayer(3,8,'Padding','same'), ...
    reluLayer, ...
    maxPooling2dLayer(2,'Padding','same','Stride',2), ...
    convolution2dLayer(3,8,'Padding','same'), ...
    reluLayer, ...
    maxPooling2dLayer(2,'Padding','same','Stride',2)];

Создайте слои декодирования. Декодер сверхдискретизировал кодируемое сообщение с помощью транспонированного слоя свертки. Создайте транспонированный слой свертки с правильным фактором повышающей дискретизации при помощи createUpsampleTransponseConvLayer функция помощника. Эта функция задана в конце этого примера.

Сеть использует clippedReluLayer как итоговый слой активации, чтобы обеспечить выходные параметры, чтобы быть в области значений [0, 1].

decodingLayers = [ ...
    createUpsampleTransponseConvLayer(2,8), ...
    reluLayer, ...
    createUpsampleTransponseConvLayer(2,8), ...
    reluLayer, ...
    createUpsampleTransponseConvLayer(2,16), ...
    reluLayer, ...
    convolution2dLayer(3,1,'Padding','same'), ...
    clippedReluLayer(1.0), ...
    regressionLayer];    

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

layers = [imageLayer,encodingLayers,decodingLayers];

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

Обучите сеть с помощью оптимизатора Адама. Задайте установки гиперпараметров при помощи trainingOptions функция. Обучайтесь в течение 100 эпох.

options = trainingOptions('adam', ...
    'MaxEpochs',100, ...
    'MiniBatchSize',imds.ReadSize, ...
    'ValidationData',dsVal, ...
    'Plots','training-progress', ...
    'Verbose',false);

Обучите сеть

Теперь, когда источник данных и опции обучения сконфигурированы, обучают сверточную сеть автоэнкодера использование trainNetwork функция.

Обучайтесь на графическом процессоре, если вы доступны. Используя графический процессор требует Parallel Computing Toolbox™, и CUDA® включил NVIDIA® графический процессор. Для получения дополнительной информации смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Обучение занимает часы приблизительно 25 минут на XP Титана NVIDIA.

net = trainNetwork(dsTrain,layers,options);

modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss"));
save(strcat("trainedImageToImageRegressionNet-",modelDateTime,".mat"),'net');    

Оцените эффективность сети шумоподавления

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

ypred = predict(net,dsTest);

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

inputImageExamples = preview(dsTest);
montage({inputImageExamples{1},ypred(:,:,:,1)});

Оцените эффективность сети путем анализа пикового отношения сигнал-шум (PSNR).

ref = inputImageExamples{1,2};
originalNoisyImage = inputImageExamples{1,1};
psnrNoisy = psnr(originalNoisyImage,ref)
psnrNoisy = single
    17.8455
psnrDenoised = psnr(ypred(:,:,:,1),ref)
psnrDenoised = single
    21.8439

PSNR выходного изображения выше, чем шумное входное изображение, как ожидалось.

Вспомогательные Функции

addNoise функция помощника добавляет соль и перечный шум к изображениям при помощи imnoise (Image Processing Toolbox) функция. addNoise функция требует, чтобы формат входных данных был массивом ячеек данных изображения, которые совпадают с форматом данных, возвращенных read функция ImageDatastore.

function dataOut = addNoise(data)

    dataOut = data;
    for idx = 1:size(data,1)
       dataOut{idx} = imnoise(data{idx},'salt & pepper');
    end

end

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

  1. Преобразуйте данные изображения в тип данных single.

  2. Измените размер данных изображения, чтобы совпадать с размером входного слоя при помощи imresize (Image Processing Toolbox) функция.

  3. Нормируйте данные к области значений [0, 1] при помощи rescale функция.

Функция помощника требует, чтобы формат входных данных был массивом 2D ячейки столбца данных изображения, которые совпадают с форматом данных, возвращенных read функция CombinedDatastore.

function dataOut = commonPreprocessing(data)

    dataOut = cell(size(data));
    for col = 1:size(data,2)
        for idx = 1:size(data,1)
            temp = single(data{idx,col});
            temp = imresize(temp,[32,32]);
            temp = rescale(temp);
            dataOut{idx,col} = temp;
        end
    end
end

augmentImages функция помощника добавляет рандомизированный 90 вращений степени к данным при помощи rot90 функция. Идентичные вращения применяются к сетевому входу и соответствующим ожидаемым ответам. Функция требует, чтобы формат входных данных был массивом 2D ячейки столбца данных изображения, которые совпадают с форматом данных, возвращенных read функция CombinedDatastore.

function dataOut = augmentImages(data)

    dataOut = cell(size(data));
    for idx = 1:size(data,1)
        rot90Val = randi(4,1,1)-1;
        dataOut(idx,:) = {rot90(data{idx,1},rot90Val),rot90(data{idx,2},rot90Val)};
    end
end

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

function out = createUpsampleTransponseConvLayer(factor,numFilters)

    filterSize = 2*factor - mod(factor,2); 
    cropping = (factor-mod(factor,2))/2;
    numChannels = 1;
    
    out = transposedConv2dLayer(filterSize,numFilters, ... 
        'NumChannels',numChannels,'Stride',factor,'Cropping',cropping);
end

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

| | | |

Связанные примеры

Больше о