🐟

VVASのチュートリアルを動かしてみる

2022/02/10に公開

はじめに

今回はXilinxで提供されているVitis ビデオ解析SDK(VVAS)について見ていきたいと思います。VVASはビデオ分析アプリケーションやサービスを構築および運用するために設計された環境で、ビデオエンコーダ・デコーダや前処理、深層学習、後処理などの処理をGstreamerを使って処理できるようです。今回はこれのチュートリアルについて試していこうと思います。

構築済みイメージをSDカードに書き込む

VVASのチュートリアルのページを参考にMultichannel MLのデモを試していきます。
https://xilinx.github.io/VVAS/main/build/html/docs/Embedded/Tutorials/MultiChannelML.html

まずはじめにXilinxのサイトからMultichannel ML構築済みイメージをダウンロードします。
https://japan.xilinx.com/products/design-tools/vitis/vvas.html#development

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をダウンロードします。
https://etcher.download/download-etcher/

ダウンロードしたEtcherを起動し、sd_card.imgをSDカードに書き込みます。

チュートリアルの内容とデバイス構成

今回のチュートリアルは、H.264ファイルを入力ソースとして、そのファイルをデコードしてNV12フォーマットにします。その後にAI処理を適用し顔検出した部分にバウンディングボックスをオーバーレイしてHDMIモニタに出力するという内容になります。
https://xilinx.github.io/VVAS/main/build/html/_images/single_channel_pipeline.png

チュートリアルを実行するデバイス構成は以下の通りとなります。
WindowsPCからZCU104へはTeraTermで接続します。BAUDレートは115200(bps)を設定します。

ごちゃっとしていますが、写真でみると以下のようになります。

チュートリアルの準備

上の構成が準備できたらZCU104を起動します。
起動後、以下のコマンドを実行してルートファイルシステムパーティションを100%のサイズに拡張します。またWindowsPCと通信できるようにIPアドレスも変更します。
(ここではWindows側は192.168.0.15にしています。)

TeraTerm
resize-part /dev/mmcblk0p2
ifconfig eth0 192.168.0.20

次にチュートリアルで使用するH.264の動画ファイルをZCU104に転送します。
動画ファイルが手元に無い場合は、IPHONEなどで自分の顔を撮影したデータを使用すると良いです。WindowPC上でCMDプロンプトを起動し、MOVファイルのあるディレクトリから以下のコマンドを実行して転送します。(scpのパスワードはrootを指定します。)

CMD
scp file.mov root@192.168.0.20:~

AIのモデルjsonファイルとスクリプトもZCU104に転送します。フォルダ毎コピーするので-rオプションを指定してscpを実行します。

CMD
scp -r vvas_multichannel_ml_2021.1_zcu104/utils root@192.168.0.20:~

ボード用AIモデルファイルをコピーします。

CMD
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データに保存する処理を実行します。

FileSrcFileSinkについてはGstreamerのOpenソースプラグインを使用します。
VCUDecについてはFPGAに統合されたVCUを動かすためのプラグインを使用します。
TeraTermから、以下のGstreamerのパイプラインを実行します。

TeraTerm
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に転送します。

CMD
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のパイプラインを実行します。

TeraTerm
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に転送します。

CMD
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のパイプラインを実行します。

TeraTerm
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のパイプラインを実行します。

TeraTerm
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