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

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

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

Необходимые условия для третьих лиц

Необходимый

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

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

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

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

Проверьте окружение GPU

Используйте 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 State Park дополняет цветные изображения ближними инфракрасными каналами, которые обеспечивают более четкое разделение классов.

Этот пример использует Данные парка штата Хэмлин-Бич [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

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

The segmentImageUnet.m функция точки входа выполняет пеструю семантическую сегментацию на входном изображении с помощью сети multisspectralUnet, найденной в 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-2020 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 Pre-trained 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 (net);

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

Загрузите данные о государственном парке Хамлин-Бич.

if ~exist(fullfile(pwd,'data'))
    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-by-width-by-height. В MATLAB многоканальные изображения расположены как массивы width-by-height-by-numChannels. Чтобы изменить форму данных так, чтобы каналы находились в третьей размерности, используйте функцию helper, 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 функция точки входа, создайте объект Строение для целевого объекта MEX, установив целевой язык на C++. Используйте coder.DeepLearningConfig (GPU Coder) функция для создания CuDNN объект строения глубокого обучения и присвоение его DeepLearningConfig свойство объекта строения кода GPU. Запуск codegen команда, задающая размер входа [12446 7654 7] и закрашенной фигуры размер [1024 1024]. Эти значения соответствуют всему размеру test_data. Меньшие размеры закрашенной фигуры ускоряют вывод. Чтобы увидеть, как вычисляются закрашенные фигуры, смотрите segmentImageUnet.m функция точки входа.

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

Запустите сгенерированный 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]);

Отображение сегментированных test_data U-Net

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

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] Роннебергер, Олаф, Филипп Фишер и Томас Брокс. «U-Net: Сверточные сети для сегментации биомедицинских изображений». arXiv preprint arXiv:1505.04597, 2015.

[2] Kemker, R., C. Salvaggio, and C. Kanan. «Мультиспектральный набор данных высокого разрешения для семантической сегментации». CoRR, abs/1703.01918, 2017.

Для просмотра документации необходимо авторизоваться на сайте