Генерация кода для сети Семантической Сегментации, которая использует U-net

Этот пример показывает генерацию кода для приложения сегментации изображений что глубокое обучение использования. Это использует codegen команда, чтобы сгенерировать MEX-функцию, которая выполняет предсказание на Сетевом объекте DAG для U-Net, нейронной сети для глубокого обучения для сегментации изображений.

Для подобного примера, покрывающего сегментацию изображений при помощи U-Net без codegen команда, смотрите Семантическую Сегментацию Многоспектральных Изображений Используя Глубокое обучение (Image Processing Toolbox).

Сторонние необходимые условия

Необходимый

Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.

  • CUDA® включил NVIDIA® графический процессор и совместимый драйвер.

Дополнительный

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

Проверьте среду графического процессора

Используйте coder.checkGpuInstall Функция (GPU Coder), чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

Сеть сегментации

U-Net [1] является типом сверточной нейронной сети (CNN), спроектированной для семантической сегментации изображений. В U-Net начальные серии сверточных слоев вкраплены макс. слоями объединения, последовательно уменьшив разрешение входного изображения. Эти слои сопровождаются серией сверточных слоев, вкрапленных повышающей дискретизацией операторов, последовательно увеличивая разрешение входного изображения. Объединение этих двух серийных путей формирует U-образный график. Сеть первоначально обучалась для и использовалась, чтобы выполнить предсказание на биомедицинских приложениях сегментации изображений. Этот пример демонстрирует способность сети отслеживать изменения в лесном покрове в зависимости от времени. Экологические агентства отслеживают вырубку леса, чтобы оценить и квалифицировать экологическое и экологическое здоровье области.

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

Этот пример использует Данные о национальном парке Hamlin Beach [2] наряду с предварительно обученной сетью U-Net для того, чтобы правильно классифицировать каждый пиксель.

Используемый U-Net обучен сегментировать пиксели, принадлежащие 18 классам, который включает:

0. Other Class/Image Border      7. Picnic Table         14. Grass
1. Road Markings                 8. Black Wood Panel     15. Sand
2. Tree                          9. White Wood Panel     16. Water (Lake)
3. Building                     10. Orange Landing Pad   17. Water (Pond)
4. Vehicle (Car, Truck, or Bus) 11. Water Buoy           18. Asphalt (Parking Lot/Walkway)
5. Person                       12. Rocks
6. Lifeguard Chair              13. Other Vegetation

segmentImageUnet Функция точки входа

segmentImageUnet.m функция точки входа выполняет patchwise семантическую сегментацию на входном изображении при помощи multispectralUnet сети, найденной в multispectralUnet.mat файл. Функция загружает сетевой объект от multispectralUnet.mat файл в персистентную переменную mynet и повторные использования персистентная переменная на последующих вызовах предсказания.

type('segmentImageUnet.m')
%  OUT = segmentImageUnet(IM, PATCHSIZE) returns a semantically segmented
%  image, segmented using the network multispectralUnet. The segmentation
%  is performed over each patch of size PATCHSIZE.
%
% Copyright 2019-2021 The MathWorks, Inc.
function out = segmentImageUnet(im, patchSize)

%#codegen

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('trainedUnet/multispectralUnet.mat');
end

[height, width, nChannel] = size(im);
patch = coder.nullcopy(zeros([patchSize, nChannel-1]));

% pad image to have dimensions as multiples of patchSize
padSize = zeros(1,2);
padSize(1) = patchSize(1) - mod(height, patchSize(1));
padSize(2) = patchSize(2) - mod(width, patchSize(2));

im_pad = padarray (im, padSize, 0, 'post');
[height_pad, width_pad, ~] = size(im_pad);

out = zeros([size(im_pad,1), size(im_pad,2)], 'uint8');

for i = 1:patchSize(1):height_pad    
    for j =1:patchSize(2):width_pad        
        for p = 1:nChannel-1              
            patch(:,:,p) = squeeze( im_pad( i:i+patchSize(1)-1,...
                                            j:j+patchSize(2)-1,...
                                            p));            
        end
         
        % pass in input
        segmentedLabels = activations(mynet, patch, 'Segmentation-Layer');
        
        % Takes the max of each channel (6 total at this point)
        [~,L] = max(segmentedLabels,[],3);
        patch_seg = uint8(L);
        
        % populate section of output
        out(i:i+patchSize(1)-1, j:j+patchSize(2)-1) = patch_seg;
       
    end
end

% Remove the padding
out = out(1:height, 1:width);

Получите предварительно обученный сетевой объект U-Net DAG

trainedUnet_url = 'https://www.mathworks.com/supportfiles/vision/data/multispectralUnet.mat';
downloadTrainedUnet(trainedUnet_url,pwd);
Downloading Pretrained U-net for Hamlin Beach dataset...
This will take several minutes to download...
done.
ld = load("trainedUnet/multispectralUnet.mat");
net = ld.net;

Сеть DAG содержит 58 слоев включая свертку, макс. объединение, конкатенацию глубины и классификацию пикселей выходные слои. Чтобы отобразить интерактивную визуализацию архитектуры нейронной сети для глубокого обучения, используйте analyzeNetwork функция. (сетевой) analyzeNetwork;

Подготовка данных

Загрузите данные о национальном парке Hamlin Beach.

if ~exist(fullfile(pwd,'data'),'dir')
    url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat';
    downloadHamlinBeachMSIData(url,pwd+"/data/");
end
Downloading Hamlin Beach dataset...
This will take several minutes to download...
done.

Загрузите и исследуйте данные в MATLAB.

load(fullfile(pwd,'data','rit18_data','rit18_data.mat'));

% Examine data
whos test_data
  Name           Size                         Bytes  Class     Attributes

  test_data      7x12446x7654            1333663576  uint16              

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

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

test_data  = switchChannelsToThirdPlane(test_data);

% Confirm data has the correct structure (channels last).
whos test_data
  Name               Size                     Bytes  Class     Attributes

  test_data      12446x7654x7            1333663576  uint16              

Запустите генерацию кода MEX

Сгенерировать код CUDA для segmentImageUnet.m функция точки входа, создайте объект GPU Configuration для цели MEX установка выходного языка на C++. Используйте coder.DeepLearningConfig (GPU Coder) функция, чтобы создать CuDNN объект настройки глубокого обучения и присвоение это к DeepLearningConfig свойство объекта настройки графического процессора кода. Запустите codegen команда, задающая входной размер [12446,7654,7] и размер закрашенной фигуры [1024,1024]. Эти значения соответствуют целому test_data размеру. Меньшие размеры закрашенной фигуры ускоряют вывод. Чтобы видеть, как закрашенные фигуры вычисляются, смотрите segmentImageUnet.m функция точки входа.

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
inputArgs = {ones(size(test_data),'uint16'),coder.Constant([1024 1024])};
codegen -config cfg segmentImageUnet -args inputArgs -report
Code generation successful: View report

Запустите Сгенерированный MEX, чтобы Предсказать Результаты для test_data

Этот segmentImageUnet функционируйте берет в данных, чтобы протестировать (test_data) и вектор, содержащий размерности размера закрашенной фигуры, чтобы использовать. Возьмите закрашенные фигуры изображения, предскажите пиксели в конкретной закрашенной фигуре, затем объедините все закрашенные фигуры вместе. Из-за размера test_data (12446x7654x7), легче обработать такое большое изображение в закрашенных фигурах.

segmentedImage = segmentImageUnet_mex(test_data,[1024 1024]);

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

segmentedImage = uint8(test_data(:,:,7)~=0) .* segmentedImage;

Поскольку выход семантической сегментации является шумным, удалите шум и случайные пиксели при помощи medfilt2 функция.

segmentedImage = medfilt2(segmentedImage,[5,5]);

Отобразите U-Net Сегментированный test_data

Следующая строка кода создает вектор из имен классов.

classNames = [ "RoadMarkings","Tree","Building","Vehicle","Person", ...
               "LifeguardChair","PicnicTable","BlackWoodPanel",...
               "WhiteWoodPanel","OrangeLandingPad","Buoy","Rocks",...
               "LowLevelVegetation","Grass_Lawn","Sand_Beach",...
               "Water_Lake","Water_Pond","Asphalt"];

Наложите метки на сегментированном тесте RGB, отображают и добавляют цветную полосу в изображение сегментации.

cmap = jet(numel(classNames));
B = labeloverlay(imadjust(test_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),...
    segmentedImage,'Transparency',0.8,'Colormap',cmap);
figure
imshow(B)

N = numel(classNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,...
    'TickLabelInterpreter','none');
colormap(cmap)
title('Segmented Image');

Ссылки

[1] Ronneberger, Олаф, Филипп Фишер и Томас Брокс. "U-Net: Сверточные Сети для Биомедицинской Сегментации Изображений". arXiv предварительно распечатывают arXiv:1505.04597, 2015.

[2] Kemker, R., К. Сальвагхио и К. Кэнэн. "Многоспектральный Набор данных с высоким разрешением для Семантической Сегментации". CoRR, abs/1703.01918, 2017.