このページは前リリースの情報です。該当の英語のページはこのリリースで削除されています。
この例では、深層学習を使用する交通標識の検出および認識用途の CUDA® MEX コードを生成する方法を説明します。交通標識の検出および認識は、ドライバーに道路標識についての情報を提供して支援する運転者支援システムのための重要な用途です。
この交通標識の検出および認識の例では、検出、非最大抑制 (NMS)、および認識の 3 つのステップを実行します。この例では、最初に You Only Look Once (YOLO) ネットワークのバリアントであるオブジェクト検出ネットワークを使用して、入力イメージにある交通標識を検出します。次に、NMS アルゴリズムを使用して、重なりのある検出を抑制します。最後に、認識ネットワークによって検出された交通標識を分類します。
Compute Capability 3.2 以上の CUDA 対応 NVIDIA® GPU。
NVIDIA CUDA ツールキットおよびドライバー。
NVIDIA cuDNN ライブラリ。
コンパイラおよびライブラリの環境変数。サポートされているコンパイラおよびライブラリのバージョンの詳細は、サードパーティ製品を参照してください。環境変数の設定は、前提条件となる製品の設定を参照してください。
GPU Coder Interface for Deep Learning Libraries サポート パッケージ。このサポート パッケージをインストールするには、アドオン エクスプローラーを使用します。
関数 coder.checkGpuInstall
を使用し、この例を実行するのに必要なコンパイラおよびライブラリが正しく設定されていることを検証します。
envCfg = coder.gpuEnvConfig('host'); envCfg.DeepLibTarget = 'cudnn'; envCfg.DeepCodegen = 1; envCfg.Quiet = 1; coder.checkGpuInstall(envCfg);
検出ネットワークは、Darknet フレームワークで学習が行われ、推論のために MATLAB® にインポートされています。交通標識のサイズはイメージのサイズと比べて比較的小さく、学習データ内のクラスあたりの学習サンプル数が少ないため、すべての交通標識を検出ネットワークに学習させるための単一のクラスと見なします。
検出ネットワークは、入力イメージを 7 行 7 列のグリッドに分割します。各グリッド セルは、交通標識の中心がそのグリッド セル内にある場合に交通標識を検出します。各セルは、2 つの境界ボックスとそれらの境界ボックスの信頼スコアを予測します。信頼スコアは、そのボックスがオブジェクトを含んでいるかどうかを示します。各セルは、グリッド セル内で交通標識が見つかる確率を予測します。最終的なスコアは前述のスコアの積です。この最終スコアに 0.2 のしきい値を適用して検出を選択します。
認識ネットワークは、MATLAB を使用して同じイメージについて学習済みです。
trainRecognitionnet.m 補助スクリプトは、認識ネットワークの学習について示しています。
検出ネットワークと認識ネットワークをダウンロードします。
getTsdr();
検出ネットワークには、畳み込み層、漏洩 ReLU 層、全結合層など、58 個の層が含まれています。
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 with '1' and 538 other classes
認識ネットワークには、畳み込み層、全結合層、分類出力層など、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 は、イメージ入力を受け取り、検出ネットワークを使用してイメージ内の交通標識を検出します。この関数は、selectStrongestBbox
を使用して重なりのある検出を抑制し (NMS)、認識ネットワークを使用して交通標識を認識します。この関数は、ネットワーク オブジェクトを 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-2020 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
の CUDA MEX の生成MEX ターゲットの GPU 構成オブジェクトを作成し、ターゲット言語を C++ に設定します。関数 coder.DeepLearningConfig
を使用して CuDNN
深層学習構成オブジェクトを作成し、それを GPU コード構成オブジェクトの DeepLearningConfig
プロパティに割り当てます。CUDA MEX を生成するには、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 を使用してコードを生成するには、'cudnn'
の代わりに、coder.DeepLearningConfig('tensorrt')
をオプションとしてコーダー構成オブジェクトに渡します。
入力イメージを読み込みます。
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;
codegen
| coder.CuDNNConfig
| coder.DeepLearningConfig
| coder.gpuEnvConfig
| coder.loadDeepLearningNetwork