exponenta event banner

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

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

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

Предпосылки

  • Процессор ARM, поддерживающий расширение NEON и имеющий ОЗУ не менее 3GB

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

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

  • MATLAB ® Coder™

  • Пакет поддержки интерфейса кодера MATLAB для библиотек глубокого обучения

  • Глубокое обучение Toolbox™

Версия библиотеки вычислений ARM, используемая в этом примере, может не быть последней версией, поддерживаемой при создании кода. Сведения о поддерживаемых версиях библиотек и переменных среды см. в разделе Предварительные условия для глубокого обучения с помощью кодера MATLAB.

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

Обзор U-Net

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

Основанная на глубоком обучении семантическая сегментация может дать точное измерение растительного покрова с помощью аэрофотоснимков высокого разрешения. Одной из проблем таких вычислений является дифференциация классов, которые имеют сходные визуальные характеристики, такие как классификация зеленого пикселя как травы, кустарника или дерева. Для повышения точности классификации некоторые наборы данных содержат многоспектральные изображения, которые предоставляют дополнительную информацию о каждом пикселе. Например, набор данных парка штата Хэмлин-Бич дополняет цветные изображения каналами ближнего инфракрасного диапазона, которые обеспечивают более четкое разделение классов.

В этом примере используются данные парка штата Хэмлин-Бич [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 Функция точки входа

Функция начальной точки segyUnetARM.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);

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

Загрузить 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);

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

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

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

Данные многоспектрального изображения расположены в виде массивов numChannel-by-width-by-height. В MATLAB многоканальные изображения располагаются как массивы width-by-height-by-numChannel. Чтобы изменить форму данных таким образом, чтобы каналы находились в третьем измерении, используйте вспомогательную функцию, switchChannelsToThirdPlane.

test_data = switchChannelsToThirdPlane(test_data);

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

whos test_data

В этом примере используется обрезанная версия полного набора данных парка штата Хэмлин-Бич, который 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

  • Makefile для создания библиотеки, unet_predict_rtw.mk

  • Makefile для построения исполняемой программы, 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. ARM_ARCH используется в Makefile для передачи флагов компилятора на основе архитектуры ARM. ARM_VER используется в Makefile для компиляции кода на основе версии библиотеки вычислений ARM.

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

На хост-платформе 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

Эта строка кода создает вектор имен классов. classNames = сеть. Слои (конец) .Классы; 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 препринт arXiv:1505.04597, 2015.

[2] Кемкер, Р., С. Сальваджо и К. Канан. «Многоспектральный набор данных высокого разрешения для семантической сегментации». 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

См. также

| | |

Связанные темы