UnitV高速化の術 その1

# はじめに
M5Stack社のUnitV AI Cameraの高速化の方法について調べていたところ、意外とこういう系の記事がなかったので自分で書いてみることにしました。
まずは、簡単にできる高速化の方法から紹介していきます。

# 環境
デバイス: [UnitV AI Camera (OV7740版)](https://docs.m5stack.com/en/unit/unitv_ov7740)
開発環境: [MaixPy](https://wiki.sipeed.com/soft/maixpy/en/index.html)

# ダブルバッファリング
### ダブルバッファリングとは
通常、カメラからの画像データを処理するとき、1つのバッファを使用して撮影と処理を順番に行います。しかし、ダブブルバッファリングを有効にすると、2つのバッファ（メモリ領域）を交互に使用して、撮影と処理を同時に行います。メモリ使用量は増加しますが、代わりにパフォーマンスを向上させることができます。

### ダブルバッファリングの有効化
カメラ初期化の際に```dual_buff=True```と指定することで、ダブルバッファリングを有効にすることができます。
```Python
sensor.reset(dual_buff=True)
```
### FPSの比較
色検出のプログラムを動かして、ダブルバッファリングを有効/無効にした状態で、FPS（フレームレート）がどれだけ変化するか比較してみます。
```Python
import sensor
import image
import time

sensor.reset(dual_buff=False)       # ダブルバッファリング無効
#sensor.reset(dual_buff=True)       # ダブルバッファリング有効
sensor.set_pixformat(sensor.RGB565) # RGB565フォーマットを使用
sensor.set_framesize(sensor.QVGA)   # QVGA(320x240)フレームサイズを使用
sensor.set_auto_gain(False)         # オートゲインをオフ
sensor.skip_frames(time = 2000)     # 2秒間フレームをスキップして安定化

threshold = [(30, 100,  15, 127,  15, 127)] # 検出する色のしきい値を設定

clock = time.clock()

while(True):
    fps_list = []
    for i in range(100):
        clock.tick()
        img = sensor.snapshot()           # 画像を取得
        blobs = img.find_blobs(threshold) # しきい値内の色を検出
        if blobs:
            max_blob = max(blobs, key=lambda b: b.area()) # 面積が最大の領域を取得
            img.draw_rectangle(max_blob[0:4])             # 検出した色を矩形で囲む
            img.draw_cross(max_blob[5], max_blob[6])      # 検出した色の中心に十字を描く
        fps_list.append(clock.fps())
    print(sum(fps_list) / len(fps_list))
```

### 計測結果
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526610/d8ab7e4b-6cf9-6f9e-c39d-6b0fe21f29bb.png)



# 低画質化
### 画質の設定
下記の関数を使うことで画質の設定ができます。
```python
sensor.set_framesize(sensor.QVGA)   # QVGA(320x240)フレームサイズを使用
```
フレームサイズには
```python
sensor.QQQQVGA # 40x30
sensor.QQQVGA  # 80x60
sensor.QQVGA   # 160x120
sensor.QVGA    # 320x240
sensor.VGA     # 640x480
```
などが設定できますが、UnitVではQQQVGA以下は対応していません（2023/11/16現在）。ファームウェアを書き換えることで、QQQVGA以下も使えるようになるのですが、これは別の記事で解説する予定です。

### FPSの比較
色検出のプログラムを動かして、QVGAとQQVGAでFPS（フレームレート）がどれだけ変化するか比較してみます。ダブルバッファリングは無効にしています。
```Python
import sensor
import image
import time

sensor.reset(dual_buff=False)       # ダブルバッファリング無効
sensor.set_pixformat(sensor.RGB565) # RGB565フォーマットを使用
sensor.set_framesize(sensor.QVGA)   # QVGA(320x240)フレームサイズを使用
#sensor.set_framesize(sensor.QQVGA) # QQVGA(160x120)フレームサイズを使用
sensor.set_auto_gain(False)         # オートゲインをオフ
sensor.skip_frames(time = 2000)     # 2秒間フレームをスキップして安定化

threshold = [(30, 100,  15, 127,  15, 127)] # 検出する色のしきい値を設定

clock = time.clock()

while(True):
    fps_list = []
    for i in range(100):
        clock.tick()
        img = sensor.snapshot()           # 画像を取得
        blobs = img.find_blobs(threshold) # しきい値内の色を検出
        if blobs:
            max_blob = max(blobs, key=lambda b: b.area()) # 面積が最大の領域を取得
            img.draw_rectangle(max_blob[0:4])             # 検出した色を矩形で囲む
            img.draw_cross(max_blob[5], max_blob[6])      # 検出した色の中心に十字を描く
        fps_list.append(clock.fps())
    print(sum(fps_list) / len(fps_list))
```
### 計測結果
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526610/5c1f40ec-4a18-eb1f-7ecf-07a5bf3bf1bf.png)

# まとめ
最終的に、ダブルバッファリングを有効にして画質をQQVGAに落とすことで、素の状態と比べて3倍近く速くすることができました。ただし、処理によっては精度が落ちたり、メモリが不足する可能性があるため、適宜調整を行ってください。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526610/5ed5892a-9641-64fd-206e-952d60929177.png)

# 参考資料
- [MaixPy公式ドキュメント](https://wiki.sipeed.com/soft/maixpy/en/api_reference/machine_vision/sensor.html)
- [OpenMV公式ドキュメント](https://docs.openmv.io/library/omv.sensor.html)