United Statesからアクセスのようです。言語設定をEnglishに切り替えますか?
Switch to English site
Skip to main content

複合スマートホームデバイス

概要


我々のチームでは、温度センサーによるその時点で最適なエアコンの設定温度を提案する機能と、監視カメラ機能をもつ複合スマートホームデバイスを開発した。

開発背景

近日、非常に日中の温度が高く熱中症の可能性が高い日が続いていた。
そこで、熱中症を回避するために適切なエアコンの設定温度を提案するデバイスが必要であると考えた。
また、将来的な展望として、熱中症を発症し、倒れてしまった場合などをカメラを用いて検知できないかということも考えた。
しかし、カメラによって取得可能な情報だけでは熱中症を検知することは難しいと考えた。
そのため、カメラを用いた便利なアプリケーションを考えたときに、監視カメラ機能を搭載することを考えた。
これは、こじつけにはなるが、暑い日々が続いていることで、人々の注意力が低下し、鍵の締め忘れなどが考えられる。
その状況下において、窃盗犯が家屋に侵入する可能性を想定したものである。

設計

Raspberry Pi と、USB カメラ、温湿度センサー、を用いて、カメラの画像の取得、温度の取得を行う。
スマートフォン上で動作するアプリが Raspberry Pi に対してリクエストを送信することにより、温度の情報を送信し、スマートフォン側で最適なエアコンの設定温度を算出し提示する。
また、Raspberry Pi 上では常にカメラの画像を監視し、動体を検知すると一定時間録画を行う。そして、スマートフォン側でその録画した映像を確認できるようにする。

このような設計を行った。
アプリと Raspberry Pi との通信には `HTTP` を用いることとし、REST 風の API でデバイス側の機能を提供するものとする。

実装

Android アプリは Java により実装を行い、API サーバ及び温度の取得には C++ を用いた。ラズパイプログラムの実装では主に以下の3点があります

1点目としては、温湿度センサーの組み立てです。型番DHT11では4つのピンがあって、今回使ったのは三つです。signal ピンをうまく動作させるために、10Kの抵抗を使いました。

2点目は、センサーからデータを読み取るプログラムです。大体wiringPiライブラリの関数を使いました。pinMode()でラズパイのピンモードを切り替えて、通信の初期化とデータの読み取りを行います。digitaiWrite()で取得されたデータは5つあり、温湿度データの整数部と小数部、それから検証としての和です。取ったデータを文字列としてmessageに入れ込みます。

3点目は、データの送信です。Http通信の部分はWeb program framework  Oat++を使いました。C++言語なので、ラズパイで簡単に実装できます。大体の形としては、まずHttp通信のRouterを生成します。Routerによって、Http要求が来たら、自動的に処理プログラムTempcontrollerを実行します、そして、処理プログラムではセンサーとの通信の確立とデータの読み取り、それからHttp APIの生成を行います。

監視カメラの機能を以下に列挙する。

- カメラからの入力をデバイスの native のフレームレートで取得し、常に監視を行う。
- 監視している最中に動体を検知すると、一定時間(デフォルトでは `10` 秒)録画を行う。
- 録画中に再び動体を検知した場合は、録画時間を延長する。
- 録画データは `mp4` 形式でファイルシステムに保存する。(プロセスが割り込みなどで中断された場合を考慮して、mp4 ではなく `AVI` などの形式にしたほうが良かったかもしれない。)
- このとき、ファイル名は UUID v4 で生成したランダムな名前をつける。

これらの機能をどのように実装したかについてそれぞれについて解説を行う。

アーキテクチャ


この監視カメラのアーキテクチャについて記述を行う。この監視カメラは、以下に示す 2 つのスレッドを動作させ、その機能を実現する。

- カメラの入力を受け取り、動体を検知するメインスレッド。
- メインスレッドからの要求でフレームを動画の形式で保存する録画スレッド。

そして、このスレッド間ではメッセージパッシングにより通信を行う。動作としては、

- メインスレッドはカメラからの入力を受け取り、動体の検知を行う。
- メインスレッドで動体を検知した時点で、メインスレッドから録画スレッドに対して録画開始リクエストを行う。
- 録画スレッドは、録画開始リクエストを受け取ると、録画した動画を書き出すためのファイルを生成する。
- メインスレッドは、録画条件(後述)を満たす間、受け取ったフレームを録画スレッドに送信し、記録を依頼する。
- 録画スレッドは、受け取ったフレームを動画ファイルに書き出す。
- 録画条件が満たされなくなると、メインスレッドは、録画終了リクエストを録画スレッドに行う。
- 録画スレッドは、録画終了リクエストを受け取ると、ファイナライズ処理をしてメモリからファイルシステムに動画ファイルを書き出す。

となる。

録画条件

動体を検知すると、監視カメラはそこから一定時間録画を行う。
その時間はデフォルトでは 10 秒としている。
ここで、録画条件を定義する。

- 最後に動体を検知してから 10 秒間 動体を検知しなければ録画を停止する

この条件により、最後に動体を検知してから 10 秒以内に動体を検知した場合は録画を 10 秒延長する。

カメラデバイスからの入力を受け取る

カメラデバイスからの入力を受け取るために、`OpenCV` を用いた。具体的には、`OpenCV` の `VideoWriter` を用いてる。

動体の検知

ここでは、動体の検知アルゴリズムについて記述を行う。

- カメラから受け取ったフレームの、各画素について平均値を計算する。これにより、「何も起きていないときのフレームの状態」を算出する。
- つづいて、現在受け取ったフレームと、「何も起きていないときのフレームの状態」との差分を検知する。
- このとき、予め定めておいたしきい値(1) を超える画素をカウントする。
- これにより、ノイズを除去する。
- 直前のステップでカウントされた画素は、平均から大幅な差分のある画素、すなわち、変化のあった画素ということになる。よって、どのくらい画像に変化があったかを計算することで動体の検知が可能となる。
- そのために、変化した画素の個数を計算する。そして、その個数が予め定めておいたしきい値(2) を超えていた場合に動体を検知したとみなす。

YsFENGz さんはまだ自己紹介を入力されていません...