ソラカメ + Lobe + AWS Lambda + Tensorflow Lite で鍵の閉め忘れを検知する

## 2022-12-19 追記

- この活動について SORACOM UG Online で発表した内容もリンクしておきます。後述しますが、精度の向上にも成功しました。

https://speakerdeck.com/soracom/detect-locking-the-door-using-sora-cam-lobe-aws-lambda-tensorflow-lite

- [SORACOM Advent Calendar 2022](https://qiita.com/advent-calendar/2022/soracom) の 19 日目の記事で、Azure を使った方法が紹介されました！

https://zenn.dev/showm001/articles/2022-12-19-01

## 作成のきっかけ

師走になるといろいろと慌ただしくなり、普段しないようなうっかりミスも出てきます。私は特にうっかりミスが多い方で、布団の取り込み忘れ・風呂の栓の閉め忘れ・電気の消し忘れなど、困りごとは多岐にわたります。これらはまだ良いのですが、一番怖いのはやはり玄関の鍵の閉め忘れです。最近は後付けのオートロックも出てきているのですが、なんとなく買うのを後回しにしていたところ、何度か閉め忘れが発生し、妻からひどく怒られてしまいました (ごめんなさい)。

そんな矢先に、クラウドカメラサービスのソラカメに静止画エクスポートの API が出てきました。丁度アドベントカレンダーのネタも探していたので、これを機に画像認識を勉強してみようと思いました。

## 成果物

以下のように LINE Notify でドアの開閉と画像を送信できました。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/9794d2c1-fb8d-3112-272f-a88ecdb193e1.png">

コードや利用方法は以下の GitHub リポジトリに置いてあります。

https://github.com/nmikuni/door-key-open-detector

## 構成

最近仕事では AWS を使うことが多いので、AWS を使うことにしました。簡単に調べてみたところ、画像認識 (推論) の方法としては大きく 2 つの構成が取れることが分かりました。

1. マネージドな画像認識サービスの Amazon Rekognition を使う
2. Amazon EC2・Amazon ECS・AWS Lambda などのコンピューティングリソースを使う

料金を調べたところ、Amazon Rekognition のカスタムラベルで推論するには 2022 年 12 月 10 日現在で 4 USD / 時間の費用が掛かることが分かったので、[2] の方針を取ることにしました。開閉確認するにしても数分に 1 回程度だろうという見込みで、できれば AWS Lambda を使いたいなと考えました。

https://aws.amazon.com/jp/rekognition/pricing/

※ちなみにこのブログでは詳細を割愛しますが、Amazon Rekognition も使ってみました。Amazon SageMaker Ground Truth と組み合わせることで簡単にラベリング・トレーニング・推論ができたのはすごく良かったです。また後半で少し触れますが、SageMaker Ground Truth では Boundng box を使ってラベリングができたのでモデルの精度も非常に良かったと感じました。いつかまた使いたいです。

最終的には、以下のような構成にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/5c4890e2-f9ec-ab46-5f18-3de3a771b74e.png)

1. Amazon EventBridge で定期的に AWS Lambda を呼び出す
2. ソラカメ API で静止画像をエクスポート
3. 静止画像を別の AWS Lambda で推論
4. 推論した結果を LINE Notify で通知

また、ラベリングとトレーニングには Lobe を用いて、Tensorflow Lite 形式でエクスポートしました。AWS Lambda に Tensorflow Lite のモデルを読み込ませています。

https://www.lobe.ai/

プログラムの詳細は前述の GitHub リポジトリを読んでもらえればと思いますが、ここでは良かったことと難しかったことを紹介していきます。

## 良かったこと 1: Lobe の手軽さ

Lobe については 2020 年のリリースの時から存在は知っていたのですが、画像認識自体に手を出すきっかけがなかったので触れていませんでした。ですが、ラベリングとトレーニングが簡単にできて、サンプルプログラム付きのモデルをエクスポートできる手軽さには感動しました。私の記事ではないのですが、この感動についてわかりやすい記事がこちらになりますので紹介します。

https://qiita.com/ma2shita/items/f5c4ecd79e44ba41065f

私の場合における実際のスクリーンショットはこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/b7d7bdb1-de78-0be9-825d-66b0d179bdc4.png)

`Label` 欄に open か closed かを入力するだけのシンプルなラベリング体験で、入力補完もあります。"Use" タグでサンプルプログラム付きのエクスポートができます。

AWS Lambda で Lobe のモデルを使いたいときもサンプルプログラムをそのまま持っていけば良いので、呼び出し側は実質以下のような 4 行を追加するだけで推論結果が手に入ります。例は Tensorflow 形式でエクスポートした場合です。

```python
from tf_example import TFModel
MODEL_DIR_PATH = '(エクスポートしたモデルを配置したパス)'

model = TFModel(dir_path=MODEL_DIR_PATH)
outputs = model.predict(image) # image は Pillow で読み込んだ画像。outputs に推論結果が返る
```

## 良かったこと 2: ATOM Cam 2 の設置が容易

カメラの置き場というのは悩みの種になります。特に玄関は何かとあわただしい場所。あまり邪魔にならないところが良いです。そういった意味でソラカメ対応の ATOM Cam 2 は非常におさまりが良かったです。

<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/f76bd9f0-9e85-c384-cf81-dad90bc6e2d9.png">

## 難しかったこと 1: AWS Lambda x Tensorflow Lite のビルド

AWS Lambda では Tensorflow などのフレームワークを AWS SAM のテンプレートとして提供しています。

https://aws.amazon.com/jp/about-aws/whats-new/2021/06/aws-sam-launches-machine-learning-inference-templates-for-aws-lambda/

Tensorflow の場合は `public.ecr.aws/lambda/python:3.8` のイメージをベースに、Lobe のサンプルプログラムがまったく問題なく動作しました。

しかし、より軽量にしようと Tensorflow Lite をビルドしようとしたところ、`'glibc_2.27' not found` のエラーにはまってしまいました。いくつかの回避策がありそうだったのですが、私は愚直に Docker Image 上で glibc をビルドする道をとってしまったため、Tensorflow Lite を動かそうとしたときビルドで非常に時間がかかるようになってしまいました。。DockerFile に以下のような余分な作業を入れています。

```DockerFile
RUN yum -y update \
    && yum -y install gcc make gcc-c++ zlib-devel bison bison-devel gzip glibc-static mesa-libGL-devel \
    && yum -y install tar

RUN curl -O https://ftp.gnu.org/gnu/glibc/glibc-2.27.tar.gz \
    && tar zxvf glibc-2.27.tar.gz \
    && mv glibc-2.27/ /opt/glibc-2.27/ \
    && rm glibc-2.27.tar.gz

WORKDIR /opt/glibc-2.27/build
RUN /opt/glibc-2.27/configure --prefix=/var/task
RUN make
RUN make install
RUN cp -pa /var/task/lib/libm.so.6 /lib64/
```

これはどうするのが一番良いのかまだわかっておらず、良いアイデアがあればぜひ知りたいです。

ただ、デプロイした AWS Lambda をそれぞれ実行した結果、Tensorflow Lite で作った AWS Lambda のほうが高速に実行が完了しました。そのため、検証は Tensorflow で、本番は Tensorflow Lite でやるようになりました。

## 難しかったこと 2: Lobe で作成したモデルの精度向上

Lobe では 2022 年 12 月 10 日現在バウンディングボックスで囲ってのラベリングができません。どういうことかというと、

Lobe の場合、以下のように画像全体に対して "Open" または "Closed" とラベリングします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/57abc4de-1f67-3ba1-8707-b30f96f6c742.png)

一方で Amazon SageMaker Ground Truth の場合は以下のようにどこを見て "Open" "Closed" を判断するのかを指定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/6fa55c94-3afe-5748-337d-583fc558b8f9.png)

おそらく、このようなバウンディングボックスで囲うラベリングができないことが原因で、最初に Lobe で作成したモデルの精度は十分ではありませんでした。画像の数を 98 枚まで増やす・"Open" と "Closed" で画像の数を揃える・上下させた画像も使ってみる・暗い画像も明るい画像もなるべく均等に入れる、といった努力で Lobe 上は 90% 程度の正解率まで向上できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/0baaca4a-fee9-e698-1395-ed10f58fdd42.png)

ただ Amazon Rekognition を使うと 30 枚の画像でも 1.0 の [F1 値](https://ja.wikipedia.org/wiki/F%E5%80%A4_(%E8%A9%95%E4%BE%A1%E6%8C%87%E6%A8%99)) でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125247/81844ea1-e0f8-68e7-7574-341c3a34b41f.png)

ここについては今後、自力でバウンディングボックスで囲ったラベリングをもとにモデルを作ったり、画像をクロッピングしたり、良い方法を考えていきたいと思います。

**2022-12-19 追記**: 画像のクロッピングで精度の向上ができました！方法の詳細は発表資料をご覧ください。

https://speakerdeck.com/soracom/detect-locking-the-door-using-sora-cam-lobe-aws-lambda-tensorflow-lite

## まとめ

SORACOM のアドベントカレンダーのわりに SORACOM の話が少なめでしたが、手軽な設置や使いやすい API によって、今まで手を出せていなかった画像認識にチャレンジできたのは良いなと思います。あとオートロックは買おうと思います。

### 宣伝

なお、今回のチャレンジについて、2022-12-13 に開催される SORACOM UG Online でもライトニングトーク (LT) で発表しようと思います！もう少し肉付けできたらと思うので、遊びに来てください！

https://soracomug-tokyo.connpass.com/event/266013/