ブログ

Armadillo-IoT G4:NPUでMobilenet_v1の推論を行う方法

at_shinya.matsumoto
2022年5月19日 12時59分

本ブログはArmadillo-IoT G4でNPU(Neural network Processing Unit)を使った物体検知(推論)を
行う方法を説明します。モデルは学習済みのモデルMobilenet v1でTensorflow Liteを使用します。
(Armadillo-IoT G4は他にONNX,ArmNNが使用可能)

Armadillo-IoT G4とは
 NPU搭載・エッジAI処理にも対応する高性能IoTゲートウェイです。LTE搭載やMIPIカメラにも対応しております。
 製品詳細はこちらを参照ください。

はじめに

Armadillo-IoT G4はコンテナ型OS(podmanエンジン)を採用しており、アプリケーション開発は全てコンテナ内で行います。
コンテナ操作の詳細につきましては製品マニュアルをご参照下さい。

また、Armadillo-IoT G4はeMMC(ストレージ)への書き込みを最小限にする観点から、tmpfs(メモリ上に作成するファイルシステム)に保存する設定にしております。メモリ上のファイルは電源を一度落とすと消えてしまう為、開発時はeMMCへ書き込む様に下記の様に設定を変更します。

ファイルをeMMCへ保存に変更するコマンド
# abos-ctrl podman-storage --disk    (バージョン v3.15.4-at.6以降で対応)
または
# podman_switch_storage --disk
 
ファイルをtmpfs(メモリ)へ保存に変更するコマンド
# abos-ctrl podman-storage --tmpfs    (バージョン v3.15.4-at.6以降で対応)
または
# podman_switch_storage --tmpfs
 
ファイルの保存先設定を確認するコマンド(下記はeMMCへ保存する設定)
# abos-ctrl podman-storage --status    (バージョン v3.15.4-at.6以降で対応)
または
# podman_switch_storage --status
Currently in disk mode, run with --tmpfs to switch

以下、eMMCへ保存する事を前提で記載致します。

物体検知実行手順

実行手順は下記の順に行います。
1.コンテナイメージ作成
2.コンテナ作成
3.推論実行
4.推論時のERRORログについて


また、firmwareとtiliteランタイムのバージョンは下記を使用しています。
このバージョンが違う場合はログの内容や動作が少し異なりますのでご注意下さい。
 firmware:2.2.0
 tfliteランタイム:2.6.0-1

firmwareの更新方法は製品マニュアルを参照ください。
下記コマンドでバージョンが表示されない(ファイルが存在しない)場合は2.2.0より以前のfirmwareになります。

[armadillo]# cat /opt/firmware/etc/imxlib_version
2.2.0

1.コンテナイメージ作成

コンテナイメージを作成する為、当社ArmadilloサイトよりDockerfileをダウンロードします。
本Dockerfileを用いる事で必要なリポジトリ、westonのコンフィグも組み込まれます。
※以後、[armadillo]はArmadillo BASE OS上、[container]はコンテナ内の作業を意味します。

Debian 11 (bullseye) サンプル Dockerfileをダウンロード
[armadillo]# wget https://armadillo.atmark-techno.com/files/downloads/armadillo-iot-g4/container/at-debian-image-dockerfile-[version].tar.gz
[armadillo]# tar zxf at-debian-image-dockerfile-[version].tar.gz
[armadillo]# cd at-debian-image-dockerfile-[version]
[armadillo]# ls
Dockerfile  resources


次に、Dockerfileをvi等で下記の様に書き換えます。(下記Dockerfileはv1.0.5の場合)
上から2つ目のRUNの行が今回追加した内容になります。

[armadillo]# cat Dockerfile
FROM docker.io/debian:bullseye
 
LABEL version="1.0.5"
 
COPY resources /
 
ARG USERNAME=atmark
ARG UID=1000
RUN apt-get update && apt-get upgrade -y && apt-get install -y weston \
    && apt-get clean && mkdir -m 1777 /tmp/.X11-unix \
    && mkdir /run/xdg_home && useradd -m -u ${UID} ${USERNAME}
RUN apt-get install -y tensorflow-lite tensorflow-lite-dev python3-tflite-runtime \
    tim-vx tensorflow-lite-vx-delegate python3-opencv \
    && apt-get install -y git unzip vim wget curl
ENV LD_LIBRARY_PATH /opt/firmware/usr/lib/aarch64-linux-gnu
ENV XDG_RUNTIME_DIR /run/xdg_home
ENV VIVANTE_SDK_DIR /opt/firmware/usr


Dockerfileが完成したら、Dockerfileがあるディレクトリでpodman buildコマンドを実行し、
コンテナイメージを作成します。ここではイメージ名をtflite_image、タグをv1.0としています。

[armadillo]# podman build -t tflite_image:v1.0 .
STEP 1/10: FROM docker.io/debian:bullseye
STEP 2/10: LABEL version="1.0.5"
--> 39f32520367
STEP 3/10: COPY resources /
 
<中略>
 
Successfully tagged localhost/tflite_image:v1.0
920589f11bfe3e440cd4596f43e60feb8523c8400db181d9890daa4f318075d6
[armadillo]# podman images
REPOSITORY                 TAG         IMAGE ID      CREATED         SIZE
localhost/tflite_image     v1.0        920589f11bfe  16 seconds ago  427 MB

以上で、必要なパッケージをインストールしたコンテナイメージの作成は完了です。

2.コンテナ作成

次にコンテナを作成する為のconfファイルを作成します。
podman runコマンドで作成する事も出来ますが、コンテナの作り替えや自動起動にもそのまま使える為、
今回はconfファイルを作成します。confファイルの書式は製品マニュアルを参照ください。

下記ディレクトリに移動
[armadillo]# cd /etc/atmark/containers/
 
下記のtflite_demo.confを作成(ファイル名=コンテナ名)
※/dev/video2ついては環境によって異なる可能性がある為、適宜調整下さい。
[armadillo]# cat tflite_demo.conf
set_image tflite_image:v1.0
add_args --env=XDG_RUNTIME_DIR=/tmp
add_args --env=QT_QPA_PLATFORM=wayland
add_args --env=LD_LIBRARY_PATH=/opt/firmware/usr/lib/aarch64-linux-gnu
add_args --cap-add=SYS_TTY_CONFIG
add_devices /dev/dri /dev/galcore /dev/mxc_hantro /dev/mxc_hantro_vc8000e
add_devices /dev/ion /dev/input /dev/tty1 /dev/video2
add_volumes /run/udev:/run/udev:ro /opt/firmware:/opt/firmware:ro
set_autostart no
add_args -it
set_command /bin/bash

《補足》
 /dev/mxc_hantro :VPU使用時に必要
 /dev/mxc_hantro_vc8000e :VPU使用時に必要
 /dev/ion :VPU使用時に必要
 /dev/dri :ドライバ(今回はHDMI)
 /dev/input :キーボード等のインプット用
 /dev/tty1 :HDMI出力のデバイス
 /opt/firmware:/opt/firmware:ro :VPU,NPU使用時に必要
 /run/udev:/run/udev:ro  :デバイス管理用
 /dev/video2 :今回使用するカメラのデバイス番号

作成したconfファイルを電源ON/OFFでも消えない様に永続化(eMMCに書き込み)し、 次にコンテナを起動~コンテナ内に入ります。

tflite_demo.confを永続化
[armadillo]# persist_file tflite_demo.conf
 
tflite_demoコンテナを作成・起動~確認
[armadillo]# podman_start tflite_demo
[armadillo]# podman ps
CONTAINER ID  IMAGE                        COMMAND     CREATED        STATUS            PORTS       NAMES
a337d6791662  localhost/tflite_image:v1.0  /bin/bash   5 seconds ago  Up 5 seconds ago              tflite_demo
 
コンテナに入る(カメラの接続は事前に実施)
[armadillo]# podman exec -it tflite_demo /bin/bash

以上でコンテナの作成が完了です。
元のイメージから再作成したい場合はpodman_start tflite_demoで元のイメージの状態のコンテナに上書きされます。
コンテナ内の作業をコンテナイメージ化したい場合はpodman commitコマンドで別名で保存出来ます
(例:podman commit tflite_demo tflite_image:v1.1)

3.推論実行

以降はコンテナ内での作業になります。

gitコマンドでソースコードをダウンロード、ディレクトリ名を変更(任意)、ディレクトリ内に移動
[container]# git clone https://github.com/EdjeElectronics/TensorFlow-Lite-Object-Detection-on-Android-and-Raspberry-Pi.git
[container]# mv TensorFlow-Lite-Object-Detection-on-Android-and-Raspberry-Pi tflite_demo
[container]# cd tflite_demo/
 
tfliteのモデルとラベルをダウンロードし、解凍
[container]# wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip
[container]# unzip coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip


今回はTFLite_detection_webcam.pyを使用しますが、カメラ番号を変更する必要がある為、
ソースコードの”self.stream = cv2.VideoCapture(0)”を書き換えます。
カメラ番号は/dev/videoXの番号に合わせてください

◆変更前
class VideoStream:
    """Camera object that controls video streaming from the Picamera"""
    def __init__(self,resolution=(640,480),framerate=30):
        # Initialize the PiCamera and the camera image stream
        self.stream = cv2.VideoCapture(0)
 
◆変更後(videoの番号に合わせてください)
class VideoStream:
    """Camera object that controls video streaming from the Picamera"""
    def __init__(self,resolution=(640,480),framerate=30):
        # Initialize the PiCamera and the camera image stream
        self.stream = cv2.VideoCapture(2)


ソースコードの修正が完了したら動作確認をします。

westonを起動
[container]# weston --tty=1 &
 
カメラで推論を実行(8秒ほどで立ち上がります)
[container]# python3 TFLite_detection_webcam.py --modeldir=$PWD


終了する場合は、キーボードを接続している場合はqキーで停止します。
その他方法ではCtrl+Cで停止します。

フルスクリーン表示する場合には下記2行を追加する事でフルスクリーンで動作します。
設定は1度で良い為、while文より先に記載します。描画時間が変わる為、FPSが低下します。
FPSは実行時の環境にもよる為参考値ですが、1280x720で50FPS、1920×1080で25FPS程度です。
(推論時間は9ms程度)

◆フルスクリーン表示
cv2.namedWindow('Object detector',cv2.WINDOW_NORMAL)
cv2.setWindowProperty('Object detector',cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)

4.推論時のERRORログについて

今回のモデルを使用した推論では実行時に下記エラーが出ます。

ERROR: Fallback unsupported op 32 to TfLite
 このエラーはNPUを使用するためVX delegateを使用していますが、unsupported opがあった為
 TensorFlow LiteにFallbackし、一部の処理をCPUに割り当てているという内容になります。
 このエラーを解消する為にはモデル作成時にunsupported opを解消する必要がありますが、
 CPU処理による遅延が問題無ければそのままでも問題はございません。

また、「W [HandleLayoutInfer:257]Op 18: default layout inference pass.」が表示されますが、
こちらについては特に問題ございません