AITRIOSで外部ストレージ(Local Storage)連携を使ってみた

ソニーセミコンダクタソリューションズの大橋です。

AITRIOSの推論時に得られる画像と推論結果メタデータは、保存場所を変更することができます。
[こちら](https://qiita.com/SSS-KenshiroOohashi/items/62c0d6642a5f27d944ea)の記事ではAzureのBlob Storageを用いた方法を紹介しましたが、今回はLocalのhttpサーバ上に保存する方法について解説します。

## はじめに
初期設定では、AITRIOSで推論を実行するとConsoleのCheck dataで画像と推論結果メタデータを確認することができます。しかし、以下のような点に不満を持つ場合もあるかもしれません。

- 推論結果メタデータは2週間で自動削除されてしまう
- 画像や推論結果メタデータをローカルにダウンロードするのが面倒(APIが用意されているが手間がかかる)
  
また、大量の画像や推論結果メタデータを取得する場合はAPIコール数が増加してしまうため、外部ストレージの使用が推奨されています。
[こちら](https://qiita.com/SSS-KenshiroOohashi/items/62c0d6642a5f27d944ea)の記事では画像や推論結果メタデータをAzureのBlob Storageに保存しましたが、本記事ではローカル環境にhttpサーバをたて、そこに保存する方法について解説します。

本記事はAITRIOSの[外部転送設定チュートリアル (HTTP Server)](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/external-transfer-settings-tutorial-for-http-server/)をもとに作成していますが、httpサーバーとしてWindowsOSではなくRaspberry Pi OSを使用しました。

## 注意点
- 本機能はhttp通信となるため、セキュアな環境内で実施してください。後述のとおり、保存先のサーバーはエッジデバイスと同一ネットワーク上にあることが前提です。
 
　また、本記事ではAITRIOS Developer Editionを利用しています。

## 前提
本記事では、以下の環境構築ができていること、知識があることを前提にしています。
- AIモデルやEdgeAppがエッジデバイスに適切にデプロイされており、推論を実行するとConsoleのCheck dataで画像と推論結果メタデータを確認できること
- httpサーバを構築するRaspberry Piを、エッジデバイスと同一ネットワーク上に接続できること
- Raspberry Pi のターミナルから python3 環境がさわれること

## 保存先となるhttpサーバを構築する
まずは保存先となるhttpサーバの設定をします。ここではpythonのWebフレームワークであるfastapiと、python用のASGI Webサーバー実装([Uvicornのサイト](https://www.uvicorn.org/)の直訳)であるUvicornを利用します。詳細は省略しますが、簡単にhttpサーバを立ち上げることができます。

本記事ではfastapiのインストール先としてRaspberry Pi OSを使用します。
```
$pip install fastapi
```
さっそく実行してみます。

実行結果

![fastapi失敗.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/4201cc6a-1b52-2fb8-09e6-917f322ad691.jpeg)


筆者の環境ではエラーになりました。PEP 668を参照せよというメッセージですが本記事の本質ではないので省略します。ここではlocal_pythonという名前の仮想環境を作って再度インストールを試みます。
```
$python3 -m venv local_python
$cd local_python
$source ./bin/activate
$pip install fastapi
```
実行結果

![fastapi成功.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/508a511e-9803-24a1-4768-5aa33c53eefc.jpeg)


今度はうまくインストールが開始されました。インストールが完了したら続けてuvicornもインストールします。
```
$pip install uvicorn
```
次に画像と推論結果メタデータの保存先ディレクトリを作成しておきます。
ここではホームディレクトリ上にserverディレクトリを作成し、その直下に画像保存用のimageディレクトリと推論結果メタデータ保存用のmetaディレクトリを作成します。
```
$cd
$mkdir server
$cd server
$mkdir image
$mkdir meta
```
最後にサンプルコード(webapp.py)をserverディレクトリに保存します。こちらのサンプルコードは[外部転送設定チュートリアル (HTTP Server)](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/external-transfer-settings-tutorial-for-http-server/)に掲載されているもので、画像と推論結果の保存を行います。

***webapp.py***
```python
from fastapi import FastAPI, Request, status
import os.path
import traceback
import logging

SAVE_PATH_IMG = './image'
SAVE_PATH_META = './meta'

app_ins = FastAPI()
# Log format
log_format = '%(asctime)s - %(message)s'
# Set log level to INFO
logging.basicConfig(format=log_format, level=logging.INFO)

def save_file(file_type, content, filename):
        file_path = os.path.join(file_type, filename)
        with open(file_path, 'wb') as w_fp:
                w_fp.write(content)


@app_ins.put("/meta/{filename}")
async def update_items(filename, request: Request):
        try:
                content = await request.body()
                os.makedirs(SAVE_PATH_META, exist_ok=True)
                save_file(SAVE_PATH_META, content, filename)
                logging.info("Meta File Saved: %s", filename)
                return {"status":status.HTTP_200_OK}
        except (Exception):
                traceback.print_exc()


@app_ins.put("/image/{filename}")
async def update_items(filename, request: Request):
        try:
                content = await request.body()
                os.makedirs(SAVE_PATH_IMG, exist_ok=True)
                save_file(SAVE_PATH_IMG, content, filename)
                logging.info("Image File Saved: %s", filename)
                return {"status":status.HTTP_200_OK}
        except (Exception):
                traceback.print_exc()
```

## 画像、推論結果メタデータ出力先を変更する
まず、Command Parameterの設定を変更します。保存先のhttpサーバのIPアドレスを確認しておきます。Raspberry Pi OS上で以下コマンドを実行します。
IPアドレス確認
```
$ifconfig
```

実行結果

![IPアドレス.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/670ba0ab-f7ad-f880-a37f-66a7e7928632.jpeg)


ここではIPアドレスが192.168.0.50でしたので、Command ParameterのStorageName、StorageNameIRに設定します。筆者環境の都合上今回はDHCPでIPアドレスを取得していますが、実運用に際しては固定IPにしておく方が良いでしょう。以下はAITRIOSのCreate Modelで、Object DetectionのAIモデルを作成した場合のCommand Parameter設定例です。

なお、Command Parameterの書き方の詳細については[Consoleユーザーマニュアル](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/documents/console-user-manual/?progLang=#_command_parameter)をご参照ください。
```
{
    "commands": [
        {
            "command_name": "StartUploadInferenceData",
            "parameters": {
                "ModelId": "ModelID", #お使いのModelIDに変更してください
                "Mode": 1,
                "UploadMethod": "HTTPStorage",
                "StorageName": "http://192.168.0.50:8080",
                "StorageSubDirectoryPath": "/image",
                "FileFormat": "JPG",
                "UploadMethodIR": "HTTPStorage",
                "StorageNameIR": "http://192.168.0.50:8080",
				        "StorageSubDirectoryPathIR": "/meta",
                "PPLParameter": {
                    "header": {
                        "id": "00",
                        "version": "01.01.00"
                    },
                    "dnn_output_detections": 64,
                    "max_detections": 5,
                    "threshold": 0.6,
                    "input_width": 320,
                    "input_height": 320
                },
                "NumberOfImages": 0,
                "UploadInterval": 1,
                "NumberOfInferencesPerMessage": 1
            }
        }
    ]
}
```



## HTTP Server起動と推論実行
準備ができたらHTTP Serverを起動します。IPアドレスはお使いの環境に合わせて変更してください。
```
$cd server
$uvicorn webapp:app_ins --reload --host 192.168.0.50 --port 8080 --no-access-log
```
HTTP Serverが起動できたらAITRIOSのConsoleでGet Inference DataトグルをONにし、推論を開始します。

実行結果

![uvicorn実行.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/1aded53c-893b-02e3-b27b-dc76e5e9b192.jpeg)

上記のように"Image File Saved"や"Meta File Saved"というログが出力されていればOKです。保存先ディレクトリも確認してみましょう。

保存結果

![画像保存.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/de580e95-8744-1934-4c06-2f5d84cf8d16.jpeg)

![推論結果保存.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724906/89465d9f-bd62-a254-cb90-ebf94200aefb.jpeg)

画像と推論結果がhttpサーバに保存されています。用途に合わせてwebapp.pyを修正・開発していくことになります。

## 出力先を元に戻す
[AzureのBlobストレージへの保存](https://qiita.com/SSS-KenshiroOohashi/items/62c0d6642a5f27d944ea)とは違い、AITRIOSのプロジェクトに対する変更はしていませんので、エッジデバイスに設定しているCommand Parameterの設定を戻すだけで、再びAITRIOS ConsoleのCheck Dataで画像と推論結果メタデータを確認することができるようになります。

## おわりに
今回は推論時の画像と推論結果メタデータをローカル環境に立てたhttpサーバに保存する方法について解説しました。推論結果メタデータについては、AITRIOS Consoleでは2週間で消えてしまいます。定期的に取得して保存しておいたり、[AzureのBlobストレージへの保存](https://qiita.com/SSS-KenshiroOohashi/items/62c0d6642a5f27d944ea)や今回紹介したhttpサーバへの保存方法など、用途に合わせて検討してみてください。

# 困った時は

もし、記事の途中でうまくいかなかった場合は、気軽にこの記事にコメントいただいたり、以下のサポートのページもご覧ください。  
コメントのお返事にはお時間を頂く可能性もありますがご了承ください。

- [Support (FAQ)](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/support)

また、記事の内容以外で AITRIOS についてお困りごとなどあれば以下よりお問い合わせください。
- [Contact Us](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/contact-us)