Main Content

YOLO v3 深層学習を使用したオブジェクト検出用のコード生成

この例では、カスタム層を使用した You Only Look Once (YOLO) v3 オブジェクト検出器用の CUDA® MEX を生成する方法を示します。YOLO v3 は YOLO v2 を改良したもので、複数のスケールにおける検出を追加してより小さなオブジェクトを検出できるようになっています。さらに、学習で使用される損失関数は、境界ボックス回帰用の平均二乗誤差と、オブジェクト分類用のバイナリ交差エントロピーに分割されており、検出精度が向上しています。この例で使用する YOLO v3 ネットワークは、Computer Vision Toolbox (TM) の "YOLO v3 深層学習を使用したオブジェクトの検出" の例を使用して学習させたものです。詳細は、YOLO v3 深層学習を使用したオブジェクトの検出 (Computer Vision Toolbox) を参照してください。

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

必須

  • 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);

YOLO v3 ネットワーク

この例の YOLO v3 ネットワークは、squeezenetがベースとなっています。このネットワークは、SqueezeNet の特徴抽出ネットワークを使用し、最後に 2 つの検出ヘッドが追加されています。2 番目の検出ヘッドのサイズは、最初の検出ヘッドの 2 倍となっているため、小さなオブジェクトをより的確に検出できます。検出するオブジェクトのサイズに基づいて、さまざまなサイズの検出ヘッドを任意の数で指定できます。YOLO v3 ネットワークは、学習データを使用して推定されたアンカー ボックスを使用します。これにより、データセットの種類に対応した初期の事前確率が改善され、ボックスを正確に予測できるようにネットワークに学習させることができます。アンカー ボックスの詳細については、アンカー ボックスによるオブジェクトの検出 (Computer Vision Toolbox)を参照してください。

この例の YOLO v3 ネットワークを次の図に示します。

各検出ヘッドは、境界ボックス座標 (x、y、幅、高さ)、オブジェクトの信頼度、および各アンカー ボックス マスクに対するクラスの確率を予測します。そのため、各検出ヘッドにおける最終畳み込み層の出力フィルターの数は、アンカー ボックス マスクの数と、アンカー ボックスあたりの予測要素の数を乗算したものになります。この検出ヘッドは、ネットワークの出力層を構成します。

事前学習済みの YOLO v3 ネットワーク

この例では、事前学習済みの YOLO v3 ネットワークを含む yolov3SqueezeNetVehicleExample_21aSPKG.zip ファイルを使用します。この例で使用する YOLO v3 ネットワークの学習は、YOLO v3 深層学習を使用したオブジェクトの検出 (Computer Vision Toolbox)で説明した手順を使用して行っています。MathWorks の Web サイトからファイルをダウンロードし、ファイルを解凍します。

fileName = matlab.internal.examples.downloadSupportFile('vision/data/','yolov3SqueezeNetVehicleExample_21aSPKG.zip');
data = unzip(fileName);
matFile = data{1,1};
vehicleDetector = load(matFile);
net = vehicleDetector.detector.Network
net = 
  dlnetwork with properties:

         Layers: [75×1 nnet.cnn.layer.Layer]
    Connections: [84×2 table]
     Learnables: [66×3 table]
          State: [6×3 table]
     InputNames: {'data'}
    OutputNames: {'customOutputConv1'  'customOutputConv2'}
    Initialized: 1

メモ: 事前学習済みの検出器ネットワークは、Computer Vision Toolbox™ Model for YOLO v3 Object Detection サポート パッケージからも利用できます。

この事前学習済みネットワークを使用するには、最初にアドオン エクスプローラーから Computer Vision Toolbox Model for YOLO v3 Object Detection をインストールしなければなりません。アドオンのインストールの詳細については、アドオンの取得と管理を参照してください。

次に、ネットワークを yolov3ObjectDetector オブジェクトから MAT ファイルに保存して続行します。次に例を示します。

detector = yolov3ObjectDetector('darknet53-coco');
net = detector.Network;
matFile = 'pretrainedYOLOv3Detector.mat';
save(matFile,'net');

エントリポイント関数 yolov3Detect

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

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

%   Copyright 2021 The MathWorks, Inc.

persistent yolov3Obj;

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

% Call to detect method
[bboxes,~,labels] = yolov3Obj.detect(in,'Threshold',0.5);

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

% Annotate detections in the image.
outImg = insertObjectAnnotation(in,'rectangle',bboxes,labels);

CUDA MEX の生成

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

cfg = coder.gpuConfig('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
cfg.GenerateReport = true;
inputArgs = {ones(227,227,3,'uint8'),coder.Constant(matFile)};

codegen -config cfg yolov3Detect -args inputArgs -report
Code generation successful: View report

TensorRT ターゲット用の CUDA® コードを生成するには、CuDNN 構成オブジェクトではなく、TensorRT 深層学習構成オブジェクトを使用します。同様に、MKLDNN ターゲット用のコードを生成するには、CPU コード構成オブジェクトを作成し、その DeepLearningConfig プロパティとして MKLDNN 深層学習構成オブジェクトを使用します。

生成された MEX の実行

ビデオ ファイル リーダーを設定し、入力ビデオを読み取ります。ビデオ プレイヤーを作成し、ビデオと出力の検出を表示します。

videoFile = 'highway_vehicles.mp4';
videoFreader = vision.VideoFileReader(videoFile,'VideoOutputDataType','uint8');
depVideoPlayer = vision.DeployableVideoPlayer('Size','Custom','CustomSize',[640 480]);

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

cont = ~isDone(videoFreader);
while cont
    I = step(videoFreader);
    in = imresize(I,[227,227]);
    out = yolov3Detect_mex(in,matFile);
    step(depVideoPlayer, out);
    % Exit the loop if the video player figure window is closed
    cont = ~isDone(videoFreader) && isOpen(depVideoPlayer); 
end

参考文献

1.Redmon, Joseph, and Ali Farhadi. "YOLOv3: An Incremental Improvement." Preprint, submitted April 8, 2018. https://arxiv.org/abs/1804.02767.