В этом примере показано, как сгенерировать код для приложения сегментации изображений, которое использует глубокое обучение. Он использует codegen
Команда, чтобы сгенерировать статическую библиотеку, которая выполняет предсказание для объекта сети DAG для U-Net. U-Net нейронной сети для глубокого обучения для сегментации изображений.
Для аналогичного примера, который использует U-Net для сегментации изображений, но не использует codegen
команда, см. Семантическая сегментация мультиспектральных изображений с использованием глубокого обучения (Image Processing Toolbox).
Процессор ARM, поддерживающий расширение NEON и имеющий ОЗУ не менее 3GB
ARM Compute Library (на целевом оборудовании ARM)
Переменные окружения для компиляторов и библиотек
MATLAB ® Coder™
Пакет поддержки MATLAB Coder Interface for Глубокое Обучение Libraries
Deep Learning Toolbox™
Версия библиотеки ARM Compute, которую использует этот пример, может быть не последней версией, которая поддержки генерацию кода. Для получения информации о поддерживаемых версиях библиотек и о переменных окружения, смотрите Необходимые условия для глубокого обучения с MATLAB Coder (MATLAB Coder).
Этот пример не поддерживается в MATLAB Online.
U-Net [1] является типом сверточной нейронной сети (CNN), предназначенной для семантической сегментации изображений. В U-Net начальная серия сверточных слоев перемежается с максимальными слоями объединения, последовательно уменьшая разрешение входного изображения. Эти слои сопровождаются серией сверточных слоев, чередующихся с операторами повышающей дискретизации, последовательно увеличивая разрешение входного изображения. Комбинация этих двух последовательных путей образует U-образный график. Сеть U-Net была первоначально обучена для выполнения предсказания в приложениях сегментации биомедицинских изображений. Этот пример демонстрирует способность сети отслеживать изменения лесного покрова с течением времени. Природоохранные учреждения отслеживают обезлесение для оценки и квалификации экологического и экологического здоровья области.
Семантическая сегментация на основе глубокого обучения может привести к точному измерению растительного покрова с помощью воздушных фотографий с высоким разрешением. Одна из проблем таких расчетов заключается в дифференциации классов, имеющих сходные визуальные характеристики, такие как классификация зеленого пикселя как травы, кустарника или дерева. Чтобы повысить точность классификации, некоторые наборы данных содержат мультиспектральные изображения, которые предоставляют дополнительную информацию о каждом пикселе. Например, набор данных Hamlin Beach State Park дополняет цветные изображения ближними инфракрасными каналами, которые обеспечивают более четкое разделение классов.
Этот пример использует Hamlin Beach State Park Data [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 выполняет лоскутную семантическую сегментацию входного изображения с помощью сети 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
функция.
analyzeNetwork(net);
Загрузите данные о государственном парке Хамлин-Бич.
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-by-width-by-height. В MATLAB многоканальные изображения расположены как массивы width-by-height-by-numChannels. Чтобы изменить форму данных так, чтобы каналы находились в третьей размерности, используйте функцию helper, switchChannelsToThirdPlane
.
test_data = switchChannelsToThirdPlane(test_data);
Подтвердите, что данные имеют правильную структуру (последние каналы).
whos test_data
Этот пример использует обрезанную версию полного набора данных Hamlin 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 Compute Library версии 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
The 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 (MATLAB Coder). The ARM_ARCH
переменная используется в Make-файле для передачи флагов компилятора на основе архитектуры ARM. The 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
The unet
executable принимает входные данные. Из-за большого размера 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. Слои (конец) .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] Роннебергер, Олаф, Филипп Фишер и Томас Брокс. «U-Net: Сверточные сети для сегментации биомедицинских изображений». arXiv preprint arXiv:1505.04597, 2015.
[2] Kemker, R., C. Salvaggio, and C. Kanan. «Мультиспектральный набор данных высокого разрешения для семантической сегментации». CoRR, abs/1703.01918, 2017.
[3] Используемые справочные входные данные являются частью данных парка штата Хэмлин-Бич. Следующие шаги могут использоваться для загрузки данных для дальнейшей оценки.
if ~exist(fullfile(pwd,'data')) url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat'; downloadHamlinBeachMSIData(url,pwd+"/data/"); end
coder.ARMNEONConfig
(MATLAB Coder) | coder.DeepLearningConfig
(MATLAB Coder) | coder.hardware
(MATLAB Coder) | packNGo
(MATLAB Coder)