M5Stack COM.X Sgifoxモジュールを用いたエッジAIの組み込み実装と,エッジAIによる画像処理結果をSigfoxでクラウドへ送信する仕組みのユースケース一例として,「人流エッジAI計測」を作ってみました。
【補足】ここで言うエッジAI
#人流エッジAI計測
画像から人を検出する,ということを断続的に超短周期で実行し続けることで,カメラの前を通り過ぎる人の数をカウントします。
###ソリューションのポイントとメリット
デバイスを設置した現場で,エッジAIを用いて画像から人物の数の情報の取り出しを実行することにより…
- データ量を削減し、必要なデータのみSigfoxで送信可能になる
- プライバシーデータを送信することなく、集めたい必要なデータ収集が可能
- アップロード先のストレージサーバ容量の削減が可能
- AI推論専用の高価な解析サーバが不要に
これらのメリットが得られます。
#前提
Sigfoxについての前提理解は、下記サイトを確認してください。
- Sigfoxクイックスタート
- Sigfox Custom Callbacks
- Sigfox IoT Agency Platform ※IoT Agency Platformはサービス終了となっているため、その他プラットフォームをお使いいただくことをお奨めします
- M5Stack COM.Xの使い方
#使用デバイス
デバイス | 写真 |
---|---|
M5Stack Gray | |
UnitV AI Camera | |
M5Stack用Sigfoxモジュール |
- UnitVのカメラが映像(画像)を取得する
- AIモデルが人を検出し移動人数をカウント,Grayに送る
- GrayがSig moduleを通じてカウント数をSig Cloudへ送信.同時に簡易的な画面表示
- Sig CloudからIot Agency Platformへ集計結果を送信,ダッシュボードを表示
#開発
AIモデル開発、エッジデバイス開発、デプロイの流れを記載します。
##AIモデル開発
YOLOv2をアーキテクチャとした検出モデルで,人物検出の学習を行います。
学習自体に特別なことはありませんが,最終的にエッジデバイス上で動かすkmodel
形式にする必要がある為、
- 軽量である
- 変換可能なモデル(レイヤー)である
という制限が加わります。
これらの制限をクリアしてくれる学習環境としてaXeleRateを利用しました。
###AIモデル開発環境
Ubuntu16.04.5 LTS
###データセット
COCOデータセット2017から以下の絞り込みを行っています.
-
person
タグを持つ - 画像の中に写っている人が2人まで
2人までにしている理由は,人数が多い画像に含まれる人物は非常に小さく映っているものが多く,今回の検出対象(カメラの前を通り過ぎる人)として不適当と判断したことによります。
最終的に絞られたトレーニングデータ35562枚,テストデータ1481枚で学習と評価を行っています。
###学習結果
テストデータに対するmAPの学習推移です。
mAPは物体検出タスクにおいて使われる評価指標で大きい程良い事を示します。
また,kmodel
への変換はaXeleRateが学習終了時に行ってくれています。
モデル自体はページ下部の付録にリンクを置いているので,自由に使って頂いて構いません。
変換処理を自分で行う場合の参考リンク
- 変換モジュール(NNcase): aXeleRateも内部ではこれを使用
- tflite→kmodel変換可能レイヤ
- kerasのPaddingについて: kerasのデフォルトパディング形式はkmodel変換できない
- 日本語記事
##エッジデバイス開発
###UnitV
基本的に公式のクイックスタートに則って準備します。
ファームウェア(※後に自作モデルを動かす為に別のパッケージを焼くことになるので,動作確認目的以外では不要です)はEasyLoaderをダウンロードし焼きます。
IDEはMaixyPy IDEを使用しました。
コード全体はページ最下部の付録に載せています。
全体の大まかな流れは以下の通りです。
- UART, KPU, sensor系の初期化
- 画像の撮影
- モデルへの画像入力と検出情報の出力
- トラッカーへ検出情報の入力,前フレームとの差異情報の出力
- カウンタへ差異情報の入力,条件に応じてカウント情報を更新
- Grayへカウント情報と現フレームの検出数を送信,2.へ戻る
-
kmodel
のロード
ベースはaXeleRateのコードです.
####KPU初期化
def init_kpu(threshold=0.3):
classes = ["person"]
task = kpu.load(0x300000) #change to "/sd/name_of_the_model_file.kmodel" if loading from SD card
a = kpu.set_outputs(task, 0, 7,7, 30) #the actual shape needs to match the last layer shape of your model(before Reshape)
anchor = (0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, 9.77052, 9.16828)
a = kpu.init_yolo2(task, threshold, 0.3, 5, anchor) #tweak the second parameter if you're getting too many false positives
return task
`kpu.load()`
`anchor`
`kpu.init_yolo2()`
####UART制御
def init_uart():
fm.register(35, fm.fpioa.UART1_TX, force=True)
fm.register(34, fm.fpioa.UART1_RX, force=True)
uart = UART(UART.UART1, 115200,8,0,0, timeout=1000, read_buf_len=4096)
return uart
`fm.register()`
`UART()`
トラッキング及びカウンタ
###M5Stack Gray(+COM.X)
M5 Stack Grayの開発環境としてArudinoがメジャーですが、micropythonを使用する為UIflowを使用します。
こちらもクイックスタートに則って準備します。
同じmicropythonベースですが、UnitVとモジュールが色々異なる点に注意が必要です(UnitV側はMaixpy: micropython to k210)
M5 Stack micropython
全体の大まかな流れは以下の通りです.
- UART、アイコン生成部の初期化
- UnitVからの信号を待つ
- 信号を受信したら,カウント数と検出数を画面に描画し,Sigfox通信
- 2に戻る
## UnitV
VTX, VRX = (22, 21)
## Sig
STX, SRX = (17, 16)
def uart_init():
# Sigfox
uart1 = UART(1, tx=STX, rx=SRX)
uart1.init(9600, bits=8, parity=None, stop=1)
# UnitV
uart2 = UART(2, tx=VTX, rx=VRX)
uart2.init(115200, bits=8, parity=None, stop=1)
return uart1, uart2
##デプロイ
####UnitV
AI開発部分で作ったモデルを動かす為に,kfpkg
パッケージを作成し焼いていきます。
参考:https://maixpy.sipeed.com/en/get_started/upgrade_firmware.html
-
ファームウェア
maixpy_v0.5.0_42_g458ed4e_m5stickv.bin
をダウンロード
https://dl.sipeed.com/MAIX/MaixPy/release/master/maixpy_v0.5.0_42_g458ed4e -
ベースとなるパッケージをダウンロード
https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/M5StickV_Firmware_v5.1.2.kfpkg -
M5StickV_Firmware_v5.1.2.kfpkg
をM5StickV_Firmware_v5.1.2.zip
とリネームし展開 -
maixypy.bin
をmaixpy_v0.5.0_42_g458ed4e_m5stickv.bin
に,facedetect.kmodel
を自作モデル(ここではmy_model.kmodel
)に置き換え -
中にある
flash-list.json
を以下のように書き換え
{
"version": "0.1.0",
"files": [
{
"address": 0x00000000,
"bin": "maixpy_v0.5.0_42_g458ed4e_m5stickv.bin",
"sha256Prefix": true
},
{
"address": 0x00D00000,
"bin": "m5stickv_resources.img",
"sha256Prefix": false
},
{
"address": 0x00300000,
"bin": "my_model.kmodel",
"sha256Prefix": false
}
]
}
-
4つのファイルをzipにまとめ,拡張子をkfpkgへと戻す
-
パッケージの書き込み
参考:https://github.com/kendryte/kflash.py
kflashをインストールしUnitVに書き込みます.筆者はAnaconda環境にインストールしました。
conda create -n kflash python=3.6
conda activate kflash
pip install kflash
kflash my_kfpkg.kfpkg
- コードの書き込み
IDE上のコードをブートコードとして書き込みます.
この時点で,電源を接続すると動くようになっています.(Grayに接続しないと動きは見えませんが..)
####M5Stack Gray
UnitV同様,IDEからコードを書きこみます。
※表示がダウンロード(誤訳?)になっていることに注意
この時点で,こちらも電源を接続すると動くようになっています。
#動作確認
####UnitV
検出の様子をIDEのデバッガで表示したものです。
「2人の人物が左からやってきて,立ち止まった後,右に抜けていく」というシナリオです。
矩形:人物検出領域
赤の数字:トラッカーによって振られたID
緑の数字:カウント
####M5Stack Gray(+COM.X)
動作画面です。
画面上部の緑の数字が人数を、それに合わせ人型のアイコンを表示しています。定期的に計測した人数をSigfox通信で送信しています。
####ダッシュボード
人流カウントをダッシュボードで確認する事ができます
ある展示会での人流を計測したもので、凡そ、どの時間帯で来場者が多いかが見て取れるかと思います。
#付録
それぞれのデバイスで使用したコードの全体とモデルを置いておきます。
https://github.com/kccsairc/Edge_AIoT