В этом примере показано, как сгенерировать код CUDA® MEX для обнаружения дорожного знака и приложения для распознавания, которое использует глубокое обучение. Обнаружение дорожного знака и распознавание являются важным приложением для систем помощи водителю, помощи и предоставления информации к драйверу о дорожных знаках.
В этом примере обнаружения и распознавания дорожного знака вы выполняете три шага - обнаружение, Немаксимальное подавление (NMS) и распознавание. Во-первых, пример обнаруживает дорожные знаки на входном изображении при помощи сети обнаружения объектов, которая является вариантом сети You Only Look Once (YOLO). Затем перекрывающиеся обнаружения подавлены при помощи алгоритма NMS. Наконец, сеть распознавания классифицирует обнаруженные дорожные знаки.
Необходимый
Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.
CUDA® включил NVIDIA® графический процессор и совместимый драйвер.
Дополнительный
Для сборок неMEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Библиотека NVIDIA cuDNN.
Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Стороннее Оборудование и Подготовку Необходимых как условие продуктов.
Используйте 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
yolo = SeriesNetwork with properties: Layers: [58×1 nnet.cnn.layer.Layer] InputNames: {'input'} OutputNames: {'classoutput'}
Чтобы просмотреть сетевую архитектуру, используйте analyzeNetwork
(Deep Learning Toolbox) функция.
analyzeNetwork(yolo)
Сеть распознавания содержит 14 слоев включая свертку, полностью соединенную, и классификация выходные слои.
load('RecognitionNet.mat');
convnet
convnet = SeriesNetwork with properties: Layers: [14×1 nnet.cnn.layer.Layer] InputNames: {'imageinput'} OutputNames: {'classoutput'}
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-2021 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: View report
Чтобы сгенерировать код при помощи 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
системы координат захватов от тестового видео, выполняет обнаружение дорожного знака и распознавание, и строит результаты на каждой системе координат тестового видео.
type tsdr_testVideo
function tsdr_testVideo % Copyright 2017-2021 The MathWorks, Inc. % Input video v = VideoReader('stop.avi'); %% Integrated codegeneration for Traffic Sign Detection and Recognition % Generate MEX cfg = coder.config('mex'); cfg.GpuConfig = coder.gpu.config; cfg.GpuConfig.Enabled = true; cfg.GenerateReport = false; cfg.TargetLang = 'C++'; % Create a GPU Configuration object for MEX target setting target language % to C++. Run the |codegen| command specifying an input of input video % frame size. This corresponds to the input image size of tsdr_predict % function. codegen -config cfg tsdr_predict -args {ones(480,704,3 ,'uint8')} fps = 0; while hasFrame(v) % Take a frame picture = readFrame(v); picture = imresize(picture,[480,704]); % 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 diplayDetections(picture,bboxes,clases,fps); end end function diplayDetections(im,boundingBoxes,classIndices,fps) % Function for inserting the detected bounding boxes and recognized classes % and displaying the result % % Inputs : % % im : Input test image % boundingBoxes : Detected bounding boxes % classIndices : Corresponding classes % % Traffic Signs (35) 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'}; outputImage = insertShape(im,'Rectangle',boundingBoxes,'LineWidth',3); for i = 1:size(boundingBoxes,1) ymin = boundingBoxes(i,2); xmin = boundingBoxes(i,1); xmax = xmin+boundingBoxes(i,3); % inserting class as text at YOLO detection classRec = classNames{classIndices(i)}; outputImage = insertText(outputImage,[xmax ymin-20],classRec,... 'FontSize',20,'TextColor','red'); end outputImage = insertText(outputImage,... round(([size(outputImage,1) 40]/2)-20),... ['Frame Rate: ',num2str(fps)],'FontSize',20,'TextColor','red'); imshow(outputImage); end