В этом примере показано, как сгенерировать код для приложения сегментации изображений, которое использует глубокое обучение. Это использует 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 Online.
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);
Загрузите 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
(Deep Learning Toolbox) функция.
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;
codegen
codegen -config cfg segmentationUnetARM -args {ones(size(input_data),'uint16')} -d unet_predict -report
Код сгенерирован в unet_predict
папка, которая расположена в текущей рабочей директории на хосте - компьютере.
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-файл из оборудования.
В следующих командах, замене:
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. 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
с папкой назначения, где библиотека сгенерирована. Переменные height
width
, и 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), легче обработать входное изображение в закрашенных фигурах. Исполняемый файл разделяет входное изображение в несколько закрашенных фигур, каждый соответствие сетевому входному размеру. Исполняемый файл выполняет предсказание на пикселях в одной конкретной закрашенной фигуре за один раз и затем комбинирует все закрашенные фигуры вместе.
Скопируйте сгенерированный выходной файл 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]);
Эта строка кода создает вектор из имен классов.
classNames = net.Layers(end).Classes; disp(classNames);
Наложите метки на сегментированном тесте 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
coder.ARMNEONConfig
| coder.DeepLearningConfig
| coder.hardware
| packNGo