はじめに
AMBL株式会社 AI開発事業部の見原です。
この記事は、AMBL株式会社 Advent Calendar 2022の19日目の記事になります。
業務では画像系のエッジAIアプリの開発を行っています。
この記事では、Jetsonにyolov7-tinyを組込んでDeepStream上でリアルタイムに物体検出を行う方法を紹介します。参考になれば幸いです。
目的
yolov7をJetsonのDeepStream上で動かせるようにする。サンプルアプリdeepstream-appを使ってyolov7で推論を行う。
環境
- Jetson Nano 4GB
- Jetpack 4.5
- DeepStream SDK 5.1
Jetsonとは?
- NVIDIAが開発した小型コンピュータ
- NVIDIAのGPUが搭載されている
DeepStreamとは?
- GStreamerをベースにしたストリーム分析ツールキット
- AIを使ったビデオ解析、音声分析、画像分析のためのパイプラインを構築できる
- C/C++またはPythonで開発できる(Graph ComposerというUIを使った開発もできるらしい)
組込み
組込み手順
- モデルのTensorRT化: モデルをDeepStreamで使える形式に変換する。デバイスに合わせてモデルを高速化する。
- コンフィグファイルの作成: 前処理の設定などを行う。
- パーサー作成: 後処理(NMS処理など)を行うファイルを作成する。
- サンプルアプリ実行
1. モデルのTensorRT化
.pt -> .wts -> .engineの順に変換する。
.wtsファイルまではgoogle colabで変換し、.engineファイルへの変換はJetsonで行う。
以下のgithubを参考に行う。
https://github.com/wang-xinyu/tensorrtx/tree/master/yolov7
.ptファイルの変換
まず必要なリポジトリをクローンする。
!git clone https://github.com/WongKinYiu/yolov7
!git clone https://github.com/wang-xinyu/tensorrtx.git -b yolov5-v6.2
以下のリンクから事前学習済みモデルyolov7-tiny.ptをダウンロードし、yolov7フォルダに保存する。
https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt
gen_wts.pyファイルをyolov7下にコピーする。
!cp tensorrtx/yolov7/gen_wts.py yolov7
以下のように変換前の.ptファイルと変換後の.wtsファイルを指定して実行する。
%cd yolov7
!python3 gen_wts.py -w yolov7-tiny.pt -o yolov7-tiny.wts
yolov7下にyolov7-tiny.wtsが生成する。
.wtsファイルの変換
Jetsonで行う。
以下のリポジトリをダウンロードし、yolov7フォルダをホームディレクトリにコピーする。
https://github.com/mihara-shoko/yolov7_tensorrt
buildフォルダを作成し、yolov7-tiny.wtsファイルをbuildフォルダにコピーする。
yololayer.hの"static constexpr int INPUT_H"と"static constexpr int INPUT_W"を416に変更する。
static constexpr int CHECK_COUNT = 3;
static constexpr float IGNORE_THRESH = 0.5f;
struct YoloKernel
{
int width;
int height;
float anchors[CHECK_COUNT * 2];
};
static constexpr int MAX_OUTPUT_BBOX_COUNT = 1000;
static constexpr int CLASS_NUM = 80;
static constexpr int INPUT_H = 416; // <-変更
static constexpr int INPUT_W = 416; // <-変更
buildフォルダに移動し、以下を実行する。
cmake ..
make
sudo ./yolov7 -s yolov7-tiny.wts yolov7-tiny.engine t
buildフォルダにyolov7-tiny.engineが生成する。これがTensorRT化されたモデル。
2. コンフィグファイルの作成
前処理、モデルファイル、信頼度の閾値、クラス数の設定などを行う。
以下のリポジトリをダウンロードし、parserフォルダをJetsonの/opt/nvidia/deepstream/deepstream-5.1/sources/ディレクトリにコピーする。
https://github.com/mihara-shoko/yolo_parser
「1. モデルのTensorRT化」で作成したyolov7-tiny.engineファイルを/opt/nvidia/deepstream/deepstream-5.1/sources/parser下にコピーする。
/opt/nvidia/deepstream/deepstream-5.1/sources/parser下にあるconfig_infer_primary.txtを必要に応じて修正する。
[property]
gpu-id=0
net-scale-factor=0.0039215697906911373
model-color-format=0
model-engine-file=yolov7-tiny.engine # TensorRT化したモデルのパス
labelfile-path=labels.txt # ラベルが書かれたテキストファイルのパス
num-detected-classes=80 # クラス数
interval=0
gie-unique-id=1
process-mode=1
network-type=0
cluster-mode=4
maintain-aspect-ratio=1
parse-bbox-func-name=NvDsInferParseCustomYoloV5
custom-lib-path=nvdsinfer_custom_impl_Yolo/libnvdsinfer_custom_impl_Yolo.so
[class-attrs-all]
pre-cluster-threshold=0.25 # 信頼度の閾値
前処理に関係する項目
項目 | 説明 | yolov7の場合の設定値 |
---|---|---|
net-scale-factor | ピクセル値にかける値 モデルにはyのピクセル値が入力される。 y = net scale factor*(x-offset) |
0.0039215697906911373 0-255を0-1のrangeにしている |
offset | ピクセル値から引く値 RGBそれぞれ別に設定できる。 モデルにはyのピクセル値が入力される。 y = net scale factor*(x-offset) |
0:0:0 設定しなくて良い |
model-color-format | 0:RGB 1:BGR 2:GRAY |
0 |
maintain-aspect-ratio | リサイズするときにアスペクト比を維持するかどうか | 1 |
詳しくはNVIDIAのページを参照
https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_plugin_gst-nvinfer.html
3. パーサー作成
後処理(NMS処理など)を行うファイルを作成する。
Jetsonの/opt/nvidia/deepstream/deepstream-5.1/sources/parserに移動する。
nvdsinfer_custom_impl_Yolo/yololayer.hのクラス数(19行目)、input size(20, 21行目)を適宜変更する(TensorRT化したときと同じ値にする)。
#ifndef _YOLO_LAYER_H
#define _YOLO_LAYER_H
#include <vector>
#include <string>
#include "NvInfer.h"
namespace Yolo
{
static constexpr int CHECK_COUNT = 3;
static constexpr float IGNORE_THRESH = 0.1f;
struct YoloKernel
{
int width;
int height;
float anchors[CHECK_COUNT * 2];
};
static constexpr int MAX_OUTPUT_BBOX_COUNT = 1000;
static constexpr int CLASS_NUM = 1;
static constexpr int INPUT_H = 416; // yolov5's input height and width must be divisible by 32.
static constexpr int INPUT_W = 416;
以下のコマンドでコンパイルする。
CUDA_VER=10.2 make -C nvdsinfer_custom_imple_Yolo
nvdsinfer_custom_impl_Yolo下に生成した.soファイルがパーサーとなる。
4. アプリ実行
Jetsonの/opt/nvidia/deepstream/deepstream-5.1/sources/parserに移動する。
deepstream_app_config.txtのuriに読み込ませたい動画のパスを設定する。
[source0]
enable=1
type=3
uri=file://../../samples/streams/sample_1080p_h264.mp4
num-sources=1
gpu-id=0
cudadec-memtype=0
以下のコマンドを実行し、アプリを実行する。
deepstream-app -c deepstream_app_config.txt
アプリ実行結果
35 FPSでリアルタイムに推論をかけることができた!
おわりに
この記事では、Jetsonにyolov7-tinyを組込んでリアルタイムに物体検出を行う方法を紹介しました。無事にDeepstreamのパイプライン上で動かすことができました。yolov5sよりもアプリ実行速度が速い(同じ条件で実行するとyolov5sの場合は30 FPS未満)ので、リアルタイムに推論をかけたい場合はおすすめです。組込みの手法は何通りかあると思うので、別の方法を知っている方いましたら教えていただきたいです!