VVASのチュートリアルを動かしてみる
はじめに
今回はXilinxで提供されているVitis ビデオ解析SDK(VVAS)
について見ていきたいと思います。VVASはビデオ分析アプリケーションやサービスを構築および運用するために設計された環境で、ビデオエンコーダ・デコーダや前処理、深層学習、後処理などの処理をGstreamerを使って処理できるようです。今回はこれのチュートリアルについて試していこうと思います。
構築済みイメージをSDカードに書き込む
VVASのチュートリアルのページを参考にMultichannel ML
のデモを試していきます。
まずはじめにXilinxのサイトからMultichannel ML
構築済みイメージをダウンロードします。
vvas_multichannel_ml_2021.1_zcu104.zip
というファイルがダウンロードされます。
ファイルを展開すると以下のファイルが含まれている事が確認できます。
ファイル | 内容 |
---|---|
sd_card.img | OSイメージファイル |
sdk.sh | sysroot生成に使う(今回は不要) |
models | DPUモデル |
app | アプリケーションとJSONファイル |
arch.json | DPUアーキテクチャ |
※DPUはDeep Learning Processor Unitの略称
sd_card.img
をSDカードに書き込むため、以下のサイトからEtcher
をダウンロードします。
ダウンロードしたEtcherを起動し、sd_card.img
をSDカードに書き込みます。
チュートリアルの内容とデバイス構成
今回のチュートリアルは、H.264ファイルを入力ソースとして、そのファイルをデコードしてNV12フォーマットにします。その後にAI処理を適用し顔検出した部分にバウンディングボックスをオーバーレイしてHDMIモニタに出力するという内容になります。
チュートリアルを実行するデバイス構成は以下の通りとなります。
WindowsPCからZCU104へはTeraTermで接続します。BAUDレートは115200(bps)
を設定します。
ごちゃっとしていますが、写真でみると以下のようになります。
チュートリアルの準備
上の構成が準備できたらZCU104を起動します。
起動後、以下のコマンドを実行してルートファイルシステムパーティションを100%のサイズに拡張します。またWindowsPCと通信できるようにIPアドレスも変更します。
(ここではWindows側は192.168.0.15にしています。)
resize-part /dev/mmcblk0p2
ifconfig eth0 192.168.0.20
次にチュートリアルで使用するH.264の動画ファイルをZCU104に転送します。
動画ファイルが手元に無い場合は、IPHONEなどで自分の顔を撮影したデータを使用すると良いです。WindowPC上でCMDプロンプトを起動し、MOVファイルのあるディレクトリから以下のコマンドを実行して転送します。(scpのパスワードはroot
を指定します。)
scp file.mov root@192.168.0.20:~
AIのモデルjsonファイルとスクリプトもZCU104に転送します。フォルダ毎コピーするので-r
オプションを指定してscp
を実行します。
scp -r vvas_multichannel_ml_2021.1_zcu104/utils root@192.168.0.20:~
ボード用AIモデルファイルをコピーします。
scp -r vvas_multichannel_ml_2021.1_zcu104/vai_models/* root@192.168.0.20:/usr/share/vitis_ai_library/models/
チュートリアルアプリケーションの実行
ここからチュートリアルを実行していきます。
ステップ1
ここではH.264ファイルをデコードしてNV12形式のRAWデータに保存する処理を実行します。
FileSrc
とFileSink
についてはGstreamerのOpenソースプラグインを使用します。
VCUDecについてはFPGAに統合されたVCU
を動かすためのプラグインを使用します。
TeraTermから、以下のGstreamerのパイプラインを実行します。
gst-launch-1.0 filesrc location=/home/root/videos/test.mov ! qtdemux ! h264parse ! omxh264dec internal-entropy-buffers=3 ! filesink location=./vcu_out.nv12 -v
処理が完了するとvcu_out.nv12
ファイルが出力されます。
これをWindowsPCに転送します。
scp root@192.168.0.20:/home/root/videos/vcu_out.nv12 vcu_out.nv12
ファイルをWindows側にコピーしたら、NV12フォーマットに対応したRAWビューワーソフト(オープンソース版が沢山あるので探してみてください)をインストールし、ファイルを再生してみます。
正しくH.264をデコードできているようです。
ステップ2
続いてSTEP2に対し、顔検出の前処理となるサイズ変更
とフォーマット変換
を追加します。
前処理プラグインにはivas_xabrscaler
を使用します。
ivas_xabrscaler
は、1つの入力フレームを受け取り、異なる解像度とカラーフォーマットを持つ複数の出力フレームを生成する機能を持つプラグインで、実処理についてはFPGAアクセラレーションで実行されます。
TeraTermから、以下のGstreamerのパイプラインを実行します。
gst-launch-1.0 -v \
filesrc location=/home/root/videos/test.mov ! qtdemux ! h264parse ! omxh264dec internal-entropy-buffers=3 ! \
ivas_xabrscaler xclbin-location=/media/sd-mmcblk0p1/dpu.xclbin kernel-name=v_multi_scaler:v_multi_scaler_1 ! \
"video/x-raw, width=320, height=320, format=RGB" ! filesink location=./pre_proc.bgr
処理が完了するとpre_proc.bgr
ファイルが出力されます。
これをWindowsPCに転送します。
scp root@192.168.0.20:/home/root/videos/pre_proc.bgr pre_proc.bgr
ファイルをWindows側にコピーしたら、RGBフォーマットに対応したRAWビューワーソフトでファイルを再生してみます。今回も正しく処理できているようです。
ステップ3
次に、STEP2に対してAIによる顔検出を実行します。
機械学習のプラグインにはivas_xfilter
を使用します。
ivas_xfilter
もivas_xabrscaler同様にFPGAアクセラレーションを実行するためのプラグインとなりますが、JSONファイルでより細かい動作設定ができるみたいです。
こちらについては、おいおい細かく調べていきたいと思います。
TeraTermから、以下のGstreamerのパイプラインを実行します。
gst-launch-1.0 -v \
filesrc location=/home/root/videos/test.mov ! qtdemux ! h264parse ! omxh264dec internal-entropy-buffers=3 ! \
ivas_xabrscaler xclbin-location=/media/sd-mmcblk0p1/dpu.xclbin kernel-name=v_multi_scaler:v_multi_scaler_1 alpha_r=128 alpha_g=128 alpha_b=128 ! \
ivas_xfilter kernels-config="/home/root/utils/jsons/dpu/kernel_densebox_320_320.json" ! fakesink
ival_xfilter
で指定するjsonファイル
の中身は以下になっています。
ここでAIモデルなどを指定するようです。
{
"xclbin-location":"/media/sd-mmcblk0p1/dpu.xclbin",
"ivas-library-repo": "/usr/lib/",
"element-mode":"inplace",
"kernels" :[
{
"library-name":"libivas_xdpuinfer.so",
"config": {
"model-name" : "densebox_320_320",
"model-class" : "FACEDETECT",
"model-format" : "BGR",
"model-path" : "/usr/share/vitis_ai_library/models/",
"run_time_model" : false,
"need_preprocess" : false,
"performance_test" : false,
"debug_level" : 1
}
}
]
}
jsonファイルのdebug_levelを4
に設定してGstreamerのパイプラインを実行すると、オブジェクト検出ログが出力されます。INFO RESULT
に顔検出領域が表示されていることが分かります。
[ivas_xfacedetect.cpp run:91] INFO:
[ivas_xdpuinfer.cpp xlnx_kernel_done:872] DEBUG: enter
[ivas_xdpuinfer.cpp xlnx_kernel_start:746] DEBUG: enter
[ivas_xdpuinfer.cpp xlnx_kernel_start:807] DEBUG: ivas_mata ptr 0xffff6c003cd0
[ivas_xfacedetect.cpp requiredwidth:100] DEBUG: enter
[ivas_xfacedetect.cpp requiredheight:107] DEBUG: enter
[ivas_xdpuinfer.cpp xlnx_kernel_start:831] DEBUG: model required wxh is 320x320
[ivas_xdpuinfer.cpp xlnx_kernel_start:833] DEBUG: input image wxh is 320x320
[ivas_xdpuinfer.cpp ivas_xrunmodel:539] DEBUG: enter
[ivas_xfacedetect.cpp run:32] DEBUG: enter
[ivas_xfacedetect.cpp run:47] DEBUG: IN width 320, height 320 infer ptr 0xffff6c003cd0
[ivas_xfacedetect.cpp run:49] DEBUG: root prediction ptr 0xffff74d58830
[ivas_xfacedetect.cpp run:84] INFO: RESULT: 130.000000 93.000000 224.000000 201.000000 (0.949262)
[ivas_xfacedetect.cpp run:88] DEBUG: prediction tree :
ステップ4
次に、STEP3に対しMETA情報(付加情報)をアタッチする機能とモニタ出力する機能を追加します。ステップ3で検出した顔検出領域をMETA情報として後段処理に渡しているようです。
TeraTermから、以下のGstreamerのパイプラインを実行します。
gst-launch-1.0 -v \
filesrc location=/home/root/videos/test.mov ! qtdemux ! h264parse ! omxh264dec internal-entropy-buffers=3 ! \
tee name=t0 \
t0.src_0 ! queue ! \
ivas_xabrscaler xclbin-location=/media/sd-mmcblk0p1/dpu.xclbin kernel-name=v_multi_scaler:v_multi_scaler_1 alpha_r=128 alpha_g=128 alpha_b=128 ! \
ivas_xfilter kernels-config="/home/root/utils/jsons/dpu/kernel_densebox_320_320.json" ! \
scalem0.sink_master ivas_xmetaaffixer name=scalem0 scalem0.src_master ! fakesink \
t0.src_1 ! queue ! \
scalem0.sink_slave_0 scalem0.src_slave_0 ! queue ! \
kmssink plane-id=34 bus-id="a0130000.v_mix" render-rectangle="<0,0,1920,1080>"
無事、HDMIディスプレイに動画が表示されることが確認できました。
補足で、HDMIのbus-id
はボード起動時にTeraTerm上の起動ログに表示されるので、表示がうまくいかない場合はここを確認すると良いです。
[ 7.684345] xilinx-vphy a0140000.vid_phy_controller: probe successful
[ 7.716587] xlnx-drm-hdmi a0100000.v_hdmi_tx_ss: probe started
[ 7.722540] xlnx-drm-hdmi a0100000.v_hdmi_tx_ss: hdmi tx audio disabled in DT
[ 7.751613] xlnx-drm-hdmi a0100000.v_hdmi_tx_ss: probe successful
[ 7.767525] xlnx-mixer a0130000.v_mix: disp bridge property not present
[ 7.774425] xlnx-mixer a0130000.v_mix: Registered mixer CRTC with id: 44
[ 7.781170] xlnx-drm xlnx-drm.1: bound a0130000.v_mix (ops 0xffff80001107e3c8
ステップ5
最後のステップとなります。STEP4に対し検出した顔を枠で囲むバウンディングボックス機能を追加します。
バウンディングボックス機能を実現するためには、VVASで提供されているivas_xboundingbox
プラグインを使用します。ivas_xboundingbox
はOpenCVをアクセラレーションするプラグインで、これもJSONファイルで動作設定ができます。
JSONファイルの内容は以下となります。
{
"xclbin-location":"/media/sd-mmcblk0p1/dpu.xclbin",
"ivas-library-repo": "/usr/lib/",
"element-mode":"inplace",
"kernels" :[
{
"library-name":"libivas_xboundingbox.so",
"config": {
"model-name" : "densebox_320_320",
"display_output" : 1,
"font_size" : 0.5,
"font" : 3,
"thickness" : 3,
"debug_level" : 1,
"label_color" : { "blue" : 0, "green" : 0, "red" : 0 },
"label_filter" : [ "class", "probability" ],
"classes" : [
]
}
}
]
}
それでは、Gstreamerのパイプラインを実行してみます。
gst-launch-1.0 -v \
filesrc location=/home/root/videos/test.mp4 ! qtdemux ! h264parse ! omxh264dec internal-entropy-buffers=3 ! \
tee name=t0 \
t0.src_0 ! queue ! \
ivas_xabrscaler xclbin-location=/media/sd-mmcblk0p1/dpu.xclbin kernel-name=v_multi_scaler:v_multi_scaler_1 alpha_r=128 alpha_g=128 alpha_b=128 ! \
ivas_xfilter kernels-config="/home/root/utils/jsons/dpu/kernel_densebox_320_320.json" ! \
scalem0.sink_master ivas_xmetaaffixer name=scalem0 scalem0.src_master ! fakesink \
t0.src_1 ! queue ! \
scalem0.sink_slave_0 scalem0.src_slave_0 ! queue ! \
ivas_xfilter kernels-config="/home/root/utils/jsons/bbox/kernel_boundingbox_facedetect.json" ! \
kmssink plane-id=34 bus-id="a0130000.v_mix" render-rectangle="<0,0,1920,1080>"
無事に、HDMIモニターに顔検出した部分にバウンディングボックスが表示されることが確認できました。
次はVVASのプラットフォームについて見ていきたいと思います。
Discussion