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にも正式に対応しています。
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
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
- YOLOのPluginをコンパイルします。
make -C nvdsinfer_custom_impl_Yolo
5.YOLOv3-tinyのサンプルを動かす
次のコマンドでサンプルが動きます。動き始めるまでは少し時間がかかります。
deepstream-app -c deepstream_app_config_yoloV3_tiny.txt
Jetson Nano高速設定で22FPSくらい、nvpmodel を下げて17FPSでした。認識率がいまいちな気がします。
下はYOLOv2-tinyです。Jetson Nano高速設定で25FPSくらいでした。認識率は良好です。
deepstream-app -c deepstream_app_config_yoloV2_tiny.txt
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の項を参照してください。
個人的にはyolo2-tinyの方が認識の反応が良さそうな気がします。yolo2-tinyを動かすにはこちらのコマンドで。
deepstream-app -c deepstream_app_config_yoloV2_tiny.txt
6.USB Cameraを接続する
Cameraをつなぎます。手持ちのBuffaloのBSWHD06Mを使いました。
- 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で動きます。
7.YOLOv3-tinyについて
論文へのリンク
https://pjreddie.com/media/files/papers/YOLOv3.pdf
YOLOv3-tinyのネットワーク構造はyolov3-tiny.cfgで定義されています。図にしてみました。入力は416×416x3(R,G,Bの3原色)の画像データで、YOLOv3-tinyのネットワークは画像を13x13に分割したものと、26x26に分割したものを出力します。
ネットワークは13x13、26x26の各区画に対し255個のデータを出力します。データにはターゲットとする対象物の大きさ(3種類)ごとの、Boundingboxの大きさ、中心位置、認識種別(80種)ごとの判定値の組が含まれます。ネットワーク計算後にこれらのデータを評価、適切なものを抽出、最終的に妥当性を評価してBoundingboxの大きさ、中心位置を出力します。
8.まとめ
- DeepStreamを使ってJetson NanoでYOLOを動かしてみました。
- YOLOの概要をまとめました。
おしまい