Генерация кода для Приложения Семантической Сегментации на целях ARM® Neon, Который Использование U-Net

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

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

Необходимые условия

  • Процессор ARM, который поддерживает расширение NEON и имеет RAM по крайней мере 3 ГБ

  • ARM Вычисляет Библиотеку (на целевом оборудовании ARM)

  • Переменные окружения для компиляторов и библиотек

  • MATLAB® Coder™

  • Интерфейс MATLAB Coder для Библиотек Глубокого обучения поддерживает пакет

  • Deep Learning Toolbox™

Версия библиотеки ARM Compute, что этим примером использование не может быть последняя версия та генерация кода поддержки. Для получения информации о поддерживаемых версиях библиотек и о переменных окружения, смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder).

Этот пример не поддерживается в MATLAB Online.

Обзор U-Net

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

Основанная на глубоком обучении семантическая сегментация может дать к точному измерению растительного покрова из воздушных фотографий с высоким разрешением. Одна из проблем такого расчета к дифференцирующимся классам, которые имеют подобные визуальные характеристики, такие как классификация зеленого пикселя как трава, кустарник или дерево. Чтобы увеличить точность классификации, некоторые наборы данных содержат многоспектральные изображения, которые предоставляют дополнительную информацию о каждом пикселе. Например, набор данных национального парка 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

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

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

type('segmentationUnetARM.m')
%  OUT = segmentationUnetARM(IM) returns a semantically segmented
%  image, which is segmented using the network multispectralUnet. This segmentation
%  is performed on the input image patchwise on patches of size 256,256.
%
% Copyright 2019-2020 The MathWorks, Inc.
function out = segmentationUnetARM(im)

%#codegen

persistent mynet;

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

% The input data has to be padded to the size compatible
% with the network Input Size. This input_data is padded inorder to
% perform semantic segmentation on each patch of size (Network Input Size)
[height, width, nChannel] = size(im);
patch = coder.nullcopy(zeros([256, 256, nChannel-1]));
% 
padSize = zeros(1,2);
padSize(1) = 256 - mod(height, 256);
padSize(2) = 256 - mod(width, 256);
% 
% Pad image must have have dimensions as multiples of network input dimensions
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:256:height_pad    
    for j =1:256:width_pad        
        for p = 1:nChannel -1             
            patch(:,:,p) = squeeze( im( i:i+255,...
                                            j:j+255,...
                                            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+255, j:j+255) = patch_seg;
       
    end
end

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

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

Загрузите multispectralUnet.mat файл и загрузка сетевой объект U-Net DAG.

if ~exist('trainedUnet/multispectralUnet.mat','file')
    trainedUnet_url = 'https://www.mathworks.com/supportfiles/vision/data/multispectralUnet.mat';
    downloadUNet(trainedUnet_url,pwd);
end
ld = load("trainedUnet/multispectralUnet.mat");
net = ld.net;

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

analyzeNetwork(net);

Подготовьте входные данные

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

if ~exist(fullfile(pwd,'data'),'dir')
    url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat';
    downloadHamlinBeachMSIData(url,pwd+"/data/");
end

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

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

Исследуйте данные

whos test_data

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

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

test_data = switchChannelsToThirdPlane(test_data);

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

whos test_data

Этот пример использует обрезанную версию полного набора данных Beach State Park Хэмлина что test_data переменная содержит. Обрежьте высоту и ширину test_data создать переменную input_data то, что этот пример использует.

test_datacropRGB = imcrop(test_data(:,:,1:3),[2600, 3000, 2000, 2000]);
test_datacropInfrared = imcrop(test_data(:,:,4:6),[2600, 3000, 2000, 2000]);
test_datacropMask = imcrop(test_data(:,:,7),[2600, 3000, 2000, 2000]);
input_data(:,:,1:3) = test_datacropRGB;
input_data(:,:,4:6) = test_datacropInfrared;
input_data(:,:,7) = test_datacropMask;

Исследуйте input_data переменная.

whos('input_data');

Запишите входные данные в текстовый файл, который передается как вход сгенерированному исполняемому файлу.

WriteInputDatatoTxt(input_data);
[height, width, channels] = size(input_data);

Настройте объект настройки генерации кода для статической библиотеки

Чтобы сгенерировать код, который предназначается для основанного на ARM устройства, создайте объект настройки для библиотеки. Не создавайте объект настройки для исполняемой программы. Настройте объект настройки для генерации исходного кода C++ только.

cfg = coder.config('lib');
cfg.TargetLang = 'C++';
cfg.GenCodeOnly = true;

Настройте объект настройки для генерации кода глубокого обучения

Создайте coder.ARMNEONConfig объект. Задайте версию библиотеки и архитектуру целевого процессора ARM. Например, предположите, что требуемая плата является платой HiKey/Rock960 с архитектурой ARMv8, и ARM Вычисляют версию 19.05 Библиотеки.

dlcfg = coder.DeepLearningConfig('arm-compute');
dlcfg.ArmComputeVersion = '19.05';
dlcfg.ArmArchitecture = 'armv8';

Присвойте DeepLearningConfig свойство объекта cfg настройки генерации кода к объекту dlcfg настройки глубокого обучения.

cfg.DeepLearningConfig = dlcfg;

Сгенерируйте исходный код C++ при помощи codegen

codegen -config cfg segmentationUnetARM -args {ones(size(input_data),'uint16')} -d unet_predict -report

Код сгенерирован в unet_predict папка, которая расположена в текущей рабочей директории на хосте - компьютере.

Сгенерируйте zip-файл при помощи packNGo

packNGo функциональные пакеты все соответствующие файлы в сжатый zip-файл.

zipFileName = 'unet_predict.zip'; 
bInfo = load(fullfile('unet_predict','buildInfo.mat'));
packNGo(bInfo.buildInfo, {'fileName', zipFileName,'minimalHeaders', false, 'ignoreFileMissing',true});

Именем сгенерированного zip-файла является unet_predict.zip.

Скопируйте Сгенерированный zip-файл в Целевой компьютер

Скопируйте zip-файл в плату целевого компьютера. Извлеките содержимое zip-файла в папку и удалите zip-файл из оборудования.

В следующих командах, замене:

  • password с вашим паролем

  • username с вашим именем пользователя

  • targetname с именем вашего устройства

  • targetDir с папкой назначения для файлов

На платформе Linux®, чтобы передать и извлечь zip-файл на целевом компьютере, запускают эти команды:

if isunix, system(['sshpass -p password scp -r '  fullfile(pwd,zipFileName) ' username@targetname:targetDir/']), end
if isunix, system('sshpass -p password ssh username@targetname "if [ -d targetDir/unet_predict ]; then rm -rf targetDir/unet_predict; fi"'), end
if isunix, system(['sshpass -p password ssh username@targetname "unzip targetDir/' zipFileName ' -d targetDir/unet_predict"']), end
if isunix, system(['sshpass -p password ssh username@targetname "rm -rf  targetDir/' zipFileName '"']), end

На платформе Windows®, чтобы передать и извлечь zip-файл на целевом компьютере, запускают эти команды:

if ispc, system(['pscp.exe -pw password -r '  fullfile(pwd,zipFileName) ' username@targetname:targetDir/']), end
if ispc, system('plink.exe -l username -pw password targetname "if [ -d targetDir/unet_predict ]; then rm -rf targetDir/unet_predict; fi"'), end
if ispc, system(['plink.exe -l username -pw password targetname "unzip targetDir/' zipFileName ' -d targetDir/unet_predict"']), end
if ispc, system(['plink.exe -l username -pw password targetname "rm -rf  targetDir/' zipFileName '"']), end

Скопируйте вспомогательные файлы в целевой компьютер

Скопируйте эти файлы от хоста - компьютера до целевого компьютера:

  • Входные данные, input_data.txt

  • Make-файл для создания библиотеки, unet_predict_rtw.mk

  • Make-файл для создания исполняемой программы, makefile_unet_arm_generic.mk

В следующих командах, замене:

  • password с вашим паролем

  • username с вашим именем пользователя

  • targetname с именем вашего устройства

  • targetDir с папкой назначения для файлов

На платформе Linux®, чтобы передать вспомогательные файлы целевому компьютеру, запускают эти команды:

if isunix, system('sshpass -p password scp unet_predict_rtw.mk username@targetname:targetDir/unet_predict/'), end
if isunix, system('sshpass -p password scp input_data.txt username@targetname:targetDir/unet_predict/'), end
if isunix, system('sshpass -p password scp makefile_unet_arm_generic.mk username@targetname:targetDir/unet_predict/'), end

На платформе Windows®, чтобы передать вспомогательные файлы целевому компьютеру, запускают эти команды:

if ispc, system('pscp.exe -pw password unet_predict_rtw.mk username@targetname:targetDir/unet_predict/'), end
if ispc, system('pscp.exe -pw password input_data.txt username@targetname:targetDir/unet_predict/'), end
if ispc, system('pscp.exe -pw password makefile_unet_arm_generic.mk username@targetname:targetDir/unet_predict/'), end

Создайте библиотеку по целевому компьютеру

Чтобы создать библиотеку по целевому компьютеру, выполните сгенерированный make-файл на оборудовании ARM.

Убедитесь, что вы устанавливаете переменные окружения ARM_COMPUTELIB и LD_LIBRARY_PATH на целевом компьютере. Смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder). ARM_ARCH переменная используется в Make-файле, чтобы передать флаги компилятора на основе Архитектуры ARM. ARM_VER переменная используется в Make-файле, чтобы скомпилировать код на основе версии библиотеки ARM Compute.

На серверной платформе Linux запустите эту команду, чтобы создать библиотеку:

if isunix, system(['sshpass -p password ssh username@targetname "make -C targetDir/unet_predict/ -f unet_predict_rtw.mk ARM_ARCH=' dlcfg.ArmArchitecture ' ARM_VER=' dlcfg.ArmComputeVersion ' "']), end

На серверной платформе Windows запустите эту команду, чтобы создать библиотеку:

if ispc, system(['plink.exe -l username -pw password targetname "make -C targetDir/unet_predict/ -f unet_predict_rtw.mk ARM_ARCH=' dlcfg.ArmArchitecture ' ARM_VER=' dlcfg.ArmComputeVersion ' "']), end

Создайте исполняемый файл на цели

В этих командах замените targetDir с папкой назначения, где библиотека сгенерирована. Переменные heightwidth, и channels представляйте размерности входных данных.

main_unet_arm_generic.cpp C++ основной файл обертки, который вызывает функцию segmentationUnetARM и передает входное изображение ему. Создайте библиотеку с файлом обертки, чтобы создать исполняемый файл.

На серверной платформе Linux, чтобы создать исполняемый файл, запускают эти команды:

if isunix, system('sshpass -p password scp main_unet_arm_generic.cpp username@targetname:targetDir/unet_predict/'), end
if isunix, system(['sshpass -p password ssh username@targetname "make -C targetDir/unet_predict/ IM_H=' num2str(height) ' IM_W=' num2str(width) ' IM_C=' num2str(channels) ' -f makefile_unet_arm_generic.mk"']), end

На серверной платформе Windows, чтобы создать исполняемый файл, запускают эти команды:

if ispc, system('pscp.exe -pw password main_unet_arm_generic.cpp username@targetname:targetDir/unet_predict/'), end
if ispc, system(['plink.exe -l username -pw password targetname "make -C targetDir/unet_predict/ IM_H=' num2str(height) ' IM_W=' num2str(width) ' IM_C=' num2str(channels) ' -f makefile_unet_arm_generic.mk"']), end

Запустите исполняемый файл на целевом компьютере

Запустите Исполняемый файл на целевом компьютере с входным файлом изображения input_data.txt.

На серверной платформе Linux запустите эту команду:

if isunix, system('sshpass -p password ssh username@targetname "cd targetDir/unet_predict/; ./unet input_data.txt output_data.txt"'), end

На серверной платформе Windows запустите эту команду:

if ispc, system('plink.exe -l username -pw password targetname "cd targetDir/unet_predict/; ./unet input_data.txt output_data.txt"'), end

unet исполняемый файл принимает входные данные. Из-за большого размера input_data (2001x2001x7), легче обработать входное изображение в закрашенных фигурах. Исполняемый файл разделяет входное изображение в несколько закрашенных фигур, каждый соответствие сетевому входному размеру. Исполняемый файл выполняет предсказание на пикселях в одной конкретной закрашенной фигуре за один раз и затем комбинирует все закрашенные фигуры вместе.

Передайте Выход от целевого компьютера до MATLAB

Скопируйте сгенерированный выходной файл output_data.txt назад к текущему сеансу работы с MATLAB. На платформе Linux, запуске:

if isunix, system('sshpass -p password scp username@targetname:targetDir/unet_predict/output_data.txt ./'), end

Выполнять то же действие с платформой Windows, запуск:

if ispc, system('pscp.exe -pw password username@targetname:targetDir/unet_predict/output_data.txt ./'), end

Сохраните выходные данные в переменной segmentedImage:

segmentedImage = uint8(importdata('output_data.txt'));
segmentedImage = reshape(segmentedImage,[height,width]);

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

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

Удалите шум и случайные пиксели при помощи medfilt2 функция.

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

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

Эта строка кода создает вектор из имен классов. имена классов = net.Layers (конец).Classes; disp (имена классов);

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

Отобразите входные данные

figure(1);
imshow(histeq(input_data(:,:,1:3)));
title('Input Image');

cmap = jet(numel(classNames));
segmentedImageOut = labeloverlay(imadjust(input_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),segmentedImage,'Transparency',0,'Colormap',cmap);
figure(2);
imshow(segmentedImageOut);

Отобразите сегментированные данные

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

Отобразите сегментированное Изображение наложения

segmentedImageOverlay = labeloverlay(imadjust(input_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),segmentedImage,'Transparency',0.7,'Colormap',cmap);
figure(3);
imshow(segmentedImageOverlay);
title('Segmented Overlayed Image');

Ссылки

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

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

[3] Ссылочные используемые Входные данные являются частью данных о национальном парке Hamlin Beach. Следующие шаги могут использоваться, чтобы загрузить данные для дальнейшей оценки.

if ~exist(fullfile(pwd,'data'))
    url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat';
    downloadHamlinBeachMSIData(url,pwd+"/data/");
end

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

(MATLAB Coder) | (MATLAB Coder) | (MATLAB Coder) | (MATLAB Coder)

Похожие темы