Vitis-AI v1.4 on Ultra96v2


この記事では[DNNDK on Vitis AI on Ultra96v2](https://qiita.com/nv-h/items/7525c9319087a3f51755)をベースに，Vitis-AI v1.4/Vitis 2020.2を用いてUltra96v2向けのプラットフォームを作成し、YOLOv3-tinyを動作させます。手順書のようであまり解説はありません。  

# Setup
- Host: Ubuntu 18.04
- Vitis 2020.2 Unified Software Platform
- petalinux 2020.2
- Vitis-AI v1.4
[Xilinx統合環境インストーラ](https://japan.xilinx.com/support/download/index.html/content/xilinx/ja/downloadNav/vivado-design-tools/2020-2.html)をダウンロード  
Petalinuxはこのインストーラを使用してダウンロードしたインストーラを起動して、インストールできた。   

```sh
# Vitisを選択して/tools/Xilinxにインストール、再度起動してPetalinuxダウンロード
sudo ./Xilinx_Unified_2020.2_1118_1232_Lin64.bin
# Petalinuxインストール
sudo chmod +x /tools/Xilinx/PetaLinux/2020.2/bin/petalinux-v2020.2-final-installer.run 
mkdir ~/petalinux_2020.2/
/tools/Xilinx/PetaLinux/2020.2/bin/petalinux-v2020.2-final-installer.run --dir ~/petalinux_2020.2/
# 2020.2有効化
source /tools/Xilinx/Vivado/2020.2/settings64.sh
source /tools/Xilinx/Vitis/2020.2/settings64.sh
source ~/petalinux_2020.2/settings.sh
```
便宜上、作業を行うディレクトリをBUILD_HOMEと名前を付けておきます。
必要なものをダウンロードします。

```sh
mkdir ultra96_vai1_4 #適当な名前
export BUILD_HOME="$PWD"
#Vitis-AI
git clone https://github.com/Xilinx/Vitis-AI
cd Vitis-AI
git checkout refs/tags/v1.4
export VITIS_AI_HOME="$PWD"
```

## Avnet Vitis platforms
Avnetが用意してくれているハードウェアプラットフォームです。

```sh
cd $BUILD_HOME
mkdir Avnet
cd Avnet
git clone https://github.com/Avnet/bdf
git clone -b 2020p2_u96v2_sbc_base_20210426_105325 https://github.com/Avnet/hdl
git clone -b 2020p2_u96v2_sbc_base_20210426_105325 https://github.com/Avnet/petalinux
git clone -b 2020p2_u96v2_sbc_base_20210426_105325 https://github.com/Avnet/vitis
```

ビルド済みのものをAvnetのコミュニティからダウンロードすることもできます。  
[Ultra96のページ](https://www.element14.com/community/docs/DOC-95649)から`Vitis PetaLinux Platform -> Ultra96-V2 – Vitis Platform 2020+ (Sharepoint site) -> 2020.2/Vitis_Platform/u96v2_sbc_vitis_2020_2.tar.gz`をダウンロードできます。  
今回は1からやってみたかったので自分でビルドしました。ビルド前に`Avnet/petalinux`に以下の修正を適用する必要がありました。`Avnet/`以下のgitのtagチェックの修正と、petalinuxで`Failed to add user layers`になってしまう問題の回避をしています。（なぜconfigure_petalinux_project()でキャッシュを無効にしないとだめなのかはよくわかっていません）  

```diff
diff --git a/scripts/common.sh b/scripts/common.sh
index 72d2256..cca75da 100755
--- a/scripts/common.sh
+++ b/scripts/common.sh
@@ -124,11 +124,11 @@ check_git_tag()
     # Verify the hdl repository is checked out with the correct ${TAG_STRING} tag
     cd ${HDL_FOLDER}
     echo -e "\nVerifying the hdl repository is checked out with the correct ${TAG_STRING} tag.\n"
-    if [ ${TAG_STRING} = $(git status head | head -n1 | cut -d ' ' -f4) ]
+    if [ ${TAG_STRING} = $(git status head | head -n1 | cut -d ' ' -f2) ]
     then
       echo -e "\nReported hdl tag matches ${TAG_STRING}.  Check petalinux tag next...\n"
     else
-      echo -e "\nReported hdl tag is $(git status head | head -n1 | cut -d ' ' -f4).\n"
+      echo -e "\nReported hdl tag is $(git status head | head -n1 | cut -d ' ' -f2).\n"
       echo -e "\nThis does not match requested ${TAG_STRING}.  Exiting now.\n"
       exit
     fi
@@ -136,11 +136,11 @@ check_git_tag()
     # Verify the petalinux repository is checked out with the correct ${TAG_STRING} tag
     cd ${PETALINUX_FOLDER}
     echo -e "\nVerifying the petalinux repository is checked out with the correct ${TAG_STRING} tag.\n"
-    if [ ${TAG_STRING} = $(git status head | head -n1 | cut -d ' ' -f4) ]
+    if [ ${TAG_STRING} = $(git status head | head -n1 | cut -d ' ' -f2) ]
     then
       echo -e "\nReported petalinux tag matches ${TAG_STRING}.  Build will continue...\n"
     else
-      echo -e "\nReported petalinux tag is $(git status head | head -n1 | cut -d ' ' -f4).\n"
+      echo -e "\nReported petalinux tag is $(git status head | head -n1 | cut -d ' ' -f2).\n"
       echo -e "\nThis does not match ${TAG_STRING}.  Exiting now.\n"
       exit
     fi
@@ -339,10 +339,10 @@ configure_petalinux_project()
     git clone -b ${META_AVNET_BRANCH} ${META_AVNET_URL} project-spec/meta-avnet
   fi

-  if [ "$KEEP_CACHE" = "true" ]
-  then
-    configure_cache_path
-  fi
+  # if [ "$KEEP_CACHE" = "true" ]
+  # then
+  #   configure_cache_path
+  # fi

   if [ "$KEEP_WORK" = "true" ]
   then
diff --git a/scripts/make_u96v2_sbc_base.sh b/scripts/make_u96v2_sbc_base.sh
index 8e50ab5..315ba2a 100755
--- a/scripts/make_u96v2_sbc_base.sh
+++ b/scripts/make_u96v2_sbc_base.sh
@@ -71,7 +71,7 @@ DEBUG="no"
 #NO_BIT_OPTION can be set to 'yes' to generate a BOOT.BIN without bitstream
 NO_BIT_OPTION='yes'

-source ${MAIN_SCRIPT_FOLDER}/common.sh
+. ${MAIN_SCRIPT_FOLDER}/common.sh
```

適用後は以下のようにしてビルドできます。2時間くらいかかりました。

```sh
cd $BUILD_HOME/Avnet/vitis
make u96v2_sbc
```
ダウンロードまたはビルドが完了すれば、Vitisフローで必要になる環境変数を設定しておきます。

```sh
export SDX_PLATFORM=$BUILD_HOME/Avnet/vitis/platform_repo/u96v2_sbc_base/u96v2_sbc_base.xpfm
```

# Build the Hardware Project
Vitis-AIリポジトリにある、DPU-TRDを元に作成します。
参考記事と同様、Vitis-AIリポジトリからコピーして修正し、ビルドを行います。
ここでの手順は[`Vitis-AI/dsa/DPU-TRD/prj/Vitis/README.md`](https://github.com/Xilinx/Vitis-AI/blob/v1.4/dsa/DPU-TRD/prj/Vitis/README.md)を参考にしています。

Vitis-AI v1.1の時とはDPU-TRDの位置が変更されていました。また、[README](https://github.com/Xilinx/Vitis-AI/blob/v1.4/dsa/DPU-TRD/prj/Vitis/README.md#521-building-the-hardware-design)にもあるように、新たに`$EDGE_COMMON_SW`を設定しておく必要があります。

```sh
cd $BUILD_HOME
mkdir ultra96v2_vitis_flow_tutorial_1 #適当な名前
cd ultra96v2_vitis_flow_tutorial_1
cp -r $VITIS_AI_HOME/dsa/DPU-TRD ./DPU-TRD-ULTRA96V2
export TRD_HOME=$BUILD_HOME/ultra96v2_vitis_flow_tutorial_1/DPU-TRD-ULTRA96V2
export EDGE_COMMON_SW=$BUILD_HOME/Avnet/petalinux/projects/u96v2_sbc_base_2020_2/images/linux
```

Ultra96v2向けに、以下の2つの設定ファイルを編集します。
- `$TRD_HOME/prj/Vitis/dpu_conf.vh`: DPUの構成を小さいものに変更

```diff
26c26
< `define B4096 
---
> `define B1600
```
- `$TRD_HOME/prj/Vitis/config_file/prj_config`: Vivado(HWプラットフォーム)構成に合わせて修正

```diff
< freqHz=300000000:DPUCZDX8G_1.aclk
< freqHz=600000000:DPUCZDX8G_1.ap_clk_2
< freqHz=300000000:DPUCZDX8G_2.aclk
< freqHz=600000000:DPUCZDX8G_2.ap_clk_2
---
> id=0:DPUCZDX8G_1.aclk
> id=1:DPUCZDX8G_1.ap_clk_2
30,32d27
< sp=DPUCZDX8G_2.M_AXI_GP0:HPC0
< sp=DPUCZDX8G_2.M_AXI_HP0:HP2
< sp=DPUCZDX8G_2.M_AXI_HP2:HP3
35c30
< nk=DPUCZDX8G:2
---
> nk=DPUCZDX8G:1
```
修正が完了したら、ビルドします。

```sh
cd $TRD_HOME/prj/Vitis/
make KERNEL=DPU DEVICE=ULTRA96V2
```

ハードウェアのビルドはそれなりに時間がかかるので、待ちます。
完了すると、以下に必要なものができあがっています。

```sh
tree binary_container_1/sd_card
binary_container_1/sd_card
├── BOOT.BIN
├── Image
├── arch.json
├── boot.scr
├── dpu.xclbin
├── image.ub
├── init.sh
├── platform_desc.txt
├── rootfs.tar.gz
└── u96v2_sbc_base.hwh
```

# Compile the Models from the Xilinx Model Zoo
Vitis-AIコンテナをビルドします。CPUしか使わない場合は`docker pull xilinx/vitis-ai:1.4.916`でセットアップできます。 
 
```sh
cd $VITIS_AI_HOME/setup/docker
./docker_build_gpu.sh

```

XilinxがAI-Model-Zooで公開しているモデルのうち、いくつかのモデルはUltra96での性能が公開されています：
https://github.com/Xilinx/Vitis-AI/tree/master/models/AI-Model-Zoo#performance-on-ultra96  

AI-Model-Zooには[tiny-yolov3モデルが存在する](https://github.com/Xilinx/Vitis-AI/blob/master/models/AI-Model-Zoo/model-list/dk_tiny-yolov3_416_416_5.46G_1.4/model.yaml)のですが、なぜかUltra96での性能が公開されていません。しかも、この`tiny_yolov3_vmss`はクラスカテゴリが['KELLOGS,CHOCOLATE,CANDLE,SHAMPOO,BULB,PLIERS,DETERGENT,KOOLAID,LIPSTICK,BOX']となっていて、データセットも見つかりません・・  

そこで、今回はVitis-AI v1.1で動作させたことのあるtiny_yolov3によるface mask検出を動作させてみようと思います。 
[Real-time tiny-YOLOv3 face mask detection on Ultra96v2](https://www.hackster.io/yasuhironitta/real-time-tiny-yolov3-face-mask-detection-on-ultra96v2-63a70c)
`tiny-yolov3`の学習方法については元記事で紹介しています。学習済みのモデル・重みは[GitHub](https://github.com/lp6m/tiny_yolov3_face_mask_detect/tree/master/host)で公開しています。元記事でも記述の通り、オリジナルのyolov3-tiny.cfgから変更を加えています。（darknetからcaffeへの変換の失敗を防ぐためmaxpoolのサイズを1箇所変更）
量子化に必要なデータセットは[YOLOv3-face-mask-detection](https://github.com/VictorLin000/YOLOv3_mask_detect)からダウンロードします。

モデルのコンパイルはVitis-AI dockerコンテナ環境で行います。

```sh
cd $VITIS_AI_HOME
mkdir yolov3_tiny_model #ここにモデルとデータセット(mask.zip)を配置
cd yolov3_tiny_model
unzip mask.zip
cd $BUILD_HOME
./Vitis-AI/docker_run.sh xilinx/vitis-ai-gpu:1.4.916 
#以下dockerコンテナ内で作業
conda activate vitis-ai-caffe
cd /workspace/Vitis-AI/yolov3_tiny_model
```

## Darknet2Caffe
DarknetからCaffeに変換するスクリプトがXilinxから提供されています。

```sh
python3 ../models/AI-Model-Zoo/caffe-xilinx/scripts/convert.py yolov3-tiny_mask.cfg yolov3-tiny_mask_60000.weights yolov3_tiny_mask.prototxt yolov3_tiny_mask.caffemodel
```

## Quantization
`Vitis-AI Quantizer`を使用してモデルの量子化を行います。量子化のためのprototxtを作成します。

```sh
cp yolov3_tiny_mask.prototxt for_quantize.prototxt
```
量子化のスケールを最適化するために、実際に推論で使用する画像を使用してキャリブレーションを行います。
`for_quantize.prototxt`の1〜6行目を削除し、以下のようにキャリブレーション画像へのパスを設定します。  

```diff
diff yolov3_tiny_mask.prototxt for_quantize.prototxt 
1,6c1,18
< name: "Darkent2Caffe"
< input: "data"
< input_dim: 1
< input_dim: 3
< input_dim: 224
< input_dim: 224
---
> layer {
>   name: "data"
>   type: "ImageData"
>   top: "data"
>   top: "label"
>   include {
>     phase: TRAIN
>   }
>   image_data_param {
>     source: "./quant.txt"
>     batch_size: 16
>   }
>   transform_param {
>     mirror: false
>     yolo_width: 416
>     yolo_height: 416
>   }
> }
```

画像ファイルリストを`quant.txt`として作成します。以下のPythonコードで作成しました。

```python
import os
import glob
calib_images = glob.glob('./mask/*.jpg')
for calib_image in calib_images:
    print(os.path.abspath(calib_image), 0)
```

```sh
python3 gen_quantize_list.py > quant.txt
vai_q_caffe quantize \
    -model ./for_quantize.prototxt \
    -weights ./yolov3_tiny_mask.caffemodel \
    --keep_fixed_neuron \
    -calib_iter 100 \
    -gpu 0
```
量子化が完了すると、以下のようにファイルが生成されます。

```
...
I1105 12:47:51.496042  7397 vai_q.cpp:368] Deploy Done!
--------------------------------------------------
Output Quantized Train&Test Model:   "./quantize_results/quantize_train_test.prototxt"
Output Quantized Train&Test Weights: "./quantize_results/quantize_train_test.caffemodel"
Output Deploy Weights: "./quantize_results/deploy.caffemodel"
Output Deploy Model:   "./quantize_results/deploy.prototxt"
```

## Compilation
次に、DPU向けにモデルのコンパイルを行います。
ここで、DPUの構成に応じてコンパイルをする必要があり、Step1で生成された`arch.json`を使用します。
ちなみに、Vitis-AI v1.2まではDPU情報を表記した`hwh`ファイルから`dlet`を用いて`dcf`を生成していましたが、`dlet`はv1.3以降docker環境に存在しないようです。   

```
cp /workspace/ultra96v2_vitis_flow_tutorial_1/DPU-TRD-ULTRA96V2/prj/Vitis/binary_container_1/sd_card/arch.json ./
vai_c_caffe \
    -a arch.json \
    -p ./quantize_results/deploy.prototxt \
    -c ./quantize_results/deploy.caffemodel \
    -o ./compiled \
    -n yolov3_tiny_mask
```

```
**************************************************
* VITIS_AI Compilation - Xilinx Inc.
**************************************************
[INFO] Namespace(batchsize=1, inputs_shape=None, layout='NCHW', model_files=['./quantize_results/deploy.caffemodel'], model_type='caffe', named_inputs_shape=None, out_filename='/tmp/yolov3_tiny_mask_org.xmodel', proto='./quantize_results/deploy.prototxt')
[INFO] caffe model: /workspace/Vitis-AI/yolov3_tiny_model/quantize_results/deploy.caffemodel
[INFO] caffe model: /workspace/Vitis-AI/yolov3_tiny_model/quantize_results/deploy.prototxt
[INFO] parse raw model     :100%|██████████████████████████████████████████████████████████████████| 48/48 [00:01<00:00, 38.79it/s]                  
[INFO] infer shape (NCHW)  :100%|██████████████████████████████████████████████████████████████████| 48/48 [00:00<00:00, 2231.09it/s]                
[INFO] infer shape (NHWC)  :100%|██████████████████████████████████████████████████████████████████| 48/48 [00:00<00:00, 3651.45it/s]                
[INFO] perform level-1 opt :100%|██████████████████████████████████████████████████████████████████| 3/3 [00:00<00:00, 1443.49it/s]                  
[INFO] generate xmodel     :100%|██████████████████████████████████████████████████████████████████| 48/48 [00:00<00:00, 647.94it/s]                 
[INFO] dump xmodel: /tmp/yolov3_tiny_mask_org.xmodel
[UNILOG][INFO] Compile mode: dpu
[UNILOG][INFO] Debug mode: function
[UNILOG][INFO] Target architecture: DPUCVDX8G_ISA0_B1600_01000020F6014404
[UNILOG][INFO] Graph name: deploy, with op num: 100
[UNILOG][INFO] Begin to compile...
[UNILOG][WARNING] xir::Op{name = layer11-maxpool, type = pool-fix}'s input and output is unchanged, so it will be removed.
[UNILOG][INFO] Total device subgraph number 4, DPU subgraph number 1
[UNILOG][INFO] Compile done.
[UNILOG][INFO] The meta json is saved to "/workspace/Vitis-AI/yolov3_tiny_model/./compiled/meta.json"
[UNILOG][INFO] The compiled xmodel is saved to "/workspace/Vitis-AI/yolov3_tiny_model/./compiled/yolov3_tiny_mask.xmodel"
[UNILOG][INFO] The compiled xmodel's md5sum is 5476c1153bfe24bc2665ca081d449edb, and has been saved to "/workspace/Vitis-AI/yolov3_tiny_model/./compiled/md5sum.txt"
```
`DPU subgraph number 1`となっているので理想的にDPUにオフロードされていそうです。
`netron`を使用してコンパイルしたモデル`yolov3_tiny_mask.xmodel`を確認できました。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/7153b7ee-2be8-b988-e4b7-0bf3d67f6b25.png width=200px>
## prototxt
今回使用するXilinxの評価アプリケーションはモデルの情報をprototxtファイルから読み込みます。
AI-Model-Zooにあるtiny-yolov3を参考に以下のprototxtファイルを`./compiled/tiny-yolov3.prototxt`として保存しました。

```prototxt
model {
  name: "yolov3_tiny_mask"
  kernel {
     name: "yolov3_tiny_mask_0"
     mean: 0.0
     mean: 0.0
     mean: 0.0
     scale: 0.00390625
     scale: 0.00390625
     scale: 0.00390625
  }
  model_type : YOLOv3
  yolo_v3_param {
    num_classes: 3
    anchorCnt: 3
    layer_name: "15"
    layer_name: "22"
    conf_threshold: 0.3
    nms_threshold: 0.45
    biases: 10
    biases: 14
    biases: 23
    biases: 27
    biases: 37
    biases: 58
    biases: 81
    biases: 82
    biases: 135
    biases: 169
    biases: 344
    biases: 319
    test_mAP: false
  }
}
```

# Compile the AI Applications
クロスコンパイル環境を整えてyolov3の評価アプリケーションをホスト上でビルドします。
本手順はVitis-AIドキュメントの[`step1-setup-cross-compiler`](https://github.com/Xilinx/Vitis-AI/tree/master/setup/mpsoc/VART#step1-setup-cross-compiler)に沿っています。
この作業はdockerコンテナではなくホスト環境で行います。

Vitis2020.2を使用しているので`./host_cross_compiler_setup_2020.2.sh`を実行する

```sh
cd $VITIS_AI_HOME/setup/mpsoc
./host_cross_compiler_setup_2020.2.sh
unset LD_LIBRARY_PATH
source /home/`$USER`/petalinux_sdk_2020.2/environment-setup-aarch64-xilinx-linux
```
クロスコンパイル環境が整ったのでアプリケーションをビルドします。
yolov3含め多数モデル向けの評価アプリケーションが公開されています。

```sh
cd $VITIS_AI_HOME/demo/Vitis-AI-Library/samples/yolov3
sh build.sh
```
`test_jpeg_yolov3, test_accuracy_yolov3_mt, test_performance_yolov3, test_video_yolov3`の4つの実行ファイルが生成されています。

# Create the SD card
これまでに作成したものを集めてきて、Ultra96v2で使用するSDカードを作成します。
Gpartedなどを使用して第一パーティションをFAT, 第二パーティションをext4でフォーマットします。  
（それぞれ`BOOT, rootfs`とラベルを付けました。)
- ブートに必要なもの

```sh
cd $TRD_HOME/prj/Vitis/binary_container_1/sd_card
cp dpu.xclbin /media/lp6m/BOOT/
cp BOOT.BIN  /media/lp6m/BOOT/
cp image.ub /media/lp6m/BOOT/
cp boot.scr /media/lp6m/BOOT/
cp Image /media/lp6m/BOOT/
sudo tar xvf rootfs.tar.gz -C /media/lp6m/rootfs/
```
- VART(Vitis-AI-Runtime)

```sh
cd $VITIS_AI_HOME/setup/mpsoc
sudo cp -r VART /media/lp6m/rootfs/home/root/
```

- yolov3 model, application, test image (video)

```sh
cd $VITIS_AI_HOME/yolov3_tiny_model
sudo cp -r compiled /media/lp6m/rootfs/home/root/yolov3_tiny_mask
sudo cp -r mask /media/lp6m/rootfs/home/root
cd $VITIS_AI_HOME/demo/Vitis-AI-Library/samples
sudo cp -r yolov3 /media/lp6m/rootfs/home/root/yolov3_app
sync
```
`sync`が完了してからSDを取り外します。
- SDカード
- Ultra96V2
- 電源

# Execute the AI applications on hardware
SDカード、電源、HDMIアダプタ、キーボード、マウス、Webカメラなどを繋いで本体を起動します。
参考：[Ultra96-V2 で開発を行う際に必要なもの & あるといいもの](https://withfpga.com/?p=169)
以降の作業はUltra96上で行います。

## Wifiの設定
ターミナルを開いて、`/home/root/wpa_supplicant.conf`を編集してSSIDとパスワードを設定します。

```sh
./wifi.sh
ifconfig -a
```

これでネットワークにつながるので、sshもできるようになります。(パスワードはroot)  

## VART(Vitis-AI Runtime)の実機へのインストール
[VART(Vitis-AI Runtime)の実機へのインストール](https://github.com/Xilinx/Vitis-AI/tree/master/tools/Vitis-AI-Library)を参考にします。
無事起動したらVARTを実機側にもインストールします。  

```sh
cd /home/root/VART
./target_vart_setup_2020.2.sh 
```

## dexplorerでDPU情報確認
`dexplorer`でDPUのバージョンや有効になっている機能をチェックすることができます。
`/usr/lib/`にカーネルイメージ`dpu.xclbin`をコピーする必要があります。  
  
```sh
cp /mnt/sd-mmcblk0p1/dpu.xclbin /usr/lib/
dexplorer -w
[DPU IP Spec]
IP  Timestamp            : 2021-06-07 19:15:00
DPU Core Count           : 1

[DPU Core Configuration List]
DPU Core                 : #0
DPU Enabled              : Yes
DPU Arch                 : B1600
DPU Target Version       : v1.4.1
DPU Freqency             : 150 MHz
Ram Usage                : Low
DepthwiseConv            : Enabled
DepthwiseConv+Relu6      : Enabled
Conv+Leakyrelu           : Enabled
Conv+Relu6               : Enabled
Channel Augmentation     : Enabled
Average Pool             : Enabled
```

## Test Performance
評価アプリケーションは`/usr/share/vitis_ai_library/models`内のモデルを対象に実行するので、コンパイルしたモデルをコピーします。

```sh
mkdir /usr/share/vitis_ai_library/models
cp -r yolov3_tiny_mask /usr/share/vitis_ai_library/models/
```
パフォーマンス計測には画像が1枚以上必要なので、画像リスト`image.list`を作成します。  

```sh
cd ~/yolov3_app
echo "/home/root/mask/Mask_0.jpg" > image.list
./test_performance_yolov3 yolov3_tiny_mask image.list
WARNING: Logging before InitGoogleLogging() is written to STDERR
I1105 19:42:33.142753  1657 benchmark.hpp:184] writing report to <STDOUT>
I1105 19:42:33.143976  1657 benchmark.hpp:211] waiting for 0/30 seconds, 1 threads running
I1105 19:42:43.144228  1657 benchmark.hpp:211] waiting for 10/30 seconds, 1 threads running
I1105 19:42:53.144506  1657 benchmark.hpp:211] waiting for 20/30 seconds, 1 threads running
I1105 19:43:03.144932  1657 benchmark.hpp:219] waiting for threads terminated
FPS=28.2217
E2E_MEAN=35403.1
DPU_MEAN=32646.8
```
画像サイズ416x416の`yolov3-tiny`はUltra96v2上(DPU1600, 150Mhz)で28FPSが達成されることがわかりました。  グラフ全体をDPUにオフロードできたため、End-to-Endの時間のうちほとんどの時間がDPUの時間を占めています。

## Image Test
```sh
./test_jpeg_yolov3 yolov3_tiny_mask ../mask/Mask_74.jpg
I1105 20:43:09.306178  1530 demo.hpp:1183] batch: 0     image: ../mask/Mask_74.jpg
I1105 20:43:09.306447  1530 process_result.hpp:44] RESULT: 0	1701.7	1393.09	2543.82	2229.84	0.983498
I1105 20:43:09.306952  1530 process_result.hpp:44] RESULT: 0	581.677	742.82	1237.53	1579.57	0.777177
I1105 20:43:09.307421  1530 process_result.hpp:44] RESULT: 2	3082.35	219.546	4175.43	1562.61	0.990156

```
残念ながら評価アプリケーションはbboxを描画してくれないようなので適当に手元で描画した結果はこのようになりました。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/d3206744-0318-77ab-b25f-beca0e962c37.jpeg width=600>
今回は精度評価などは行なっていませんがある程度認識できているように思います。

## Video Test
最近のニュース番組を使うと良い感じになります。

```sh
export DISPLAY=:0.0
xrandr --output DP-1 --mode 640x480
./test_vido_yolov3 yolov3_tiny_mask youtube.mp4
```
解像度を変更してから実行したのですが動画の評価を実行中は画面のちらつきがものすごくひどくなってしまいました。  

# まとめ

とりあえずVitis-AI v1.4 / Vitis 2020.2のフローを追うことができた。