やってみた!

やってみた!

試したことを中心に、書評や興味のあること、思ったこととか

Jetson NanoでDeepStreamを使ってYOLOv3-tinyを動かす

Rev1 2019/10/14

 YOLOv3-tinyのmaskはNVIDIAのYOLOプラグインのファイルnvdsparsebbox_Yolo.cpp中で修正されていましたので、関連する箇所を書き直しました。

ーーーーーーーーーーーーーーーーーーーーーーーーー

 YOLO(You Only Look Once)はdarknet(C言語で書かれたディープラーニングライブラリ)で開発された画像認識ディープラーニングネットワークで、1回ネットワークを通して、ちょっと後処理しただけで複数の対象物のクラス(種別)と位置を検出するという優れものです。

 YOLOの縮小セット版(tiny)はJetson Nanoでリアルタイムで動きます。

 NVIDIAは動画に対する各種処理を容易に構築できるよう、DeepStreem SDKと呼ばれる開発キットを提供しており、YOLOにも正式に対応しています。またDeepStreem SDKの最新のバージョンではJetson Nanoにも正式に対応しています。

developer.nvidia.com

 DeepStreamを使って最新版YOLO3の縮小セット版(tiny)をJetson Nanoで動かしてみます。

 NGC(NVIDIA GPU Cloud)Containerを使う予定でしたが、JetPackのContainer対応はベータ版ということで、buildはセットアップされていない、video encode,CSI camera(raspiカメラのことですね)には対応していないとのこと。YOLOを動かすにはコンパイルする必要があり、tensorRT等の環境を整備しないと無理だったので、Containerはあきらめ通常の方法でやりました。

1.高速化設定

 USBからJetson Nanoに電源を供給している場合は次の設定は使えません。設定すると最悪の場合電力不足で起動しなくなります。

    sudo nvpmodel -m 0                :CPUコア2→4
    sudo jetson_clocks                  :クロックアップ

2.DeepStream SDKのインストール

 DeepStream SDKの通常の手順に従います。

  • 関連パッケージのインストール
sudo apt install \
libssl1.0.0 \
libgstreamer1.0-0 \
gstreamer1.0-tools \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
libgstrtspserver-1.0-0 \
libjansson4=2.11-1
  • librdkafkaのインストール
    sudo apt-get install librdkafka1=0.11.3-1build1
  • DeepStream SDKのインストール
    Debian packageでインストールしました。下のホームページからJetson用のxx.debをダウンロードします。NVIDIAにユーザ登録する必要があります。         DeepStream SDK 4.0.1 | NVIDIA Developer

    ファイルをダウンロードフォルダからHomeへドラッグ&ドロップで移動させます。

        cd ~     Homeディレクトリに移動(カレントディレクトリがHomeなら必要なし)
        sudo apt-get install ./deepstream-4.0_4.0.1-1_arm64.deb

3.DeepStreamのサンプルを動かす

DeepstreamのConfigファイル(DeepStreamの設定ファイル)は、
/opt/nvidia/deepstream/deepstream-4.0/samples/configs/deepstream-app
にあります。

 Configファイルは十数個ありますが、JetsonNanoでそのまま動くのはたぶんひとつです。次の例は映像が出るまで数分かかりますが、動き始めるとリアルタイムで動きます。

cd /opt/nvidia/deepstream/deepstream-4.0/samples
deepstream-app -c configs/deepstream-app/source8_1080p_dec_infer-resnet_tracker_tiled_display_fp16_nano.txt

f:id:akifukka:20191012220610j:plain

4.YOLOv3-tinyの準備

 YOLO関係のサンプルは以下のフォルダにあります。
/opt/nvidia/deepstream/deepstream-4.0/sources/objectDetector_Yolo

 今、samplesにいるはずなので、ディレクトリを移動します。
cd ../sources/objectDetector_Yolo

 ここのフォルダにあるREADMEの通りに作業します。

  • YOLOのcfgファイル(ネットワーク構造等を定義しているもの)、weight(ネットワークの係数)を次のコマンド(スクリプト)で一括ダウンロードします。

         ./prebuild.sh

  • Jetson NanoにインストールされているCUDAのバージョンを環境変数として設定します。

         nvcc -V

 表示されたバージョンを確認して次の通り設定します。間違うとコンパイルでエラーになります。

         export CUDA_VER=10.0

         make -C nvdsinfer_custom_impl_Yolo

5.YOLOv3-tinyのサンプルを動かす

   次のコマンドでサンプルが動きます。動き始めるまでは少し時間がかかります。

     deepstream-app -c deepstream_app_config_yoloV3_tiny.txt

  Jetson Nano高速設定で22FPSくらい、nvpmodel を下げて17FPSでした。認識率がいまいちな気がします。

f:id:akifukka:20191013110440j:plain

 下はYOLOv2-tinyです。Jetson Nano高速設定で25FPSくらいでした。認識率は良好です。

     deepstream-app -c deepstream_app_config_yoloV2_tiny.txt

f:id:akifukka:20191013105758j:plain

 READMEを読むとYOLOv3-tinyはYOLOのcfgのmaskを修正した(間違っていたのを正しく直した)が、古いcfgで学習したweightしかないとのこと。

 ファイルnvdsparsebbox_Yolo.cpp中の関数NvDsInferParseCustomYoloV3Tinyで、正しくはmask=0,1,2なのですが、学習済みのweightにあわせて1,2,3に戻しています。

extern "C" bool NvDsInferParseCustomYoloV3Tiny(
std::vector<NvDsInferLayerInfo> const& outputLayersInfo,
NvDsInferNetworkInfo const& networkInfo,
NvDsInferParseDetectionParams const& detectionParams,
std::vector<NvDsInferParseObjectInfo>& objectList)
{
static const std::vector<float> kANCHORS = {
10, 14, 23, 27, 37, 58, 81, 82, 135, 169, 344, 319};
static const std::vector<std::vector<int>> kMASKS = {
{3, 4, 5},
//{0, 1, 2}}; // as per output result, select {1,2,3}
{1, 2, 3}}; return NvDsInferParseYoloV3 (
outputLayersInfo, networkInfo, detectionParams, objectList,
kANCHORS, kMASKS);
}

 なお、このNvDsInferParseCustomYoloV3Tinyは、config_infer_primary_yoloV3_tiny.txt中でparse-bbox-funcとして次の通り設定されています。

 parse-bbox-func-name=NvDsInferParseCustomYoloV3Tiny

 parse-bbox-func-nameについてはDeepStream Development GuideのApplication Customizationの項を参照してください。

 DeepStream 4.0.1

 個人的にはyolo2-tinyの方が認識の反応が良さそうな気がします。yolo2-tinyを動かすにはこちらのコマンドで。

     deepstream-app -c deepstream_app_config_yoloV2_tiny.txt

6.USB Cameraを接続する

 Cameraをつなぎます。手持ちのBuffaloのBSWHD06Mを使いました。

  BSWHD06MBK : Webカメラ | バッファロー

  • DeepStreamのConfigファイルをUSB Camera用に編集するためコピーします。
cp deepstream_app_config_yoloV3_tiny.txt deepstream_app_config_yoloV3_tiny_usb_camera.txt
  • deepstream_app_config_yoloV3_tiny_usb_camera.txtの[source0]を次の通り書き換えます。赤が変更箇所です。

 [source0]
enable=1
#Type - 1=CameraV4L2 2=URI 3=MultiURI
type=1
camera-width=640
camera-height=480
camera-fps-n=30
camera-fps-d=1
camera-v4l2-dev-node=0
#uri=file://../../samples/streams/sample_1080p_h264.mp4
#num-sources=1
#gpu-id=0
# (0): memtype_device - Memory type Device
# (1): memtype_pinned - Memory type Host Pinned
# (2): memtype_unified - Memory type Unified
#cudadec-memtype=0

ーーーーーーーーーーーーー

詳細はDeepStream Development Guideのリンク(参考)

DeepStream Development Guide
   - Reference Application Configuration
      - Configuration Groups
         - Source Group

  •  USB CameraでYOLOv3-tinyを動かします。
    deepstream-app -c deepstream_app_config_yoloV3_tiny_usb_camera.txt

 ちなみに下の写真はyoloV2-tinyです。V3と同じようにdeepstream_app_config_yoloV2_tiny.txtをコピー、修正すればUSB Cameraで動きます。

 f:id:akifukka:20191013123752j:plain

7.YOLOv3-tinyについて

pjreddie.com

論文へのリンク

https://pjreddie.com/media/files/papers/YOLOv3.pdf

  YOLOv3-tinyのネットワーク構造はyolov3-tiny.cfgで定義されています。図にしてみました。入力は416×416x3(R,G,Bの3原色)の画像データで、YOLOv3-tinyのネットワークは画像を13x13に分割したものと、26x26に分割したものを出力します。

f:id:akifukka:20191013223709j:plain

f:id:akifukka:20191013223723j:plain

 ネットワークは13x13、26x26の各区画に対し255個のデータを出力します。データにはターゲットとする対象物の大きさ(3種類)ごとの、Boundingboxの大きさ、中心位置、認識種別(80種)ごとの判定値の組が含まれます。ネットワーク計算後にこれらのデータを評価、適切なものを抽出、最終的に妥当性を評価してBoundingboxの大きさ、中心位置を出力します。

8.まとめ

  • DeepStreamを使ってJetson NanoでYOLOを動かしてみました。
  • YOLOの概要をまとめました。

おしまい

Jetson Nano カテゴリーの記事一覧へ