Raspberry Pi AI Cameraでプライバシーマスク付与してみた

<!-----------------
記事本文は下記レビュー観点を意識したうえで、自由に記載してください。 
 - [ ] 非公開情報はないか
 - [ ] 社内用語が使われていないか
 - [ ] 共通ワーディングを利用しているか
 - [ ] 技術的間違いがないか
 - [ ] リンク切れを起こしていないか
 - [ ] 政治、宗教等センシティブな領域に言及していないか (CATOPE対応)
 - [ ] 文体の統一/誤字チェック（JustRight対応）
 - [ ] その他不適切な表現・内容が含まれていないか
 - [ ]  問い合わせに関する文言を記載しているか  　
------------------->  
# はじめに 
ソニーセミコンダクタソリューションズ株式会社 の小山と申します。

先日、Raspberry Pi財団が、弊社のAI処理機能搭載イメージセンサを採用した「Raspberry Pi AI Camera」を発売しました！  
この度、本カメラモジュールを活用し、プライバシーマスクを付与するアプリケーション開発しました。

本記事では、Raspberry Pi AI Cameraのセットアップから、アプリケーション開発までの一連の流れについて紹介します！

# 本記事の要約：
- Raspberry Pi AI Cameraを使うとプライバシーマスク付与が簡単にできます
- Raspberry Pi AI Cameraを使ったアプリ開発の一連の流れを説明します

# 本文

## 0. 今回の作業の流れ
本記事では、以下の手順でプライバシーマスク付与アプリケーションの開発を進めていきます。  
なお、GitやPythonの基本的な知識は必要ですが、AIに関する専門知識は不要です。

    1. Raspberry Pi AI Cameraのセットアップ
    2. Application Module Libraryを活用した物体検出サンプルの実行
    3. 検出した人に対してプライバシーマスクの付与
    4. アプリケーション動作例

## 1. Raspberry Pi AI Cameraのセットアップ
まずはRaspberry Pi AI Cameraのセットアップになります。  
具体的な手順の説明については省略致しますが、[こちらの記事](https://qiita.com/daiki0321/items/4223611adb453d6c7aa2)に詳細に記載されていますので、参考にしてみてください。  
2章の最後まで終わっていれば、こちらの記事でのセットアップは完了です。

## 2. Application Module Libraryを活用した物体検出サンプルの実行
セットアップが完了したら、Application Module Libraryを利用して、物体検出モデルをRaspberry Pi AI Cameraで動かしてみます！ 

### Application Module Libraryとは
[Application Module Library](https://github.com/SonySemiconductorSolutions/aitrios-rpi-application-module-library) とは、IMX500向けのアプリケーション開発を簡単かつ効率的に行うためのSDKです。 
### Application Module Libraryのセットアップ
1. git cloneコマンドからApplication Module Libraryのレポジトリをコピー  

    ```bash
    git clone https://github.com/SonySemiconductorSolutions/aitrios-rpi-application-module-library.git
    ```

2. 開発環境のセットアップ
    ```bash
    make setup
    ```

3. ソフトウェアアップデートとカメラ動作に必要なモジュールのインストール
    ```bash
    sudo apt update && sudo apt full-upgrade
    sudo apt install imx500-all
    sudo apt install python3-opencv python3-munkres python3-picamera2
    ```

4. 仮想環境作成とApplication Module Libraryのインストール
    ```bash
    python -m venv .venv --system-site-packages
    . .venv/bin/activate
    pip install modlib-<version>-py3-none-any.whl
    ```

### 物体検出サンプルの実行
配布されている物体検出用のサンプルコード（aitrios-rpi-application-module-library/example/aicam/detector.py）を実行します。    

コードの主な内容としては、以下となります。 
1. 使用するAIモデルの選択
2. カメラへAIモデルのデプロイ
3. カメラからのフレームを取得
4. 検出した物体を示すボックスとラベルをフレーム上に描画
5. 処理結果をリアルタイムで画面に表示  

この短いコードで物体検出を簡単に動かすことが可能となっています！

```python
from modlib.apps import Annotator
from modlib.devices import AiCamera
from modlib.models.zoo import SSDMobileNetV2FPNLite320x320

device = AiCamera()
model = SSDMobileNetV2FPNLite320x320()
device.deploy(model)

annotator = Annotator(thickness=1, text_thickness=1, text_scale=0.4)

with device as stream:
    for frame in stream:
        detections = frame.detections[frame.detections.confidence > 0.55]
        labels = [f"{model.labels[class_id]}: {score:0.2f}" for _, score, class_id, _ in detections]

        annotator.annotate_boxes(frame, detections, labels=labels)
        frame.display()
```

## 3. 検出した人に対してプライバシーマスクの付与
先ほど使用したサンプルコードを改変し、人に対して、プライバシーマスクの付与する機能を実装します。
### 物体検出から人のみを検出するよう設定
今回検出したい対象は人であるため、人のみを検出するようにコードを変更します。  
detectionsの属性としてclass_idが用意されています。こちらのIDから検知対象を人に制限していきます。  
今回使用する"SSDMobileNetV2FPNLite"モデルでは、class_ID：0が人となっています。
```python
detections = frame.detections[(frame.detections.confidence > CONFIDENCE_THRESHOLD) & (frame.detections.class_id == 0)]
```

### 検出した人エリアに対してモザイク処理の適用
今回は、OpenCVを使って実装を行いました。  
モザイク処理は、画像を一度縮小してから拡大して、元のサイズに戻すことで実装可能です。  
cv2.resizeを使い、第1引数で指定した画像を第2引数で指定したサイズに縮小/拡大することができます。  
第一引数には、検出した人エリアのフレームを入力します。  
またモザイク処理の強さは、縮小の比率で変更することが可能です。  
下記のコード内で定義している"MOSAIC_SCALE"をより小さくするとモザイク処理が強くなり、大きくするとモザイク処理が弱くなります。用途に合わせて、調整してみてください。
```python
MOSAIC_SCALE = 0.1

for box, score, _, _ in detections:
    x1, y1, x2, y2 = box
            
    x1, y1, x2, y2 = int(x1 *w), int(y1 *h), int(x2 *w), int(y2 *h)

    mosaic_w = x2 - x1 
    mosaic_h = y2 - y1
    
    roi = frame_data[y1:y2, x1:x2]

    #縮小
    small_roi = cv2.resize(roi, (int(mosaic_w*MOSAIC_SCALE), int(mosaic_h*MOSAIC_SCALE)), interpolation=cv2.INTER_LINEAR)
        
    #拡大
    mosaic_roi = cv2.resize(small_roi, (mosaic_w,mosaic_h), interpolation = cv2.INTER_NEAREST)
```


### 完成コード
今回開発したプライバシーマスク付与アプリのコード例になります。 

全体の流れとしては、以下の通りです。
1. 使用するAIモデルの選択
2. カメラへAIモデルのデプロイ
3. カメラからのフレームを取得
4. 物体検出による人検出
5. 人検出エリアに対してモザイク処理
6. モザイク処理した映像を表示

```python
from modlib.apps import Annotator
from modlib.devices import AiCamera
from modlib.models.zoo import SSDMobileNetV2FPNLite320x320
import cv2

#Constants definition
PERSON_CLASS_ID = 0 
MOSAIC_SCALE = 0.1
CONFIDENCE_THRESHOLD = 0.5

#Person detection using modlib
def detection(frame, model):
    detections = frame.detections[(frame.detections.confidence > CONFIDENCE_THRESHOLD) & (frame.detections.class_id == PERSON_CLASS_ID)]
    labels = [f"{model.labels[class_id]}: {score:0.2f}" for _, score, class_id, _ in detections]

    return detections, labels

#Apply mosaic to detected person areas
def apply_privacymask(frame_data, detections):
    h, w, _ = frame_data.shape

    for box, score, _, _ in detections:
        x1, y1, x2, y2 = box
        x1, y1, x2, y2 = int(x1 *w), int(y1 *h), int(x2 *w), int(y2 *h)

        mosaic_w = x2 - x1 
        mosaic_h = y2 - y1
        
        roi = frame_data[y1:y2, x1:x2]

        #Apply mosaic by reducing and enlarging the image
        small_roi = cv2.resize(roi, (int(mosaic_w *MOSAIC_SCALE), int(mosaic_h *MOSAIC_SCALE)), interpolation=cv2.INTER_LINEAR)
        mosaic_roi = cv2.resize(small_roi, (mosaic_w,mosaic_h), interpolation = cv2.INTER_NEAREST)

        frame_data[y1:y2, x1:x2] = mosaic_roi

    return frame_data

#Execute person detection, mosaic processing, label drawing and display for each frame
def process_frame(frame, model, annotator):
    frame_data = frame.image

    #Person detection
    detections, labels  = detection(frame, model)

    #Apply mosaic
    frame_data = apply_privacymask(frame_data, detections)
    frame.image = frame_data        

    #Draw
    annotator.annotate_boxes(frame, detections, labels)
    frame.display()

def main():
    device = AiCamera() #Select device
    model = SSDMobileNetV2FPNLite320x320() #Select model
    device.deploy(model) #Deploy to IMX500

    #Innitialize annotator to display inference result
    annotator = Annotator(thickness=1, text_thickness=1, text_scale=0.4)

    #Start inference
    with device as stream:
        for frame in stream:
            process_frame(frame, model, annotator)

if __name__ == "__main__":
    main()
```
## 4. アプリケーション動作例
物体検出による人検知を活用し、人に対してプライバシーマスクを付与することで、映像出力時のプライバシー保護が実現できました！  
![PrivacyMask_Result.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993343/a30bf3bc-9dd4-49aa-be7b-764e8641ab90.gif)


## 終わりに
Raspberry Pi AI Cameraを初めて触って数日で実装することができました。  
このようにRaspberry Pi AI Cameraを用いることで簡単にAIを活用したアプリケーションの開発が可能となっています！  

ぜひ皆さんもRaspberry Pi AI Cameraを活用したアプリケーション開発を行い、体感してみてください！  

また、最後まで記事をお読みいただきありがとうございました！


# 困った時は

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

<!-----------------RasPiのみに関連する記事の場合、下記のAITRiOSサポートへの誘導は記載しないでください。------------------->  
- [Support (FAQ)](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/support)

<!-----------------RasPiのみに関連する記事の場合、下記のAITRiOSサポートへの誘導は記載しないでください。------------------->  
また、記事の内容以外で AITRIOS についてお困りごとなどあれば以下よりお問い合わせください。
- [Contact Us](https://developer.aitrios.sony-semicon.com/edge-ai-sensing/contact-us)

<!-----------------RasPiに関する記事が含まれる場合は下記を追加してください。------------------->  
RaspberryPiに関連する疑問がある場合は、下記フォーラムをご確認、ご活用ください。
- [Raspberry Pi Forums](https://forums.raspberrypi.com/)