Main Content

車線検出と車両検出を実行する深層学習 Simulink モデルのコード生成

この例では、車線検出と車両検出を実行する Simulink® モデルから、畳み込みニューラル ネットワーク (CNN) を使用して CUDA® アプリケーションを開発する方法を説明します。この例では、交通量ビデオのフレームを入力として受け取り、自車の左右の車線に対応する 2 つの車線境界線を出力し、フレーム内の車両を検出します。この例では、GPU Coder Toolbox™ の"GPU Coder により最適化された車線検出" の例の事前学習済み車線検出ネットワークを使用します。詳細は、GPU Coder により最適化された車線検出を参照してください。この例では、Computer Vision Toolbox™ の"YOLO v2 深層学習を使用したオブジェクト検出" の例の事前学習済み車線検出ネットワークも使用します。詳細については、YOLO v2 深層学習を使用したオブジェクトの検出(计算机矢量绘图软件n Toolbox)を参照してください。

この例では以下の概念を説明します。

  • Simulink で車線検出アプリケーションをモデル化。最初に、交通量ビデオが、227 x 227 x 3 にサイズ変更され、定数係数の 255 が乗算されることによって前処理されます。次に、Deep Learning Toolbox™ のPredictブロックに読み込まれた事前学習済みのネットワークによって処理されます。最後に、左右の車線境界線が検出されると、車線境界線の軌跡をモデル化するための放物線係数が取得されます。

  • Simulink で車両検出アプリケーションをモデル化。交通量ビデオは、事前学習済みの YOLO v2 検出器で処理されます。このネットワークは、ビデオ内の車両を検出し、その車両の境界ボックスの座標と信頼スコアを出力します。

  • コード生成用にモデルを構成。

  • Simulink モデルの CUDA 実行可能ファイルの生成。

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

GPU 環境の検証

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

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

アルゴリズム ワークフロー

この Simulink モデルのアルゴリズム ワークフローのブロック線図を以下に示します。

事前学習済みの車線検出ネットワークおよび車両検出ネットワークの取得

この例では、trainedLaneNetと、事前学習済みのネットワークを含むyolov2ResNet50VehicleExampleの MAT ファイルを使用します。ファイルのサイズはそれぞれ、約 143 MB と約 98 MB です。MathWorks の Web サイトからファイルをダウンロードします。

lanenetFile = matlab.internal.examples.downloadSupportFile('gpucoder/cnn_models/lane_detection','trainedLaneNet.mat'); vehiclenetFile = matlab.internal.examples.downloadSupportFile('vision/data','yolov2ResNet50VehicleExample.mat');

テスト用の交通量ビデオのダウンロード

モデルをテストするために、この例では Caltech Lanes Dataset を使用しています。ファイルのサイズは約 16 MB です。MathWorks の Web サイトからファイルをダウンロードします。

mediaFile = matlab.internal.examples.downloadSupportFile('gpucoder/media','caltech_washington1.avi');

車線検出と車両検出の Simulink モデル

交通量ビデオで車線検出と車両検出を実行するための Simulink モデルを示します。このモデルを実行すると、Video Viewerブロックが、車線と車両に注釈を付けた状態で交通量ビデオを表示します。

open_system('laneAndVehicleDetection');

Simulink モデルの予測と検出器のブロックで、ダウンロードしたネットワーク モデルのファイル パスを設定します。Simulink モデルによって読み込まれるテスト ビデオの場所を設定します。

set_param('laneAndVehicleDetection/Lane Detection','NetworkFilePath',lanenetFile) set_param('laneAndVehicleDetection/Vehicle Detector','DetectorFilePath',vehiclenetFile) set_param('laneAndVehicleDetection/Traffic Video','inputFileName',mediaFile)

車線検出

Predictブロックは、trainedLaneNet.matファイルから事前学習済みの車線検出ネットワークを読み込みます。このネットワークは入力としてイメージを取り、自車の左右の車線に対応する 2 つの車線境界線を出力します。各車線境界線は、次の放物線方程式によって表されます。

$y = ax^2+bx+c$

ここで、y は横方向オフセット、x は車両からの縦方向の距離です。このネットワークは、車線ごとに 3 つのパラメーター a、b、c を出力します。ネットワーク アーキテクチャはAlexNetに似ていますが、最後の数層は、規模の小さい全結合層と回帰出力層に置き換えられています。MATLAB Function ブロックLaneDetectionCoordinatesは、関数lane_detection_coordinatesを定義します。この関数は、予測ブロックからの出力を受け取り、laneFoundltPtsrtPtsという 3 つのパラメーターを出力します。しきい値処理は、左右の車線境界線が両方とも検出できるかどうかを判断するために使用されます。両方とも検出できれば、laneFoundは true に設定され、境界線の軌跡が計算されて、ltPtsrtPtsにそれぞれ格納されます。

typelane_detection_coordinates
function [laneFound,ltPts,rtPts] = lane_detection_coordinates(laneNetOut) % Copyright 2020-2021 The MathWorks, Inc. persistent laneCoeffMeans; if isempty(laneCoeffMeans) laneCoeffMeans = [-0.0002,0.0002,1.4740,-0.0002,0.0045,-1.3787]; end persistent laneCoeffStds; if isempty(laneCoeffStds) laneCoeffStds = [0.0030,0.0766,0.6313,0.0026,0.0736,0.9846]; end params = laneNetOut .* laneCoeffStds + laneCoeffMeans; % 'c' should be more than 0.5 for it to be a right lane isRightLaneFound = abs(params(6)) > 0.5; isLeftLaneFound = abs(params(3)) > 0.5; persistent vehicleXPoints; if isempty(vehicleXPoints) vehicleXPoints = 3:30; %meters, ahead of the sensor end ltPts = coder.nullcopy(zeros(28,2,'single')); rtPts = coder.nullcopy(zeros(28,2,'single')); if isRightLaneFound && isLeftLaneFound rtBoundary = params(4:6); rt_y = computeBoundaryModel(rtBoundary, vehicleXPoints); ltBoundary = params(1:3); lt_y = computeBoundaryModel(ltBoundary, vehicleXPoints); % Visualize lane boundaries of the ego vehicle tform = get_tformToImage; % Map vehicle to image coordinates ltPts = tform.transformPointsInverse([vehicleXPoints', lt_y']); rtPts = tform.transformPointsInverse([vehicleXPoints', rt_y']); laneFound = true; else laneFound = false; end end

車両検出

YOLO v2 オブジェクトの検出ネットワークは、特徴抽出ネットワークと、その後に続く検出ネットワークという、2 つのサブネットワークで構成されます。事前学習済みのネットワークは、特徴抽出にResNet-50を使用します。検出サブネットワークは特徴抽出ネットワークと比べて小さい CNN であり、少数の畳み込み層と YOLO v2 に固有の層で構成されます。Simulink モデルは、Computer Vision Toolbox™ の对象探测器ブロックを使用して車両検出を実行します。このブロックは、イメージを入力として受け取り、境界ボックス座標をイメージ内の車両の信頼度スコアと共に出力します。

車両境界ボックスの注釈と交通量ビデオの車線軌跡

LaneVehicleAnnotationMATLAB Function ブロックは、関数lane_vehicle_annotationを定義します。この関数は、車両境界ボックスに対して信頼度スコアとともに注釈を付けます。また、laneFoundが true の場合は、ltPtsrtPtsに格納された左右の車線境界線に交通量ビデオ内で注釈が付けられます。

typelane_vehicle_annotation
function In = lane_vehicle_annotation(laneFound,ltPts,rtPts,bboxes,scores,In) % Copyright 2020-2021 The MathWorks, Inc. if ~isempty(bboxes) In = insertObjectAnnotation(In, 'rectangle',bboxes,scores); end pts = coder.nullcopy(zeros(28, 4, 'single')); if laneFound prevpt = [ltPts(1,1) ltPts(1,2)]; for k = 2:1:28 pts(k,1:4) = [prevpt ltPts(k,1) ltPts(k,2)]; prevpt = [ltPts(k,1) ltPts(k,2)]; end In = insertShape(In, 'Line', pts, 'LineWidth', 2); prevpt = [rtPts(1,1) rtPts(1,2)]; for k = 2:1:28 pts(k,1:4) = [prevpt rtPts(k,1) rtPts(k,2)]; prevpt = [rtPts(k,1) rtPts(k,2)]; end In = insertShape(In, 'Line', pts, 'LineWidth', 2); In = insertMarker(In, ltPts); In = insertMarker(In, rtPts); end end

シミュレーションの実行

[コンフィギュレーション パラメーター] ダイアログ ボックスを開きます。

[シミュレーション ターゲット]ペインで[GPU による高速化]を選択します。[深層学習]グループで、ターゲット ライブラリとして[cuDNN]を選択します。

set_param(bdroot,'GPUAcceleration','on'); set_param(bdroot,'SimDLTargetLibrary','cudnn'); set_param(bdroot,'DLTargetLibrary','cudnn');

車線検出アルゴリズムおよび車両検出アルゴリズムを検証し、Simulink モデルに読み込まれた交通量ビデオに関する車線軌跡、車両境界ボックス、スコアを表示するため、シミュレーションを実行します。

set_param('laneAndVehicleDetection',“SimulationMode”,'Normal'); sim('laneAndVehicleDetection');

Simulink モデルの生成とビルド

[コード生成]ペインで[言語]として[C++]を選択し、[GPU コードの生成]を有効にします。

set_param(bdroot,'TargetLang','C++'); set_param(bdroot,'GenerateGPUCode','CUDA');

[コード生成]、[GPU コード]ペインのサブカテゴリ[ライブラリ]で、[cuBLAS][cuSOLVER]、および[cuFFT]を有効にします。

set_param(bdroot,'GPUcuBLAS','on'); set_param(bdroot,'GPUcuSOLVER','on'); set_param(bdroot,'GPUcuFFT','on');

slbuildコマンドを使用して、ホスト GPU で Simulink モデルを生成してビルドします。コード ジェネレーターは実行可能ファイルを "ビルド フォルダー"(現在の作業フォルダーの中のlaneAndVehicleDetection_ert_rtwという名前のサブフォルダー) に配置します。

status = evalc(“slbuild (laneAndVehicleDetection)”);

生成された CUDA コード

laneAndVehicleDetection_ert_rtwという名前のサブフォルダーには、Simulink モデルの各種ブロックに対応して生成された C++ コードと、これらのブロックで実行される特定の演算が含まれています。たとえばtrainedLaneNet0_laneAndVehicleDetection0.hファイルには、事前学習済みの車線検出ネットワークを表す、属性とメンバー関数を含む C++ クラスが含まれています。

同様に、yolov2ResNet50VehicleExample0_laneAndVehicleDetection0.hファイルには、事前学習済みの YOLO v2 検出ネットワークを表す C++ クラスが含まれています。

参考

関数

関連するトピック