Main Content

シングル ショット マルチボックス検出器を使用したオブジェクト検出のコードの生成

この例では、SSD ネットワーク (ssdObjectDetector オブジェクト) 用の CUDA® コードを生成し、NVIDIA® cuDNN ライブラリと TensorRT ライブラリを活用する方法を説明します。SSD ネットワークは、イメージ内の複数のオブジェクトをシングル ショットで検出する、フィードフォワード畳み込みニューラル ネットワークに基づいています。SSD ネットワークは、2 つのサブネットワークをもつと考えることができます。特徴抽出ネットワークに検出ネットワークが続きます。

この例では、Computer Vision Toolbox™ の "SSD 深層学習を使用したオブジェクト検出" の例で学習させたネットワークのコードを生成します。詳細については、SSD 深層学習を使用したオブジェクト検出を参照してください。"SSD 深層学習を使用したオブジェクト検出" の例では、特徴抽出に ResNet-50 を使用します。検出サブネットワークは特徴抽出ネットワークと比べて小さい CNN であり、少数の畳み込み層と SSD に固有の層で構成されます。

サードパーティの必要条件

必須

この例では、CUDA MEX を生成します。以下のサードパーティ要件が適用されます。

  • CUDA 対応 NVIDIA GPU および互換性のあるドライバー。

オプション

スタティック ライブラリ、ダイナミック ライブラリ、または実行可能ファイルなどの MEX 以外のビルドについて、この例では以下の要件も適用されます。

GPU 環境の検証

関数coder.checkGpuInstall (GPU Coder)を使用して、この例を実行するのに必要なコンパイラおよびライブラリが正しく設定されていることを検証します。

envCfg = coder.gpuEnvConfig('host');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

事前学習済みの DAG ネットワークの取得

この例では、事前学習済みの SSD ネットワークを含む ssdResNet50VehicleExample_20a MAT ファイルを使用します。このファイルのサイズは約 44 MB です。MathWorks® の Web サイトからファイルをダウンロードします。

ssdNetFile = matlab.internal.examples.downloadSupportFile('vision/data','ssdResNet50VehicleExample_20a.mat');

DAG ネットワークには、畳み込み層、ReLU 層、バッチ正規化層に加えて、アンカー ボックス層、SSD マージ層、焦点損失層など、180 個の層が含まれています。深層学習ネットワーク アーキテクチャを対話的に可視化して表示するには、関数 analyzeNetwork (Deep Learning Toolbox) を使用します。

load(ssdNetFile);
analyzeNetwork(detector.Network);

エントリポイント関数 ssdObj_detect

エントリポイント関数 ssdObj_detect.m は、イメージ入力を受け取り、ssdResNet50VehicleExample_20a.mat ファイルに保存されている深層学習ネットワークを使用して、イメージに対して検出器を実行します。この関数は、ネットワーク オブジェクトを ssdResNet50VehicleExample_20a.mat ファイルから永続変数 ssdObj に読み込み、それ以降の検出の呼び出しではこの永続オブジェクトを再利用します。

type('ssdObj_detect.m')
function outImg = ssdObj_detect(in,matFile)

%   Copyright 2019-2022 The MathWorks, Inc.

persistent ssdObj;

if isempty(ssdObj)
    ssdObj = coder.loadDeepLearningNetwork(matFile);
end

% Pass in input
[bboxes,~,labels] = detect(ssdObj,in,'Threshold',0.5);

% Convert categorical labels to cell array of charactor vectors for 
% execution
labels = cellstr(labels);

% Annotate detections in the image.
if ~isempty(labels)
    outImg = insertObjectAnnotation(in,'rectangle',bboxes,labels);
else
    outImg = in;
end

MEX コード生成の実行

エントリポイント関数 ssdObj_detect.m 用の CUDA コードを生成するには、MEX ターゲットの GPU コード構成オブジェクトを作成し、ターゲット言語を C++ に設定します。関数 coder.DeepLearningConfig (GPU Coder) を使用して CuDNN 深層学習構成オブジェクトを作成し、それを GPU コード構成オブジェクトの DeepLearningConfig プロパティに割り当てます。入力サイズを 300×300×3 に指定して codegen コマンドを実行します。この値は SSD ネットワークの入力層サイズに対応します。

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
inputArgs = {ones(300,300,3,'uint8'),coder.Constant(ssdNetFile)};
codegen -config cfg ssdObj_detect -args inputArgs -report
Code generation successful: View report

生成された MEX の実行

この例では、295 個のイメージを含んだ小さな車両データ セットを使用して、生成された MEX をテストします。これらのイメージの多くは、Caltech の Cars 1999 データ セットおよび Cars 2001 データ セットからのものです (Caltech Research Data Respository の Web サイトで入手可能)。Pietro Perona 氏によって作成されたもので、許可を得て使用しています。

車両データ セットを読み込み、10 個のイメージをランダムに選択して生成されたコードをテストします。

unzip vehicleDatasetImages.zip
imageNames = dir(fullfile(pwd,'vehicleImages','*.jpg'));
imageNames = {imageNames.name}';
rng(0);
imageIndices = randi(length(imageNames),1,10);

ビデオ入力をフレームごとに読み取り、検出器を使用してビデオ内の車両を検出します。

for idx = 1:10
    testImage = imread(fullfile(pwd,'vehicleImages',imageNames{imageIndices(idx)}));
    resizedImage = imresize(testImage,[300,300]);
    detectorOutput = ssdObj_detect_mex(resizedImage,ssdNetFile);
    imshow(detectorOutput);
    pause(0.5)
end

参考文献

[1] Liu, Wei, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng Yang Fu, and Alexander C. Berg. "SSD: Single shot multibox detector." In 14th European Conference on Computer Vision, ECCV 2016. Springer Verlag, 2016.