micro:bitとAzure Face APIで作る「入室管理システム」
こんにちは、遠藤です。
コピペテックマガジン第5回目は、第4回に引き続いてBBC micro:bitを使った電子工作です。
今回は、micro:bitと焦電赤外線センサー(人感センサー) EKMC1601111を繋いで、オフィスや家に入ってきた人をお知らせするシステムを作ってみたいと思います。
システムの全体像はこんな感じになります。
動作についてはまず、動画を見てみてください。
これは弊社のオフィスの入り口ですが、人が入室すると焦電赤外線センサーが検知してmicro:bitでそれを受け、micro:bitからPC (Surface)に対してBluetooth経由で人が来たことを通知します。
焦電赤外線センサーは、周辺と人や動物などが動く際に発する赤外線のゆらぎを検出するセンサーで、EKMC1601111は、データシートによると5mの距離、垂直方向に82度、水平方向に94度の指向性で人の動きを検出可能です。
また、EKMC1601111は集光レンズと信号増幅機も含めたセンサーモジュールとなっており、直接micro:bitの端子につなぎデジタル入力として値を読み取ることができます。
micro:bitは、人が来たことを検知するとBluetoothサービスを利用して、Bluetooth接続したPCのブラウザに対してUARTメッセージを通知します。
Bluetooth接続は、ブラウザで利用できるWeb Bluetoothという仕様を利用しますが、この記事を公開している現在ではPC版のChromeとAndroidのChromeのみ対応していています。記事ではPC版のChromeを利用します
Chromeが、micro:bitから人を検出したメッセージを受けつけるとPCのカメラで写真を撮ります。
撮った写真をサーバーに送信し、サーバー側でMicrosoft AzureのFace APIを呼び出し写真に写った人物を識別します。サーバー側のプログラムはPythonで動かします。
Face APIの結果を受けて、すでに登録されている人であった場合は名前をSlackに通知し、未登録だった場合は、写真と名前を登録するフォーム付きのメッセージをSlackに通知します。
名前の登録はSlackのチームメンバーから選択できるようにしています。メンバーを選択するとFace APIに新しい人物が登録され、次に入出したときに名前が通知できるようになります。
Slackでメンバーを選択した際にSlackからWebアプリが呼び出されますが、このときWebアプリはインターネットからアクセスできるようにする必要があります。
インターネットからアクセスできるように(トンネル)するためにngrokというサービスを利用します。
このように今回もmicro:bitは使いますが、電子工作部分はほんの一部で、人物を検出した後は、クラウドサービスとWebアプリを連携した作り込みといったソフトウェアがメインの内容になっています。
準備するもの
電子工作用買い物リスト
今回の電子工作に使用する部材は以下のとおりです。
電子パーツについては、秋月電子通商のECサイトのリンクをつけてありますので、電子パーツを買えるお店が近くにない場合はこちらから購入してください。
その他、準備が必要なもの
この記事ではWindows 10をベースに説明しています。
また、PCには以下をインストールしておいてください。
焦電赤外線センサーとmicro:bitのセットアップ
micro:bitで焦電赤外線センサーの入力を制御して写真を撮るプログラムを作成して、その後センサーとmicro:bitを繋いでいきます。
micro:bitのプログラム作成には、ブラウザで利用できるmakecode を利用します。
https://makecode.microbit.org を開くと、新しいプロジェクトが作成されプロジェクトが開きます。
完成版のmakecodeプロジェクトを以下のURLで公開していますので、必要に応じて参考にしてください。
https://makecode.microbit.org/_Vt4JkhcsM4dY
拡張機能Bluetoothを追加
ブロックを追加してプログラミングを始める前に、まずBluetoothパッケージを追加します。
右上の歯車アイコンをクリックして、メニューから[拡張機能]を選択します。
[bluetooth]を選択します。
[Remove extention(s) and add bluetooth]ボタンをクリックします。
ブロックリストの[無線]に替わって[Bluetooth]が追加されます。
Bluetoothのペアリング設定
次にmicro:bitのBluetoothの設定をしていきます。
[プロジェクトの設定]を開きます。
ここで、プロジェクト名も変更しておきます。
[名前]にプロジェクト名を設定し、[No Pairing Required: Anyone can connect via Bluetooth.]を選択します。
ペアリング設定を選択すると、プロジェクトの設定が閉じられます。
micro:bit用のプログラムを作成
必要なパッケージが追加できたら、以下のように人感センサーで入室を検知して、写真を取るプログラムを作成していきます。
1. [Bluetooth ...more]から[Bluetooth UARTサービス]を[最初だけ]に追加します。
2. [論理] から [もし <真▼> なら (+) ]を[ずっと]に追加し、<真▼>を[論理] > [(0) {=} (0)]に置き換え、左側の(0)を[高度なブロック] > [入出力端子] > [デジタルで読み取る 端子 {P0▼}]に置き換え、右側の(0)には「1」をセットします。
3. 2.のブロックに[Bluetooth ...more]から[Bluetooth UART 数値を文字で書き出す(0) ]を追加し、(0)を「1」に変更します。
4. 続けて、[基本] から [アイコンを表示 {アイコン}]を追加し、{アイコン}は「チェック」を選択します。
5. [基本] から [一時停止(ミリ秒) {100}]を追加して、停止時間を「5000」に設定します。
6. [基本 ...more]から[表示を消す]を追加します。
7. [ずっと]ループの最後に[基本] から [一時停止(ミリ秒) {100}]を追加します。
micro:bit用のプログラミングは以上です。
[ダウンロード]をクリックして、hexファイルをダウンロードします。
micro:bitとPCをUSBケーブルで接続して、ダウンロードした「人が来たら通知する.hex」ファイルをmicro:bitに転送します。
micro:bitと焦電赤外線センサーをつなぐ
micro:bitに焦電赤外線センサーをつないで、センサーの動きを確認してみます。
焦電赤外線センサーEKMC1601111をブレッドボードに差します。
Source、Grand、Drainをそれぞれブレッドボードの以下の位置に差します。
ピンの向きを確認して、センサーを差し込みます。
Micro:bitのGND端子とGrand、3V端子とDrain、P0端子とSourceがつながるように、みのむしクリップ付きジャンパーワーイヤーでつなぎます。
ここまでの動作を確認してみます。
センサーに手をかざしたりすると、micro:bitにチェックマークが表示されます。
micro:bitからの通知を受けてPCで写真を撮る
Webアプリケーションのソースファイルを以下のURLからダウンロードしてください。
https://github.com/hrendoh/face-detection-with-microbit/archive/master.zip
ダウンロードしたファイル face-detection-with-microbit-master.zip を展開してPCのユーザのホームディレクトリ(Windowの場合は、「C\Users\<ユーザー名>」)に移動します。
展開したフォルダーからHTMLファイル face-detecttion-with-microbit-master/templates/index.html をChromeで直接開きます。
カメラの使用を許可するダイアログが表示されるので[許可]をクリックします。
次に[CONNECT]ボタンをクリックすると、Bluetoothペアリングの設定ダイアログが開きます。
「BBC micro:bit [pagit]」を選択して[ペア設定]をクリックします。
[試行中]に切り替わり[接続中]になったらペアリングとmicro:bitのBluetooth UARTサービスの準備に成功しています。
micro:bitと合わせて動作を確認してみます。
センサーで検知するとPCのカメラで写真が撮られることが確認できます。
確認用動画では、センサーの向き的に常に反応してしまっているので、5秒おきに写真が撮られるような動作になっています。
Webアプリケーション サーバーをセットアップ
先程はHTMLファイルを直接Chromeで開きましたが、次は撮った写真をサーバーに送信し、Face APIをたたいて写真の人物を識別するようにするために、PC上にWebサーバーを立てていきます。
アプリケーションの構成
今回のWebアプリケーションはPythonのflaskというWebアプリケーションフレームワークを使用して実装しています。
アプリケーションの構成は以下のようになっています。
- main.py
- templates/
- index.html
- static/photos/
main.pyn には、Webアプリケーションのサーバーサイドのコードをすべて含んでいます。
templates ディレクトリは、flaskでテンプレートを配置するディレクトリです。先程使用したindex.htmlを含みます。
static ディレクトリは、cssやjs、画像など静的リソースを配置するディレクトリです。今回は撮影された写真を保存して、Slackからアクセスします。
Python環境 Anacondaのインストール
Pythonの環境はWindowsでもMacでもインストーラで簡単にセットアップできるAnacondaを使用します。
以下の手順でAnadondaをインストールしていきます。
1. Pythonのインストーラをダウンロードします。
https://www.anaconda.com/download/ にアクセスし下にスクロールするとダウンロードボタンがあります。
[Python 3.7 version]の[Download]ボタンをクリックします。
2. ダウンロードされたAnaconda3-5.3.0-Windows-x86_64.exeを実行します。
Anacondaのインストーラが開きます。[Next > ]をクリックして次に進みます。
2. [I Agree]をクリックします。
3. [Just Me]を選択して[Next >]をクリックします。
4. インストール先のフォルダを指定して[Next >]をクリックします。
5. オプションはデフォルトのまま[Install]をクリックしてインストールを開始します。
6. しばらく待ちます。インストールが完了したら[Next>]をクリックします。
7. テキストエディがVisualStudioCodeをインストールしますか?と聞かれます。テキストエディタがない場合は、ここでインストールしておいてください。
テキストエディタがすでにインストールされている場合は[Skip]をクリックします。
8. 以上でインストール完了です。[Finish]をクリックしてインストーラを閉じます。
PythonコンソールでWebアプリケーション サーバーを起動
Windowsメニューから[Anaconda3(64-bit)] > [Anaconda Prompt]を開きます。
(base) C:\Users\ユーザ名> のプロンプトが開きます。
ディレクトリ face-detection-with-microbit-master に移動し、「python main.py 」と打ち込みEnterを押して実行します。
Windowsの場合、Windowsファイアウォールの許可が求められます。(Macの場合はそのまま起動します)
[アクセスを許可する(A)]をクリックするとサーバーが起動します。
動作確認
http://localhost:3001 にアクセスすると以下のように、先程ファイルを直接開いたのと同じ画面が開きます。
今度は写真が撮られるとWebサーバーに写真が送られて、Webサーバー側でFace APIで検出しようとしています。
まだ、Azure Face APIの準備をしていないのでエラーになっています。
Microsoft Azure Face APIを使って顔を検出
次に、撮った写真に写っている人物をMicrosoftのFace APIを使って識別してみます。
Microsoft Azureのサブスクリプションを持っていない場合は、無料試使用版のサブスクリプションを取得できます。
以下のURLからAzureにサインナップしてください。
https://azure.microsoft.com/ja-jp/free/
サインナップするとAzure ポータルが開きます。
ポータルが開いたら、以下の手順でFaceリソースを追加していきます。
1. 画面の左のメニューから、[すべてのサービス] > [AI + MACHINE LEARNING]から[Cognitive Service]を選択します。
2. Cognitive Servicesのページに切り替わるので、左上の[+ 追加]ボタンまたは[Congnitive Serviesの作成]ボタンをクリックします。
3. AI + Machine Learningのページで、Cognitive Servicesの[さらに表示]をクリックします。
4. 右に開いたAPI一覧から[Face]を選択し、[作成]をクリックします。
5. 作成フォームが開きます。
[Name]には適当な名前「FaceDetection」を入れ、サブスクリプションは「Azure Free Trial」を選択します。
[場所]は「東日本」(japaneast)を選択し、価格レベルは「F0」、[Resource Group]は適当に作成したものを選択して[作成]をクリックします。
6. リソースの作成が完了すると、右上に以下のポップアップが表示されるので、[ダッシュボードにピン留めする]をクリックしてダッシュボードに登録しておきます。
7. 左のメニューから[ダッシュボード]を開き、作成した[FaceDetection]を選択します。
8. [FaceDetection]が開いたら、左から[Keys]を選択して、APIキーを表示します。
[KEY 1]をAPIの認証に使います。
[KEY 1]をコピーして、main.pyの「<Azure Face API Key>」の箇所を置き換えてください。
# <Azure Face API Key>をKEY 1の値に置き換え
FACE_API_SUBSCRIPTION_KEY = '<Azure Face API Key>'
main.pyを再起動します。
再起動は、main.pyを起動しているターミナルにフォーカスして[Ctrl + C]キーを入力すると停止します。再び「python main.py」を入力してEnterします。
写真が撮られると、Face APIで検出された顔に枠が表示されます。
WebアプリケーションのコンソールではSlackのWebhookを呼び出すところで、以下のようなエラーが表示されます。
引き続きngrok、Slackの設定をしていきます。
ngrokでWebアプリケーションをインターネットに公開
Slackの設定の前に、Webアプリケーションをインターネットに公開しておきます。
https://ngrok.com/ にアクセスしアカウントを作成します。
(アカウントを持っている方はサインアップの手順はスキップしてください。)
[Get start for free]か右上の[Sign up]ボタンをクリックします。
EmailまたはGithubアカウント、Googleアカウントいずれかで登録できますが、ここではEmailでサインナップしてみます。
登録フォームに名前、Eメールアドレス、パスワードを入力して[Create an account]ボタンをクリックします。
Eメールによるコンファームは無く、登録するとすぐに以下の[Setup & Install]のページが表示されます。
[Download for Windows]をクリックしてngrokコマンドを含むzipファイルをダウンロードします。
ダウンロードされた「ngrok-stable-windows-amd64.zip」ファイルを展開して、ngrokファイルをユーザのホームディレクトリ(C:\Users¥<ユーザ名>)に移動しておきます。
ページをスクロールして、[Connect your account]のコードをコピーします。
Anaconda navigatorからターミナルをもう一つ開き、コピーしたコードをペーストして実行します。
ngrokの認証情報が.ngrok2フォルダに保存されます。
続いて「ngrok http 3001 」を実行して、Webhookをngrokをつなぎます。
実行すると以下の画面に切り替わります。
ブラウザで、https://<xxxxx>.ngrok.io にアクセスすると、以下のように同じページが表示されます。
割り当てられるURLの値は起動毎に変わります。この記事が終わるまでは起動したままにしておいてください。
Slackチームに通知と人物を選択するWebhookを登録
次はSlackに、入室の通知と新しい人物の写真にラベル付けをするWebhookを登録します。
Slackワークスペースがない場合は、以下のURLより新しいチームをサインナップしてください。
https://slack.com/create#email
ワークスペースの準備ができたらSlackにサインインしているブラウザで、https://api.slack.com にアクセスしします。
このサイトで、Webhookを含むSlack用のアプリケーション Slack Appを作成し、発行されるWebhookのURLと、OAuthアクセストークンをmain.pyにセットします。
ところで、ただの通知のみのWebhookであればSlack Appを作成しなくても https://slack.com/services/new/incoming-webhook から簡単に設定が可能です。
この記事では、メンバーを選択するところでInteractive messagesという機能を使いますが、Interactive messagesはユーザの入力を受け付けるサーバーのEndpointを設定する必要があり、それはSlack Appの設定画面 Interactive Components で行います。
また、写真の人物を選択した際にSlackから送られてくる情報は、選択したユーザのSlackの内部Idのみなので、users.info APIをたたいてユーザ名を取得し、それをFace APIのPersonのnameにセットしています。Slack APIのアクセスにはOAuthアクセストークンが必要ですが、こちらもSlack Appの設定ページOAuth & Permissionsから取得することができます。
では、以下の手順でSlack Appを作成し設定してきましょう。
1. [Start Building]をクリックしてアプリケーションの作成を開始します。
以下の[Create a Slack App]フォームが表示されます。
[App Name]には「入室管理システム」と入力し、[Development Slack Workspace]では、アプリを利用するSlackのワークスペースを選択して、[Create App]ボタンをクリックします。
2. 新しくアプリケーションが作成され、以下の[Basic Information]のページが表示されます。
[Add features and functionality]から[Incoming Webhooks]をクリックして開きます。(左のメニューから[Incoming Webhooks]を開いても同じです)
3. Incoming Webhooksを有効にするために、右上のスイッチをクリックして「On」にして、[Add New Webhook to Workspace]をクリックします。
4. [Post to]で入室管理システムが投稿をするチャンネルを選択して[Authorize]をクリックします。
5. [Webhook URLs for Your workspace]の[Webhook URL]に、作成されたWebhoookのURLが追加されます。
追加されたURLをコピーして、main.pyの「<Slack Incoming Webhook URL>」を置き換えます。
# <Slack Incoming Webhook URL>をWebhook URLの値に置き換え
SLACK_INCOMING_WEBHOOK_URL = '<Slack Incoming Webhook URL>
6. 続いて、左の[Features]から[Interactive Components]を開き、Interactive messagesを有効にするために、右上のスイッチをクリックして「On」にします。
7. 設定が可能になるので[Request URL]に、ngrokのURLに「persons」を足した値「https://xxxxxx.ngrok.io/persons」を入力し、[Save Changes]をクリックして保存します。
「persons」はユーザーを選択した際にFace APIに人物 Personを登録するアクション名なります。
8. 次に、左のメニューより[OAuth & Permissions]を開きます。
9. 少しスクロールして、[Scopes]の[Select Permission Scopes]のプルダウンから「users.read」の権限を選択します。
「users.read」を付与することによって、users.info APIを使用してユーザ情報を取得できるようになります。
10. [Access your workspace's profile information users.read]が追加されたことを確認して、[Save Changes]をクリックします。
11. サイトの上部に、以下のメッセージが表示されるので[click here]をクリックします。
12. 再度、チャンネルにインストールします。
13. [OAuth & Permissions]のページに戻ります。
[OAuth Access Token]をコピーしてmain.pyの「<Slack OAuth Access Token>」を置き換えます。
# <Slack OAuth Access Token>をOAuth Access Tokenの値に置き換え
SLACK_OAUTH_ACCESS_TOKEN = '<Slack OAuth Access Token>'
main.pyを再起動します。
以上で、一通り実装完了です。
全体の動作確認
では、人の検出からSlackへの通知まで全体の動きを確認してみましょう。
冒頭の動画のように、センサーが反応して写真が撮られるとSlackに以下のような写メッセージが投稿されます。
[メンバーを選択]からメンバーを選択します。
メンバーを選択すると、main.pyのpersonsアクションが呼び出されて、選択した名前で写真がFace APIに登録されます。
同じ人の写真が投稿される場合は、「<Slackのユーザ名>が入室しました。」というメッセージと共に写真が投稿されます。
他のメンバー、矢野さんが入室してきた場合も以下の通りちゃんと動くことが確認できました。
Slackのユーザ名「yanotaka」を選択後、再度検出すると正しく判定できています。
チューニングポイント
以上で、本編のアプリケーションは完成ですが、補足としていくつかチューニングポイントをまとめてみます。
写真を撮るタイミング
EKMC1601111は反応が良いので弊社オフィスのようにドアまでの距離が近いと部屋に入る前に写真が撮られてしまいあまりよいアングルで撮影できない場合があります。
解決策としては以下のような手段がありそうです。
1. 確実な方法は、反応したら一定時間連写しすべてサーバーに送信し、顔を検出できた一枚を採用するロジックにする。
2. 人を検知してから写真を撮るまでに間をおく。
写真単体での検出率アップ
顔が写っていても、解像度や明るさによっては検出率が下がります。
今回の記事では、Surface Pro 3のWebカメラを利用していますが、あまり明るさ調整の反応がよくないので、タイミングしだいでは暗く写ってしまったりします。
明るさについては解決策としては以下のような手段がありそうです。
1. カメラ性能の良いAndroid端末を利用する。
2. OpenCVなどを利用してソフトウェアで露出を上げる。
解像度については、幅640、高さ480にしてありますが、templates/index.html の以下のコードのwidthを変更して写真の解像を高くすることができます。
// 写真の横幅 (表示幅は320px、640だと表示されている大きさの倍の解像度になります)
var width = 640;
// 横幅、0のままであれば width の 3/4 の高さが使用されます
var height = 0;
設置場所によってうまくいかない場合は参考に調整してみてください。
この記事が気に入ったらサポートをしてみませんか?