Обнаружение дорожного знака и распознавание

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

В этом примере, обнаружении дорожного знака и распознавании выполняется на трех шагах - обнаружение, Немаксимальное подавление (NMS) и распознавание. Во-первых, пример обнаруживает дорожные знаки на данном входном изображении с помощью сети обнаружения объектов, которая является вариантом сети You Only Look Once (YOLO). Затем перекрывающиеся обнаружения подавлены с помощью алгоритма NMS. Наконец, сеть распознавания используется для классификации обнаруженных дорожных знаков.

Предпосылки

  • CUDA включил NVIDIA®, графический процессор с вычисляет возможность 3.2 или выше.

  • NVIDIA инструментарий CUDA и драйвер.

  • Библиотека NVIDIA cuDNN v7 или выше.

  • Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Переменные окружения.

  • Deep Learning Toolbox™, чтобы использовать объект SeriesNetwork.

  • Image Processing Toolbox™ для чтения и отображения изображений.

  • Computer Vision Toolbox™ для видео средства чтения, средства просмотра и Немаксимального подавления (NMS) используется в примере.

  • GPU Coder™ для генерации кода CUDA.

  • Интерфейс GPU Coder для Библиотек Глубокого обучения поддерживает пакет. Чтобы установить этот пакет поддержки, используйте Add-On Explorer.

Проверьте среду графического процессора

Используйте coder.checkGpuInstall, функционируют и проверяют, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно.

coder.checkGpuInstall('gpu','codegen','cudnn','quiet');

О сетях обнаружения и распознавания

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

Сеть обнаружения делит входное изображение на 7x7, сетка и каждая ячейка сетки обнаруживают дорожный знак, если центр дорожного знака находится в пределах ячейки сетки. Каждая ячейка предсказывает две ограничительных рамки и музыку уверенности к этим ограничительным рамкам. Очки уверенности говорят нам, содержит ли поле объект или нет. Каждая ячейка также предсказывает на вероятности для нахождения дорожного знака в ячейке сетки. Итоговый счет является продуктом вышеупомянутых двух. Мы применяем порог 0,2 на этом итоговом счете, чтобы выбрать обнаружения.

Сеть распознавания также обучена на тех же изображениях при помощи MATLAB.

trainRecognitionnet.m скрипт демонстрирует обучение сети распознавания.

Получите предварительно обученный SeriesNetwork

Загрузите сети обнаружения и распознавания.

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 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

Сгенерируйте MEX CUDA для функции 'tsdr_predict'

Создайте объект настройки графического процессора для цели MEX и установите выходной язык на C++. Используйте кодер. 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'.

Запустите сгенерированный MEX

Загрузите входное изображение.

im = imread('stop.jpg');
imshow(im);

tsdr вызова предсказывают функцию на входном изображении.

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

Используйте ясный mex, чтобы удалить статические сетевые объекты, загруженные в памяти.

clear mex;

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте