【Pythonコード公開】留守でも安心！異常検知システムを自作してみた（前編）【機械学習】

来週、久しぶりの出張で家を留守にする予定なので、我が家の防犯が心配！
そこで、侵入者を検知する異常検知システムを作ってみました＆Pythonコードも公開します！
侵入者検知以外にも、**「駐車場の空き状況の検知」「立ち入り禁止区域の監視」などの用途にも使える** （かもしれない）システムです。

**作成した異常検知システムのGUI：**
![Umapyoi異常検知アプリイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/416d7e01-57ca-1635-5511-63736ced84cb.png)


# 異常検知システム概要
玄関（靴箱の上）に設置したカメラ映像を監視し、異常（侵入者など）があったら、自動で検知してメールで通知してくれるシステムです！
留守中にメールが来るかドキドキですね！

カメラ映像が正常か異常か判定するのは、異常検知モデルです。
人がいない状態の画像を学習データとして利用することで、人影や身体の一部が映った場合に異常と判定する異常検知モデルを作成することができます。

今回は、コーディング無しで簡単に異常検知モデルを作成できる[ADFI](https://adfi.jp/ja)というプラットフォームを利用しました。
ADFIについては、[過去記事で詳しく解説](https://qiita.com/umapyoi/items/ddd45a47aa79ccbde28b)していますので参照ください。

https://qiita.com/umapyoi/items/ddd45a47aa79ccbde28b

**概要図：**
![概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/b81f600e-250c-74a2-ac6a-542fae48395c.png)

# システム構成
下の図の通り、Pythonプログラムが２つ（camera.py、app.py）の非常にシンプルな構成です。
カメラ内蔵のノートPCが１台あれば誰でも構築できます。

![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2535236/463ea307-a1b5-eff6-d446-a2ddc083cf1a.png)

## camera.pyの処理
玄関に設置したカメラ（ノートPCに内蔵のカメラでも可）から、定期的に画像を取得し、「処理対象フォルダ」に保存します。

## app.pyの処理
定期的に「処理対象フォルダ」内をチェックし、画像があった場合、異常検知モデルに画像を送信します。
異常検知モデルの検知結果を受け取り、GUIに表示します。（必要に応じて、異常だった場合メール送信処理などを行う。）
送信済みの画像は、「処理対象フォルダ」から「処理済みフォルダ」に移動させます。

# システム作成手順（前編）
## camera.pyの作成
まずは、カメラから定期的に画像を取得して、フォルダに保存するプログラム（camera.py）を作成します。
完成コードは下記の通りです。

```
import cv2
import datetime
import os

# カメラ映像から画像を取得
def save_camera_image(device_num, dir_path, basename, cycle=-1, ext='png', delay=1, window_name='camera'):
    cap = cv2.VideoCapture(device_num)

    if not cap.isOpened():
        return

    os.makedirs(dir_path, exist_ok=True)
    base_path = os.path.join(dir_path, basename)

    n = 0
    c = 0
    while True:
        ret, frame = cap.read()
        cv2.imshow(window_name, frame)
        key = cv2.waitKey(delay) & 0xFF
        # キーボードのqを押すと終了
        if key == ord('q'):
            break
        # キーボードのcを押すと手動で画像を取得
        if key == ord('c'):
            img_path = '{}_{}.{}'.format(base_path, c, ext)
            cv2.imwrite(img_path, frame)
            print(img_path)
            c += 1
        # cycleを指定している場合は、定期的に画像を自動保存
        if n == cycle:
            n = 0
            img_path = '{}_{}.{}'.format(base_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S%f'), ext)
            cv2.imwrite(img_path, frame)
            print(img_path)
        n += 1

    cv2.destroyWindow(window_name)

# main
def main():
    save_dir = 'camera'
    save_camera_image(0, save_dir, 'camera_capture', 500)
    
if __name__ == '__main__':
    main()
```
上記コードを実行するには、OpenCVのライブラリが必要です。
もしインストールしてなかった場合は、下記コマンドでインストールしてください。
```
pip install opencv-python
```
このプログラムでは、実行中にキーボードの「c」を押すと、手動で画像を保存できます。
また、「q」を押すと、プログラムを終了できます。

なお、画像を取得するカメラは「save_camera_image」の「device_num」で設定できます。

## 学習データを収集
camera.pyが上手く動くことを確認したら、次は、異常検知モデル作成のための学習データの収集です。
カメラの設置場所を決めて、位置を固定してください。

固定が完了したら、camera.pyを実行して、正常な状態（人が映っていない状態）の画像を数十枚保存してください。

# 後編につづく
[後編](https://qiita.com/umapyoi/items/31fd018aaee02a61699d)では、いよいよ異常検知モデルとGUIを作成します。

https://qiita.com/umapyoi/items/31fd018aaee02a61699d

# 関連記事

https://qiita.com/umapyoi/items/ddd45a47aa79ccbde28b

https://qiita.com/umapyoi/items/aa7c829b4591653f1b50

https://qiita.com/umapyoi/items/ec64142dd3c70e90a9dc

https://qiita.com/umapyoi/items/5a0e21338c64fc7c44e2