В этом примере показано, как сгенерировать код CUDA® MEX для обнаружения дорожного знака и приложения для распознавания, которое использует глубокое обучение. Обнаружение дорожного знака и распознавание являются важным приложением для систем помощи водителю, помощи и предоставления информации к драйверу о дорожных знаках.

В этом примере обнаружения и распознавания дорожного знака вы выполняете три шага - обнаружение, Немаксимальное подавление (NMS) и распознавание. Во-первых, пример обнаруживает дорожные знаки на входном изображении при помощи сети обнаружения объектов, которая является вариантом сети You Only Look Once (YOLO). Затем перекрывающиеся обнаружения подавлены при помощи алгоритма NMS. Наконец, сеть распознавания классифицирует обнаруженные дорожные знаки.
CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.2 или выше.
NVIDIA инструментарий CUDA и драйвер.
Библиотека NVIDIA cuDNN.
Переменные окружения для компиляторов и библиотек. Для получения информации о поддерживаемых версиях компиляторов и библиотек, смотрите Сторонние продукты (GPU Coder). Для подготовки переменных окружения смотрите Подготовку Необходимых как условие продуктов (GPU Coder).
Интерфейс GPU Coder для Библиотек Глубокого обучения поддерживает пакет. Чтобы установить этот пакет поддержки, используйте Add-On Explorer.
Используйте coder.checkGpuInstall функция, чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
Сеть обнаружения обучена в среде даркнета и импортирована в MATLAB® для вывода. Поскольку размер дорожного знака относительно мал относительно того из изображения, и количество учебных выборок в классе меньше в обучающих данных, все дорожные знаки рассматриваются как единый класс для того, чтобы обучить сеть обнаружения.
Сеть обнаружения делит входное изображение на 7 7 сетка. Каждая ячейка сетки обнаруживает дорожный знак, если центр дорожного знака находится в пределах ячейки сетки. Каждая ячейка предсказывает две ограничительных рамки и музыку уверенности к этим ограничительным рамкам. Баллы уверенности указывают, содержит ли поле объект или нет. Каждая ячейка предсказывает на вероятности для нахождения дорожного знака в ячейке сетки. Итоговый счет является продуктом предыдущих баллов. Вы применяете порог 0,2 на этом итоговом счете, чтобы выбрать обнаружения.
Сеть распознавания обучена на тех же изображениях при помощи MATLAB.
trainRecognitionnet.m скрипт помощника показывает обучение сети распознавания.
Загрузите сети обнаружения и распознавания.
getTsdr();
Сеть обнаружения содержит 58 слоев включая свертку, текучий ReLU и полносвязные слоя.
load('yolo_tsr.mat');
yolo.Layers
ans =
58x1 Layer array with layers:
1 'input' Image Input 448x448x3 images
2 'conv1' Convolution 64 7x7x3 convolutions with stride [2 2] and padding [3 3 3 3]
3 'relu1' Leaky ReLU Leaky ReLU with scale 0.1
4 'pool1' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
5 'conv2' Convolution 192 3x3x64 convolutions with stride [1 1] and padding [1 1 1 1]
6 'relu2' Leaky ReLU Leaky ReLU with scale 0.1
7 'pool2' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
8 'conv3' Convolution 128 1x1x192 convolutions with stride [1 1] and padding [0 0 0 0]
9 'relu3' Leaky ReLU Leaky ReLU with scale 0.1
10 'conv4' Convolution 256 3x3x128 convolutions with stride [1 1] and padding [1 1 1 1]
11 'relu4' Leaky ReLU Leaky ReLU with scale 0.1
12 'conv5' Convolution 256 1x1x256 convolutions with stride [1 1] and padding [0 0 0 0]
13 'relu5' Leaky ReLU Leaky ReLU with scale 0.1
14 'conv6' Convolution 512 3x3x256 convolutions with stride [1 1] and padding [1 1 1 1]
15 'relu6' Leaky ReLU Leaky ReLU with scale 0.1
16 'pool6' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
17 'conv7' Convolution 256 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0]
18 'relu7' Leaky ReLU Leaky ReLU with scale 0.1
19 'conv8' Convolution 512 3x3x256 convolutions with stride [1 1] and padding [1 1 1 1]
20 'relu8' Leaky ReLU Leaky ReLU with scale 0.1
21 'conv9' Convolution 256 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0]
22 'relu9' Leaky ReLU Leaky ReLU with scale 0.1
23 'conv10' Convolution 512 3x3x256 convolutions with stride [1 1] and padding [1 1 1 1]
24 'relu10' Leaky ReLU Leaky ReLU with scale 0.1
25 'conv11' Convolution 256 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0]
26 'relu11' Leaky ReLU Leaky ReLU with scale 0.1
27 'conv12' Convolution 512 3x3x256 convolutions with stride [1 1] and padding [1 1 1 1]
28 'relu12' Leaky ReLU Leaky ReLU with scale 0.1
29 'conv13' Convolution 256 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0]
30 'relu13' Leaky ReLU Leaky ReLU with scale 0.1
31 'conv14' Convolution 512 3x3x256 convolutions with stride [1 1] and padding [1 1 1 1]
32 'relu14' Leaky ReLU Leaky ReLU with scale 0.1
33 'conv15' Convolution 512 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0]
34 'relu15' Leaky ReLU Leaky ReLU with scale 0.1
35 'conv16' Convolution 1024 3x3x512 convolutions with stride [1 1] and padding [1 1 1 1]
36 'relu16' Leaky ReLU Leaky ReLU with scale 0.1
37 'pool16' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
38 'conv17' Convolution 512 1x1x1024 convolutions with stride [1 1] and padding [0 0 0 0]
39 'relu17' Leaky ReLU Leaky ReLU with scale 0.1
40 'conv18' Convolution 1024 3x3x512 convolutions with stride [1 1] and padding [1 1 1 1]
41 'relu18' Leaky ReLU Leaky ReLU with scale 0.1
42 'conv19' Convolution 512 1x1x1024 convolutions with stride [1 1] and padding [0 0 0 0]
43 'relu19' Leaky ReLU Leaky ReLU with scale 0.1
44 'conv20' Convolution 1024 3x3x512 convolutions with stride [1 1] and padding [1 1 1 1]
45 'relu20' Leaky ReLU Leaky ReLU with scale 0.1
46 'conv21' Convolution 1024 3x3x1024 convolutions with stride [1 1] and padding [1 1 1 1]
47 'relu21' Leaky ReLU Leaky ReLU with scale 0.1
48 'conv22' Convolution 1024 3x3x1024 convolutions with stride [2 2] and padding [1 1 1 1]
49 'relu22' Leaky ReLU Leaky ReLU with scale 0.1
50 'conv23' Convolution 1024 3x3x1024 convolutions with stride [1 1] and padding [1 1 1 1]
51 'relu23' Leaky ReLU Leaky ReLU with scale 0.1
52 'conv24' Convolution 1024 3x3x1024 convolutions with stride [1 1] and padding [1 1 1 1]
53 'relu24' Leaky ReLU Leaky ReLU with scale 0.1
54 'fc25' Fully Connected 4096 fully connected layer
55 'relu25' Leaky ReLU Leaky ReLU with scale 0.1
56 'fc26' Fully Connected 539 fully connected layer
57 'softmax' Softmax softmax
58 'classoutput' Classification Output crossentropyex
Сеть распознавания содержит 14 слоев включая свертку, полностью соединенную, и классификация выходные слои.
load('RecognitionNet.mat');
convnet.Layers
ans =
14x1 Layer array with layers:
1 'imageinput' Image Input 48x48x3 images with 'zerocenter' normalization and 'randfliplr' augmentations
2 'conv_1' Convolution 100 7x7x3 convolutions with stride [1 1] and padding [0 0 0 0]
3 'relu_1' ReLU ReLU
4 'maxpool_1' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
5 'conv_2' Convolution 150 4x4x100 convolutions with stride [1 1] and padding [0 0 0 0]
6 'relu_2' ReLU ReLU
7 'maxpool_2' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
8 'conv_3' Convolution 250 4x4x150 convolutions with stride [1 1] and padding [0 0 0 0]
9 'maxpool_3' Max Pooling 2x2 max pooling with stride [2 2] and padding [0 0 0 0]
10 'fc_1' Fully Connected 300 fully connected layer
11 'dropout' Dropout 90% dropout
12 'fc_2' Fully Connected 35 fully connected layer
13 'softmax' Softmax softmax
14 'classoutput' Classification Output crossentropyex with '0' and 34 other classes
tsdr_predict Функция точки входаtsdr_predict.m функция точки входа берет вход изображений и обнаруживает дорожные знаки в изображении при помощи сети обнаружения. Функция подавляет перекрывающиеся обнаружения (NMS) при помощи selectStrongestBbox и распознает дорожный знак при помощи сети распознавания. Функция загружает сетевые объекты от yolo_tsr.mat в персистентную переменную detectionnet и RecognitionNet.mat в персистентную переменную recognitionnet. Функциональные повторные использования постоянные объекты на последующих вызовах.
type('tsdr_predict.m')
function [selectedBbox,idx] = tsdr_predict(img)
%#codegen
% This function detects the traffic signs in the image using Detection Network
% (modified version of Yolo) and recognizes(classifies) using Recognition Network
%
% Inputs :
%
% im : Input test image
%
% Outputs :
%
% selectedBbox : Detected bounding boxes
% idx : Corresponding classes
% Copyright 2017-2019 The MathWorks, Inc.
coder.gpu.kernelfun;
% resize the image
img_rz = imresize(img,[448,448]);
% Converting into BGR format
img_rz = img_rz(:,:,3:-1:1);
img_rz = im2single(img_rz);
%% TSD
persistent detectionnet;
if isempty(detectionnet)
detectionnet = coder.loadDeepLearningNetwork('yolo_tsr.mat','Detection');
end
predictions = detectionnet.activations(img_rz,56,'OutputAs','channels');
%% Convert predictions to bounding box attributes
classes = 1;
num = 2;
side = 7;
thresh = 0.2;
[h,w,~] = size(img);
boxes = single(zeros(0,4));
probs = single(zeros(0,1));
for i = 0:(side*side)-1
for n = 0:num-1
p_index = side*side*classes + i*num + n + 1;
scale = predictions(p_index);
prob = zeros(1,classes+1);
for j = 0:classes
class_index = i*classes + 1;
tempProb = scale*predictions(class_index+j);
if tempProb > thresh
row = floor(i / side);
col = mod(i,side);
box_index = side*side*(classes + num) + (i*num + n)*4 + 1;
bxX = (predictions(box_index + 0) + col) / side;
bxY = (predictions(box_index + 1) + row) / side;
bxW = (predictions(box_index + 2)^2);
bxH = (predictions(box_index + 3)^2);
prob(j+1) = tempProb;
probs = [probs;tempProb];
boxX = (bxX-bxW/2)*w+1;
boxY = (bxY-bxH/2)*h+1;
boxW = bxW*w;
boxH = bxH*h;
boxes = [boxes; boxX,boxY,boxW,boxH];
end
end
end
end
%% Run Non-Maximal Suppression on the detected bounding boxess
coder.varsize('selectedBbox',[98, 4],[1 0]);
[selectedBbox,~] = selectStrongestBbox(round(boxes),probs);
%% Recognition
persistent recognitionnet;
if isempty(recognitionnet)
recognitionnet = coder.loadDeepLearningNetwork('RecognitionNet.mat','Recognition');
end
idx = zeros(size(selectedBbox,1),1);
inpImg = coder.nullcopy(zeros(48,48,3,size(selectedBbox,1)));
for i = 1:size(selectedBbox,1)
ymin = selectedBbox(i,2);
ymax = ymin+selectedBbox(i,4);
xmin = selectedBbox(i,1);
xmax = xmin+selectedBbox(i,3);
% Resize Image
inpImg(:,:,:,i) = imresize(img(ymin:ymax,xmin:xmax,:),[48,48]);
end
for i = 1:size(selectedBbox,1)
output = recognitionnet.predict(inpImg(:,:,:,i));
[~,idx(i)]=max(output);
end
tsdr_predict ФункцияСоздайте объект настройки графического процессора для цели MEX и установите выходной язык на C++. Используйте coder.DeepLearningConfig функция, чтобы создать CuDNN объект настройки глубокого обучения и присвоение это к DeepLearningConfig свойство объекта настройки графического процессора кода. Чтобы сгенерировать MEX CUDA, используйте codegen команда и задает вход, чтобы иметь размер [480,704,3]. Это значение соответствует входному размеру изображения tsdr_predict функция.
cfg = coder.gpuConfig('mex'); cfg.TargetLang = 'C++'; cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn'); codegen -config cfg tsdr_predict -args {ones(480,704,3,'uint8')} -report
Code generation successful: To view the report, open('codegen/mex/tsdr_predict/html/report.mldatx').
Чтобы сгенерировать код при помощи TensorRT, передайте coder.DeepLearningConfig('tensorrt') как опция к настройке кодера возражают вместо 'cudnn'.
Загрузите входное изображение.
im = imread('stop.jpg');
imshow(im);

Вызовите tsdr_predict_mex на входном изображении.
im = imresize(im, [480,704]); [bboxes,classes] = tsdr_predict_mex(im);
Сопоставьте классификационные индексы с именами дорожного знака в словаре класса.
classNames = {'addedLane','slow','dip','speedLimit25','speedLimit35','speedLimit40','speedLimit45',...
'speedLimit50','speedLimit55','speedLimit65','speedLimitUrdbl','doNotPass','intersection',...
'keepRight','laneEnds','merge','noLeftTurn','noRightTurn','stop','pedestrianCrossing',...
'stopAhead','rampSpeedAdvisory20','rampSpeedAdvisory45','truckSpeedLimit55',...
'rampSpeedAdvisory50','turnLeft','rampSpeedAdvisoryUrdbl','turnRight','rightLaneMustTurn',...
'yield','yieldAhead','school','schoolSpeedLimit25','zoneAhead45','signalAhead'};
classRec = classNames(classes);
Отобразите обнаруженные дорожные знаки.
outputImage = insertShape(im,'Rectangle',bboxes,'LineWidth',3); for i = 1:size(bboxes,1) outputImage = insertText(outputImage,[bboxes(i,1)+bboxes(i,3) bboxes(i,2)-20],classRec{i},'FontSize',20,'TextColor','red'); end imshow(outputImage);

Включенный файл помощника tsdr_testVideo.m системы координат захватов от тестового видео, выполняет обнаружение дорожного знака и распознавание, и строит результаты на каждой системе координат тестового видео.
% Input video
v = VideoReader('stop.avi');
fps = 0; while hasFrame(v)
% Take a frame
picture = readFrame(v);
picture = imresize(picture,[920,1632]);
% Call MEX function for Traffic Sign Detection and Recognition
tic;
[bboxes,clases] = tsdr_predict_mex(picture);
newt = toc; % fps
fps = .9*fps + .1*(1/newt);% display
displayDetections(picture,bboxes,clases,fps);
endОчистите статические сетевые объекты, которые загрузились в память.
clear mex;