exponenta event banner

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

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

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

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

Решения для глубокого обучения позволяют аппроксимировать более общие и сложные операции. Например, многомасштабная сеть агрегирования контекста (CAN), представленная Q. Chen [1], может аппроксимировать многомасштабное отображение тонов, перенос фотографического стиля, нелокальную дегазацию и рисование карандашом. Multiscale CAN обучается изображениям с полным разрешением для большей точности обработки высокочастотных деталей. После обучения сети сеть может обходить обычную операцию обработки и непосредственно обрабатывать изображения.

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

Аппроксимационная сеть оператора

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

Чтобы помочь сети узнать свойства глобального образа, многомасштабная архитектура CAN имеет большое поле восприятия. Первый и последний слои имеют одинаковый размер, поскольку оператор не должен изменять размер изображения. Последовательные промежуточные слои расширяются экспоненциально увеличивающимися масштабными коэффициентами (отсюда «многомасштабный» характер CAN). Расширение позволяет сети искать пространственно разделенные элементы на различных пространственных частотах без снижения разрешения изображения. После каждого уровня свертки сеть использует адаптивную нормализацию, чтобы сбалансировать влияние пакетной нормализации и отображения идентичности на аппроксимированный оператор.

Загрузить данные обучения и тестирования

Загрузите IAPR TC-12 Benchmark, который состоит из 20 000 натурных изображений [2]. Набор данных включает фотографии людей, животных, городов и многое другое. Размер файла данных составляет ~ 1,8 ГБ. Если вы не хотите загружать набор данных обучения, необходимый для обучения сети, то вы можете загрузить предварительно обученный CAN, набравload('trainedOperatorLearning-Epoch-181.mat'); в командной строке. Затем перейдите непосредственно к разделу Выполнение аппроксимации двусторонней фильтрации с использованием многомасштабной CAN в этом примере.

imagesDir = tempdir;
url_1 = 'http://www-i6.informatik.rwth-aachen.de/imageclef/resources/iaprtc12.tgz';
downloadIAPRTC12Data(url_1,imagesDir);

Этот пример обучает сеть с маленьким подмножеством Исходных данных IAPRTC-12.

trainImagesDir = fullfile(imagesDir,'iaprtc12','images','39');
exts = {'.jpg','.bmp','.png'};
pristineImages = imageDatastore(trainImagesDir,'FileExtensions',exts);

Перечислите количество обучающих изображений.

numel(pristineImages.Files)
ans = 916

Подготовка данных обучения

Чтобы создать набор обучающих данных, прочтите нетронутые изображения и выпишите изображения, которые были отфильтрованы в двустороннем порядке. Отфильтрованные изображения хранятся на диске в каталоге, указанном preprocessDataDir.

preprocessDataDir = [trainImagesDir filesep 'preprocessedDataset'];

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

Вспомогательная функция выполняет эти операции для каждого нетронутого изображения в inputImages:

  • Вычислите степень сглаживания для двусторонней фильтрации. Сглаживание отфильтрованного изображения уменьшает шум изображения.

  • Выполнение двусторонней фильтрации с использованием imbilatfilt(Панель инструментов обработки изображений).

  • Сохранить отфильтрованный образ на диск с помощью imwrite.

bilateralFilterDataset(pristineImages,preprocessDataDir);

Определение хранилища данных для извлечения случайных исправлений для обучения

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

В этом примере сетевые входы представляют собой нетронутые изображения в pristineImages. Требуемыми сетевыми ответами являются обработанные изображения после двусторонней фильтрации. Создание хранилища данных образа с именем bilatFilteredImages из коллекции файлов изображений с двусторонним фильтрованием.

bilatFilteredImages = imageDatastore(preprocessDataDir,'FileExtensions',exts);

Создать randomPatchExtractionDatastore(Панель инструментов обработки изображений) из двух хранилищ данных изображений. Укажите размер фрагмента 256 на 256 пикселей. Укажите 'PatchesPerImage"чтобы извлечь один случайно расположенный патч из каждой пары изображений во время обучения. Укажите размер мини-пакета, равный единице.

miniBatchSize = 1;
patchSize = [256 256];
dsTrain = randomPatchExtractionDatastore(pristineImages,bilatFilteredImages,patchSize, ....
    'PatchesPerImage',1);
dsTrain.MiniBatchSize = miniBatchSize;

randomPatchExtractionDatastore предоставляет мини-пакеты данных в сеть на каждой итерации эпохи. Выполните операцию чтения в хранилище данных для просмотра данных.

inputBatch = read(dsTrain);
disp(inputBatch)
       InputImage          ResponseImage  
    _________________    _________________

    {256×256×3 uint8}    {256×256×3 uint8}

Настройка многомасштабных уровней CAN

В этом примере определяется многомасштабный CAN с использованием слоев из Deep Learning Toolbox™, включая:

  • imageInputLayer - Слой ввода изображения

  • convolution2dLayer - 2D сверточный слой для сверточных нейронных сетей

  • batchNormalizationLayer - Уровень нормализации партий

  • leakyReluLayer - Слой негерметичного выпрямленного линейного блока

  • regressionLayer - Уровень регрессионного вывода для нейронной сети

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

  • adaptiveNormalizationMu - Слой масштаба, который регулирует преимущества отделения пакетной нормализации

  • adaptiveNormalizationLambda - Слой масштаба, который регулирует преимущества отделения идентичности

Первый слой, imageInputLayer, работает с исправлениями изображений. Размер исправления основан на сетевом поле приема, которое является пространственной областью изображения, влияющей на отклик самого верхнего уровня в сети. В идеале поле сетевого восприятия совпадает с размером изображения, так что оно может видеть все функции высокого уровня в изображении. Для двустороннего фильтра размер области аппроксимации изображения фиксируется равным 256 на 256.

networkDepth = 10;
numberOfFilters = 32;
firstLayer = imageInputLayer([256 256 3],'Name','InputLayer','Normalization','none');

За входным слоем изображения следует 2-D сверточный слой, содержащий фильтры 32 размером 3 на 3. Нулевая подстройка входных данных к каждому слою свертки так, чтобы карты элементов оставались такими же по размеру, что и входные данные после каждой свертки. Инициализируйте веса для единичной матрицы.

Wgts = zeros(3,3,3,numberOfFilters); 
for ii = 1:3
    Wgts(2,2,ii,ii) = 1;
end
convolutionLayer = convolution2dLayer(3,numberOfFilters,'Padding',1, ...
    'Weights',Wgts,'Name','Conv1');

За каждым слоем свертки следуют слой нормализации пакета и слой шкалы адаптивной нормализации, который регулирует уровни ветви нормализации пакета. Позже в этом примере будет создан соответствующий слой шкалы адаптивной нормализации, который регулирует интенсивность ветви тождества. Пока следуйте adaptiveNormalizationMu слой с добавочным слоем. Наконец, укажите протекающий уровень ReLU со скалярным умножителем 0.2 для отрицательных вводов.

batchNorm = batchNormalizationLayer('Name','BN1');
adaptiveMu = adaptiveNormalizationMu(numberOfFilters,'Mu1');
addLayer = additionLayer(2,'Name','add1');
leakyrelLayer = leakyReluLayer(0.2,'Name','Leaky1');

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

middleLayers = [convolutionLayer batchNorm adaptiveMu addLayer leakyrelLayer];
    
Wgts = zeros(3,3,numberOfFilters,numberOfFilters);
for ii = 1:numberOfFilters
    Wgts(2,2,ii,ii) = 1;
end
    
for layerNumber = 2:networkDepth-2
    dilationFactor = 2^(layerNumber-1);
    padding = dilationFactor;
    conv2dLayer = convolution2dLayer(3,numberOfFilters, ...
        'Padding',padding,'DilationFactor',dilationFactor, ...
        'Weights',Wgts,'Name',['Conv' num2str(layerNumber)]);
    batchNorm = batchNormalizationLayer('Name',['BN' num2str(layerNumber)]);
    adaptiveMu = adaptiveNormalizationMu(numberOfFilters,['Mu' num2str(layerNumber)]);
    addLayer = additionLayer(2,'Name',['add' num2str(layerNumber)]);
    leakyrelLayer = leakyReluLayer(0.2, 'Name', ['Leaky' num2str(layerNumber)]);
    middleLayers = [middleLayers conv2dLayer batchNorm adaptiveMu addLayer leakyrelLayer];    
end

Не применяйте коэффициент расширения ко второму и последнему слою свертки.

conv2dLayer = convolution2dLayer(3,numberOfFilters, ...
    'Padding',1,'Weights',Wgts,'Name','Conv9');

batchNorm = batchNormalizationLayer('Name','AN9');
adaptiveMu = adaptiveNormalizationMu(numberOfFilters,'Mu9');
addLayer = additionLayer(2,'Name','add9');
leakyrelLayer = leakyReluLayer(0.2,'Name','Leaky9');
middleLayers = [middleLayers conv2dLayer batchNorm adaptiveMu addLayer leakyrelLayer];

У последнего слоя скручивания есть единственный фильтр размера 1 на 1 на 32 на 3, который восстанавливает изображение.

Wgts = sqrt(2/(9*numberOfFilters))*randn(1,1,numberOfFilters,3);
conv2dLayer = convolution2dLayer(1,3,'NumChannels',numberOfFilters, ...
    'Weights',Wgts,'Name','Conv10');

Последний слой - это регрессионный слой вместо протекающего слоя ReLU. Уровень регрессии вычисляет среднеквадратичную ошибку между изображением с двусторонней фильтрацией и предсказанием сети.

finalLayers = [conv2dLayer 
    regressionLayer('Name','FinalRegressionLayer')
];

Соедините все слои.

layers = [firstLayer middleLayers finalLayers'];
lgraph = layerGraph(layers);

Создайте пропущенные соединения, которые действуют как ветвь идентичности для уравнения адаптивной нормализации. Подключите пропускные соединения к дополнительным слоям.

skipConv1 = adaptiveNormalizationLambda(numberOfFilters,'Lambda1');
skipConv2 = adaptiveNormalizationLambda(numberOfFilters,'Lambda2');
skipConv3 = adaptiveNormalizationLambda(numberOfFilters,'Lambda3');
skipConv4 = adaptiveNormalizationLambda(numberOfFilters,'Lambda4');
skipConv5 = adaptiveNormalizationLambda(numberOfFilters,'Lambda5');
skipConv6 = adaptiveNormalizationLambda(numberOfFilters,'Lambda6');
skipConv7 = adaptiveNormalizationLambda(numberOfFilters,'Lambda7');
skipConv8 = adaptiveNormalizationLambda(numberOfFilters,'Lambda8');
skipConv9 = adaptiveNormalizationLambda(numberOfFilters,'Lambda9');

lgraph = addLayers(lgraph,skipConv1);
lgraph = connectLayers(lgraph,'Conv1','Lambda1');
lgraph = connectLayers(lgraph,'Lambda1','add1/in2');

lgraph = addLayers(lgraph,skipConv2);
lgraph = connectLayers(lgraph,'Conv2','Lambda2');
lgraph = connectLayers(lgraph,'Lambda2','add2/in2');

lgraph = addLayers(lgraph,skipConv3);
lgraph = connectLayers(lgraph,'Conv3','Lambda3');
lgraph = connectLayers(lgraph,'Lambda3','add3/in2');

lgraph = addLayers(lgraph,skipConv4);
lgraph = connectLayers(lgraph,'Conv4','Lambda4');
lgraph = connectLayers(lgraph,'Lambda4','add4/in2');

lgraph = addLayers(lgraph,skipConv5);
lgraph = connectLayers(lgraph,'Conv5','Lambda5');
lgraph = connectLayers(lgraph,'Lambda5','add5/in2');

lgraph = addLayers(lgraph,skipConv6);
lgraph = connectLayers(lgraph,'Conv6','Lambda6');
lgraph = connectLayers(lgraph,'Lambda6','add6/in2');

lgraph = addLayers(lgraph,skipConv7);
lgraph = connectLayers(lgraph,'Conv7','Lambda7');
lgraph = connectLayers(lgraph,'Lambda7','add7/in2');

lgraph = addLayers(lgraph,skipConv8);
lgraph = connectLayers(lgraph,'Conv8','Lambda8');
lgraph = connectLayers(lgraph,'Lambda8','add8/in2');

lgraph = addLayers(lgraph,skipConv9);
lgraph = connectLayers(lgraph,'Conv9','Lambda9');
lgraph = connectLayers(lgraph,'Lambda9','add9/in2');

Постройте график слоев.

plot(lgraph)

Укажите параметры обучения

Обучение сети с помощью оптимизатора Adam. Задайте параметры гиперпараметра с помощью trainingOptions функция. Использовать значения по умолчанию 0.9 для "Momentum«и» 0.0001 для "L2Regularization'(распад веса). Укажите постоянную скорость обучения 0.0001. Поезд на 181 эпоху.

maxEpochs = 181;
initLearningRate = 0.0001;
miniBatchSize = 1;

options = trainingOptions('adam', ...
    'InitialLearnRate',initLearningRate, ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'Plots','training-progress', ...
    'Verbose',false);

Обучение сети

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

Для обучения сети установите doTraining переменная в следующем коде true. Обучение многомасштабной CAN с помощью trainNetwork функция.

Обучение на GPU, если он доступен. Для использования графического процессора требуются параллельные вычислительные Toolbox™ и графический процессор NVIDIA ® с поддержкой CUDA ®. Дополнительные сведения см. в разделе Поддержка графического процессора по выпуску (Панель инструментов параллельных вычислений). Обучение занимает около 15 часов на NVIDIA™ Titan X.

doTraining = false;
if doTraining
    modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss"));
    net = trainNetwork(dsTrain,lgraph,options);
    save(strcat("trainedOperatorLearning-",modelDateTime,"-Epoch-",num2str(maxEpochs),".mat"),'net');
else
    load('trainedOperatorLearning-Epoch-181.mat');
end

Выполнение аппроксимации двусторонней фильтрации с использованием многомасштабной CAN

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

  • Создайте образец шумного входного изображения из опорного изображения.

  • Выполнить обычную двустороннюю фильтрацию шумного изображения с помощью imbilatfilt(Панель инструментов обработки изображений).

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

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

  • Оцените качество обозначенных изображений путем количественной оценки сходства изображений с нетронутым эталонным изображением.

Создать образец шумного изображения

Создайте образец шумного изображения, которое будет использоваться для сравнения результатов аппроксимации оператора с обычной двусторонней фильтрацией. Набор тестовых данных, testImages, содержит 21 нетронутое изображение, поставляемое в Toolbox™ обработки изображений. Загрузка изображений в imageDatastore.

exts = {'.jpg','.png'};
fileNames = {'sherlock.jpg','car2.jpg','fabric.png','greens.jpg','hands1.jpg','kobi.png',...
    'lighthouse.png','micromarket.jpg','office_4.jpg','onion.png','pears.png','yellowlily.jpg',...
    'indiancorn.jpg','flamingos.jpg','sevilla.jpg','llama.jpg','parkavenue.jpg',...
    'peacock.jpg','car1.jpg','strawberries.jpg','wagon.jpg'};
filePath = [fullfile(matlabroot,'toolbox','images','imdata') filesep];
filePathNames = strcat(filePath,fileNames);
testImages = imageDatastore(filePathNames,'FileExtensions',exts);

Отображение тестовых изображений в виде монтажа.

montage(testImages)

Выберите одно из изображений для использования в качестве опорного изображения для двусторонней фильтрации. Преобразование изображения в тип данных uint8.

indx = 3; % Index of image to read from the test image datastore
Ireference = readimage(testImages,indx);
Ireference = im2uint8(Ireference);

При необходимости можно использовать собственное изображение в качестве опорного. Обратите внимание, что размер тестового изображения должен быть не менее 256 на 256. Если тестовое изображение меньше 256 на 256, увеличьте размер изображения с помощью imresize(Панель инструментов обработки изображений). Для сети также требуется тестовый образ RGB. Если тестовое изображение имеет оттенки серого, преобразуйте его в RGB с помощью cat функция для объединения трех копий исходного изображения вдоль третьего размера.

Отображение ссылочного изображения.

imshow(Ireference)
title('Pristine Reference Image')

Используйте imnoise(Панель инструментов обработки изображений) для добавления нулевого среднего гауссова белого шума с дисперсией 0,00001 к опорному изображению.

Inoisy = imnoise(Ireference,'gaussian',0.00001);
imshow(Inoisy)
title('Noisy Image')

Фильтрация изображения с помощью двусторонней фильтрации

Обычная двусторонняя фильтрация является стандартным способом уменьшения шума изображения при сохранении резкости краев. Используйте imbilatfilt(Панель инструментов обработки изображений), чтобы применить двусторонний фильтр к шумному изображению. Укажите степень сглаживания, равную дисперсии значений пикселей.

degreeOfSmoothing = var(double(Inoisy(:)));
Ibilat = imbilatfilt(Inoisy,degreeOfSmoothing);
imshow(Ibilat)
title('Denoised Image Obtained Using Bilateral Filtering')

Обработка образа с использованием обученной сети

Передача нормализованного входного изображения через обучаемую сеть и наблюдение за activations от конечного слоя (регрессионного слоя). Выходной сигнал сети представляет собой желаемое денозованное изображение.

Iapprox = activations(net,Inoisy,'FinalRegressionLayer');

Toolbox™ обработки изображений требует, чтобы изображения с плавающей запятой имели значения пикселей в диапазоне [0, 1]. Используйте rescale чтобы масштабировать значения пикселов в этом диапазоне, затем преобразовать изображение в uint8.

Iapprox = rescale(Iapprox);
Iapprox = im2uint8(Iapprox);
imshow(Iapprox)
title('Denoised Image Obtained Using Multiscale CAN')

Визуальное и количественное сравнение

Чтобы получить лучшее визуальное представление о денозированных изображениях, изучите небольшую область внутри каждого изображения. Укажите интересующую область (ROI) с помощью вектора roi в формате [x y width height]. Элементы определяют координаты x и y верхнего левого угла, а также ширину и высоту окупаемости инвестиций.

roi = [300 30 50 50];

Обрезайте изображения до этой окупаемости инвестиций и отобразите результат как монтаж.

montage({imcrop(Ireference,roi),imcrop(Inoisy,roi), ...
    imcrop(Ibilat,roi),imcrop(Iapprox,roi)}, ...
    'Size',[1 4]);
title('Reference Image | Noisy Image | Bilateral-Filtered Image | CAN Prediction');

CAN удаляет больше шума, чем обычная двусторонняя фильтрация. Оба метода сохраняют резкость края.

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

Измерьте пиковое отношение сигнал/шум (PSNR) каждого изображения относительно опорного изображения. Большие значения PSNR обычно указывают на лучшее качество изображения. Посмотрите psnr(Панель инструментов обработки изображений) для получения дополнительной информации об этой метрике.

noisyPSNR = psnr(Inoisy,Ireference);
bilatPSNR = psnr(Ibilat,Ireference);
approxPSNR = psnr(Iapprox,Ireference);
disp(['PSNR of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = ', ...
    num2str([noisyPSNR bilatPSNR approxPSNR])])
PSNR of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = 20.2857      25.7978      26.2011

Измерьте индекс структурного подобия (SSIM) каждого изображения. SSIM оценивает визуальное воздействие трех характеристик изображения: яркости, контраста и структуры, на эталонное изображение. Чем ближе значение SSIM к 1, тем лучше тестовое изображение согласуется с эталонным изображением. Посмотрите ssim(Панель инструментов обработки изображений) для получения дополнительной информации об этой метрике.

noisySSIM = ssim(Inoisy,Ireference);
bilatSSIM = ssim(Ibilat,Ireference);
approxSSIM = ssim(Iapprox,Ireference);
disp(['SSIM of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = ', ...
    num2str([noisySSIM bilatSSIM approxSSIM])])
SSIM of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = 0.76251     0.91576     0.92663

Измерение качества воспринимаемого изображения с помощью средства оценки качества изображения естественности (NIQE). Меньшие оценки NIQE указывают на лучшее качество восприятия. Посмотрите niqe(Панель инструментов обработки изображений) для получения дополнительной информации об этой метрике.

noisyNIQE = niqe(Inoisy);
bilatNIQE = niqe(Ibilat);
approxNIQE = niqe(Iapprox);
disp(['NIQE score of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = ', ...
    num2str([noisyNIQE bilatNIQE approxNIQE])])
NIQE score of: Noisy Image / Bilateral-Filtered Image / Operator Approximated Image = 12.1865      7.22606      6.18105

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

Ссылки

[1] Чэнь, К. Ж. Сюй и В. Колтун. «Быстрая обработка изображений с помощью полностью сверточных сетей». В трудах конференции IEEE 2017 по компьютерному зрению. Венеция, Италия, октябрь 2017 г., стр. 2516-2525.

[2] Грубингер, М., П. Клаф, Х. Мюллер и Т. Деселер. «Эталонный тест IAPR TC-12: новый ресурс оценки для визуальных информационных систем». Труды языковых ресурсов TrainingImage 2006 для извлечения изображений на основе контента. Генуя, Италия. Том 5, май 2006, стр. 10.

См. также

| | | | | (Панель инструментов обработки изображений) | (Панель инструментов обработки изображений)

Связанные темы