В этом примере показано, как использовать codegen
команда для генерации кода для приложения классификации изображений, использующего глубокое обучение на процессорах Intel ®. Сгенерированный код использует Math Kernel Library для глубоких нейронных сетей (MKL-DNN). Этот пример состоит из двух частей:
В первой части показано, как сгенерировать MEX-функцию, которая принимает пакет изображений как вход.
Вторая часть показывает, как сгенерировать исполняемый файл, который принимает пакет изображений как вход.
Процессор Intel с поддержкой инструкций Intel Advanced Vector Extensions 2 (Intel AVX2)
Intel Math Kernel Library для глубоких нейронных сетей (MKL-DNN)
Переменные окружения для компиляторов и библиотек. Дополнительные сведения о поддерживаемых версиях компиляторов см. в разделе Поддерживаемые компиляторы. Для настройки переменных окружения смотрите Необходимые условия для глубокого обучения с MATLAB Coder.
Этот пример поддерживается на платформах Linux ®, Windows ® и Mac ® и не поддерживается для MATLAB Online.
Загрузите выборку видео файла.
if ~exist('./object_class.avi', 'file') url = 'https://www.mathworks.com/supportfiles/gpucoder/media/object_class.avi.zip'; websave('object_class.avi.zip',url); unzip('object_class.avi.zip'); end
resnet_predict
ФункцияЭтот пример использует сетевую ResNet-50 DAG, чтобы показать классификацию изображений на рабочих столах Intel. Предварительно обученная модель ResNet-50 для MATLAB доступна в рамках пакета поддержки Deep Learning Toolbox Model for ResNet-50 Network.
The resnet_predict
функция загружает ResNet-50 сеть в объект постоянной сети, а затем выполняет предсказание на входе. Последующие вызовы функции повторно используют объект постоянной сети.
type resnet_predict
% Copyright 2020 The MathWorks, Inc. function out = resnet_predict(in) %#codegen % A persistent object mynet is used to load the series network object. % At the first call to this function, the persistent object is constructed and % setup. 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 mynet; if isempty(mynet) % Call the function resnet50 that returns a DAG network % for ResNet-50 model. mynet = coder.loadDeepLearningNetwork('resnet50','resnet'); end % pass in input out = mynet.predict(in);
resnet_predict
Чтобы сгенерировать MEX-функцию для resnet_predict
функция, использование codegen
с объектом строения глубокого обучения для библиотеки MKL-DNN. Присоедините объект строения глубокого обучения к объекту строения генерации кода MEX, которому вы передаете codegen
. Запуск codegen
и задайте вход как 4D матрицу размера [224,224,3,|batchSize|]. Это значение соответствует размеру входного слоя ResNet-50 сети.
batchSize = 5; cfg = coder.config('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('mkldnn'); codegen -config cfg resnet_predict -args {ones(224,224,3,batchSize,'single')} -report
Code generation successful: To view the report, open('codegen\mex\resnet_predict\html\report.mldatx').
Предполагая, что Object_class.avi видео файла уже загружено. Создайте объект videoReader и прочитайте пять систем координат с помощью функции videoReader read. Поскольку значение batchSize установлено равным 5, считайте 5 изображений. Измените размер пакета входа изображений до размера, необходимого для сброса размера 50, ожидаемого ResNet50 сети.
videoReader = VideoReader('Object_class.avi'); imBatch = read(videoReader,[1 5]); imBatch = imresize(imBatch, [224,224]);
Вызовите сгенерированный resnet_predict_mex
функция, которая выводит результаты классификации для входов, которые вы предоставляете.
predict_scores = resnet_predict_mex(single(imBatch));
Получите 5 лучшие счета вероятностей и их меток для каждого изображения в пакете.
[val,indx] = sort(transpose(predict_scores), 'descend'); scores = val(1:5,:)*100; net = resnet50; classnames = net.Layers(end).ClassNames; for i = 1:batchSize labels = classnames(indx(1:5,i)); disp(['Top 5 predictions on image, ', num2str(i)]); for j=1:5 disp([labels{j},' ',num2str(scores(j,i), '%2.2f'),'%']) end end
Для предсказаний на первом изображении сопоставьте пять лучших счетов предсказания со словами в synset
словарь.
fid = fopen('synsetWords.txt'); synsetOut = textscan(fid,'%s', 'delimiter', '\n'); synsetOut = synsetOut{1}; fclose(fid); [val,indx] = sort(transpose(predict_scores), 'descend'); scores = val(1:5,1)*100; top5labels = synsetOut(indx(1:5,1));
Отобразите пять лучших классификационных меток на изображении.
outputImage = zeros(224,400,3, 'uint8'); for k = 1:3 outputImage(:,177:end,k) = imBatch(:,:,k,1); end
scol = 1; srow = 1; outputImage = insertText(outputImage, [scol, srow], 'Classification with ResNet-50', '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);
Очистить сохраняющийся сетевой объект из памяти.
clear mex;
resnet_predict_exe
Функция точки входаЧтобы сгенерировать исполняемый файл из кода MATLAB, задайте новую функцию точки входа resnet_predict_exe
. Эта функция аналогична предыдущей функции точки входа resent_predict
но, в сложение, включает код для предварительной обработки и постобработки. API, который resnet_predict_exe
использование не зависит от платформы. Эта функция принимает видео и размер пакета как входные параметры. Эти аргументы являются константами во время компиляции.
type resnet_predict_exe
% Copyright 2020 The MathWorks, Inc. function resnet_predict_exe(inputVideo,batchSize) %#codegen % A persistent object mynet is used to load the series network object. % At the first call to this function, the persistent object is constructed and % setup. 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 mynet; if isempty(mynet) % Call the function resnet50 that returns a DAG network % for ResNet-50 model. mynet = coder.loadDeepLearningNetwork('resnet50','resnet'); end % Create video reader and video player objects % videoReader = VideoReader(inputVideo); depVideoPlayer = vision.DeployableVideoPlayer; % Read the classification label names % synsetOut = readImageClassLabels('synsetWords.txt'); i=1; % Read frames until end of video file % while ~(i+batchSize > (videoReader.NumFrames+1)) % Read and resize batch of frames as specified by input argument% reSizedImagesBatch = readImageInputBatch(videoReader,batchSize,i); % run predict on resized input images % predict_scores = mynet.predict(reSizedImagesBatch); % overlay the prediction scores on images and display % overlayResultsOnImages(predict_scores,synsetOut,reSizedImagesBatch,batchSize,depVideoPlayer) i = i+ batchSize; end release(depVideoPlayer); end function synsetOut = readImageClassLabels(classLabelsFile) % Read the classification label names from the file % % Inputs : % classLabelsFile - supplied by user % % Outputs : % synsetOut - cell array filled with 1000 image class labels synsetOut = cell(1000,1); fid = fopen(classLabelsFile); for i = 1:1000 synsetOut{i} = fgetl(fid); end fclose(fid); end function reSizedImagesBatch = readImageInputBatch(videoReader,batchSize,i) % Read and resize batch of frames as specified by input argument% % % Inputs : % videoReader - Object used for reading the images from video file % batchSize - Number of images in batch to process. Supplied by user % i - index to track frames read from video file % % Outputs : % reSizedImagesBatch - Batch of images resized to 224x224x3xbatchsize img = read(videoReader,[i (i+batchSize-1)]); reSizedImagesBatch = coder.nullcopy(ones(224,224,3,batchSize,'like',img)); resizeTo = coder.const([224,224]); reSizedImagesBatch(:,:,:,:) = imresize(img,resizeTo); end function overlayResultsOnImages(predict_scores,synsetOut,reSizedImagesBatch,batchSize,depVideoPlayer) % Read and resize batch of frames as specified by input argument% % % Inputs : % predict_scores - classification results for given network % synsetOut - cell array filled with 1000 image class labels % reSizedImagesBatch - Batch of images resized to 224x224x3xbatchsize % batchSize - Number of images in batch to process. Supplied by user % depVideoPlayer - Object for displaying results % % Outputs : % Predicted results overlayed on input images % sort the predicted scores % [val,indx] = sort(transpose(predict_scores), 'descend'); for j = 1:batchSize scores = val(1:5,j)*100; outputImage = zeros(224,400,3, 'uint8'); for k = 1:3 outputImage(:,177:end,k) = reSizedImagesBatch(:,:,k,j); end % Overlay the results on image % scol = 1; srow = 1; outputImage = insertText(outputImage, [scol, srow], 'Classification with ResNet-50', 'TextColor', [255 255 255],'FontSize',20, 'BoxColor', [0 0 0]); srow = srow + 30; for k = 1:5 scoreStr = sprintf('%2.2f',scores(k)); outputImage = insertText(outputImage, [scol, srow], [synsetOut{indx(k,j)},' ',scoreStr,'%'], 'TextColor', [255 255 255],'FontSize',15, 'BoxColor', [0 0 0]); srow = srow + 25; end depVideoPlayer(outputImage); end end
resnet_predict_exe
ФункцияФункция resnet_predict_exe
содержит четыре подраздела, которые выполняют эти действия:
Считайте классификационные метки из предоставленного входного текстового файла
Считывайте вход пакет изображений и изменяйте их размер по мере необходимости в сети
Выполните вывод для входного пакета изображений
Наложите результаты на изображения
Для получения дополнительной информации о каждом из этих шагов см. последующие разделы.
readImageClassLabels
ФункцияЭта функция принимает synsetWords.txt
файл как входной параметр. Он считывает метки классификации и заполняет массив ячеек.
function synsetOut = readImageClassLabels(classLabelsFile) % Read the classification label names from the file % % Inputs : % classLabelsFile - supplied by user % % Outputs : % synsetOut - cell array filled with 1000 image class labels
synsetOut = cell(1000,1); fid = fopen(classLabelsFile); for i = 1:1000 synsetOut{i} = fgetl(fid); end fclose(fid); end
readImageInputBatch
ФункцияЭта функция считывает и изменяет размер изображений из входа файла видео, который передается в функцию как входной параметр. Он считывает указанные входные изображения и изменяет их размер до 224x224x3, который является размером, ожидаемым сетью resnet50.
function reSizedImagesBatch = readImageInputBatch(videoReader,batchSize,i) % Read and resize batch of frames as specified by input argument% % % Inputs : % videoReader - Object used for reading the images from video file % batchSize - Number of images in batch to process. Supplied by user % i - index to track frames read from video file % % Outputs : % reSizedImagesBatch - Batch of images resized to 224x224x3xbatchsize
img = read(videoReader,[i (i+batchSize-1)]); reSizedImagesBatch = coder.nullcopy(ones(224,224,3,batchSize,'like',img)); resizeTo = coder.const([224,224]); reSizedImagesBatch(:,:,:,:) = imresize(img,resizeTo); end
mynet.predict
ФункцияЭта функция принимает измененный размер пакета изображений как вход и возвращает результаты предсказания.
% run predict on resized input images % predict_scores = mynet.predict(reSizedImagesBatch);
overlayResultsOnImages
ФункцияЭта функция принимает результаты предсказания и сортирует их в порядке убывания. Он накладывает эти результаты на входные изображения и отображает их.
function overlayResultsOnImages(predict_scores,synsetOut,reSizedImagesBatch,batchSize,depVideoPlayer) % Read and resize batch of frames as specified by input argument% % % Inputs : % predict_scores - classification results for given network % synsetOut - cell array filled with 1000 image class labels % reSizedImagesBatch - Batch of images resized to 224x224x3xbatchsize % batchSize - Number of images in batch to process. Supplied by user % depVideoPlayer - Object for displaying results % % Outputs : % Predicted results overlayed on input images
% sort the predicted scores % [val,indx] = sort(transpose(predict_scores), 'descend');
for j = 1:batchSize scores = val(1:5,j)*100; outputImage = zeros(224,400,3, 'uint8'); for k = 1:3 outputImage(:,177:end,k) = reSizedImagesBatch(:,:,k,j); end
% Overlay the results on image % scol = 1; srow = 1; outputImage = insertText(outputImage, [scol, srow], 'Classification with ResNet-50', 'TextColor', [255 255 255],'FontSize',20, 'BoxColor', [0 0 0]); srow = srow + 30; for k = 1:5 scoreStr = sprintf('%2.2f',scores(k)); outputImage = insertText(outputImage, [scol, srow], [synsetOut{indx(k,j)},' ',scoreStr,'%'], 'TextColor', [255 255 255],'FontSize',15, 'BoxColor', [0 0 0]); srow = srow + 25; end
depVideoPlayer(outputImage); end end
Создайте объект строения кода для генерации исполняемого файла. Прикрепите к нему объект строения глубокого обучения. Установите batchSize
и inputVideoFile
переменные.
Если вы не намерены создавать пользовательскую функцию C++ main и вместо этого используете сгенерированный пример C++ main, установите GenerateExampleMain
параметр в 'GenerateCodeAndCompile'
. Также отключите cfg. EnableOpenMP, чтобы убедиться, что нет никаких библиотечных зависимостей openmp, когда вы запускаете свой исполняемый файл с рабочего стола.
cfg = coder.config('exe'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('mkldnn'); batchSize = 5; inputVideoFile = 'object_class.avi'; cfg.GenerateExampleMain = 'GenerateCodeAndCompile'; cfg.EnableOpenMP = 0;
Запуск codegen
команда для создания исполняемого файла. Запустите сгенерированный исполняемый resnet_predict_exe либо в командной строке MATLAB, либо на настольном терминале.
codegen -config cfg resnet_predict_exe -args {coder.Constant(inputVideoFile), coder.Constant(batchSize)} -report system('./resnet_predict_exe')
codegen
| coder.DeepLearningConfig
| coder.loadDeepLearningNetwork
| coder.MklDNNConfig