Генерация кода для глубокого обучения на Raspberry Pi

В этом примере показано, как сгенерировать и развернуть код для предсказания на Raspberry Pi™ при помощи codegen с пакетом поддержки MATLAB для оборудования Raspberry Pi.

Когда вы генерируете код для предсказания, пользующегося Библиотекой ARM® Compute и пакетом аппаратной поддержки, codegen генерирует код по хосту - компьютеру, копирует сгенерированные файлы в целевой компьютер и создает исполняемый файл на целевом компьютере.

Предпосылки

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

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

  • Библиотека компьютерного зрения с открытым исходным кодом

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

  • MATLAB® Coder™

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

  • Deep Learning Toolbox™

  • Пакет поддержки MATLAB для оборудования Raspberry Pi

Для поддерживаемых версий библиотек и для получения информации о подготовке переменных окружения, смотрите Предпосылки для Глубокого обучения для MATLAB Coder (MATLAB Coder). Этот пример не поддержан для MATLAB Online.

squeezenet_raspi_predict Функция

Этот пример использует сеть DAG SqueezeNet, чтобы показать, что классификация изображений с ARM Вычисляет Библиотеку. Предварительно обученный SqueezeNet для MATLAB доступен в Deep Learning Toolbox. squeezenet_arm_predict функционируйте загружает сеть SqueezeNet в персистентный сетевой объект. На последующих вызовах функции снова используется постоянный объект.

Так, чтобы сгенерированная исполняемая программа соединилась против библиотек OpenCV, squeezenet_arm_predict функция задает опции компоновщика при помощи coder.updateBuildInfo.

type squeezenet_raspi_predict
% Copyright 2018 The MathWorks, Inc.

function out = squeezenet_raspi_predict(in)
%#codegen

% A persistent object mynet is used to load the DAGNetwork object.
% At the first call to this function, the persistent object is constructed and
% set up. When the function is called subsequent times, the same object is reused 
% to call predict on inputs, avoiding reconstructing and reloading the
% network object.


persistent net;
opencv_linkflags = '`pkg-config --cflags --libs opencv`';
coder.updateBuildInfo('addLinkFlags',opencv_linkflags);
if isempty(net)
    net = coder.loadDeepLearningNetwork('squeezenet', 'squeezenet');
end

out = net.predict(in);

end


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

Создайте объект настройки генерации кода для генерации исполняемой программы. Задайте генерацию Кода С++.

cfg = coder.config('exe');
cfg.TargetLang = 'C++';

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

Создайте coder.ARMNEONConfig объект. Задайте версию библиотеки ARM Compute, которая находится на Raspberry Pi. Задайте архитектуру Raspberry Pi.

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

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

cfg.DeepLearningConfig = dlcfg;

Создайте связь с Raspberry Pi

Использование Пакет Поддержки MATLAB для Raspberry Pi Поддерживает функцию Пакета, raspi, создать связь с Raspberry Pi. В следующем коде, замене:

  • raspiname с именем вашего Raspberry Pi

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

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

r = raspi('raspiname','username','password');

Сконфигурируйте аппаратные параметры генерации кода для Raspberry Pi

Создайте coder.Hardware объект для Raspberry Pi и присоединения это к объекту настройки генерации кода.

hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;

Задайте папку сборки на Raspberry Pi

buildDir = '~/remoteBuildDir';
cfg.Hardware.BuildDir = buildDir;

Предоставьте C++ основной файл

C++ основной файл читает входное изображение, предсказание запусков на изображении, и отображает метки классификации на изображении.

Задайте основной файл в объекте настройки генерации кода.

cfg.CustomSource = 'main_squeezenet_raspi.cpp';

Сгенерируйте исполняемую программу на Raspberry Pi

Используйте codegen сгенерировать Код С++. Когда вы используете codegen с Пакетом Поддержки MATLAB для Оборудования Raspberry Pi исполняемый файл основан на Raspberry Pi.

Убедитесь, что вы устанавливаете переменные окружения ARM_COMPUTELIB и LD_LIBRARY_PATH на Raspberry Pi. Смотрите Предпосылки для Глубокого обучения для MATLAB Coder (MATLAB Coder).

codegen -config cfg squeezenet_raspi_predict -args {ones(227, 227, 3,'single')} -report

Выберите сгенерированную исполняемую директорию

Чтобы протестировать сгенерированный код на Raspberry Pi, скопируйте входное изображение в директорию сгенерированного кода. Можно найти эту директорию вручную или при помощи raspi.utils.getRemoteBuildDirectory API. Эта функция перечисляет директории двоичных файлов, которые сгенерированы при помощи codegen. Предположение, что двоичный файл найден только в одной директории, введите:

applicationDirPaths = raspi.utils.getRemoteBuildDirectory('applicationName','squeezenet_raspi_predict');
targetDirPath = applicationDirPaths{1}.directory;

Скопируйте файлы в качестве примера в Raspberry Pi

Чтобы скопировать файлы, требуемые запускать исполняемую программу, используйте putFile, который доступен с Пакетом Поддержки MATLAB для Оборудования Raspberry Pi.

r.putFile('synsetWords_squeezenet_raspi.txt', targetDirPath);
r.putFile('coffeemug.png',targetDirPath);

Запустите исполняемую программу на Raspberry Pi

Запустите исполняемую программу на Raspberry Pi из MATLAB и направьте выход назад к MATLAB.

exeName = 'squeezenet_raspi_predict.elf';
argsforexe = ' coffeemug.png '; % Provide the input image;
command = ['cd ' targetDirPath ';./' exeName argsforexe];
output = system(r,command)

Получите баллы предсказания

outputfile = [targetDirPath, '/output.txt'];
r.getFile(outputfile);

Сопоставьте баллы предсказания с метками

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

net = squeezenet;
ClassNames = net.Layers(end).ClassNames;

Считайте классификацию.

fid = fopen('output.txt') ;
S = textscan(fid,'%s');
fclose(fid) ;
S = S{1} ;
predict_scores = cellfun(@(x)str2double(x), S);

Удалите значения NaN, которые были строками.

predict_scores(isnan(predict_scores))=[];
[val,indx] = sort(predict_scores, 'descend');
scores = val(1:5)*100;
top5labels = ClassNames(indx(1:5));

Отобразите метки классификации на изображении.

im = imread('coffeemug.png');
im = imresize(im, [227 227]);
outputImage = zeros(227,400,3, 'uint8');
for k = 1:3
    outputImage(:,174:end,k) = im(:,:,k);
end
scol = 1;
srow = 1;
outputImage = insertText(outputImage, [scol, srow], 'Classification with Squeezenet', 'TextColor', 'w','FontSize',20, 'BoxColor', 'black');
srow = srow + 30;
for k = 1:5
    outputImage = insertText(outputImage, [scol, srow], [top5labels{k},' ',num2str(scores(k), '%2.2f'),'%'], 'TextColor', 'w','FontSize',15, 'BoxColor', 'black');
    srow = srow + 25;
end
imshow(outputImage);