Raspberry PiにUSB接続したカメラで取得した画像から人の混雑度を推論し、結果をブラウザで表示

Raspberry PiとUSBカメラを使って、以下のことを実現します。

1. USBカメラの画像をRaspberry Pi上で動作するGravioで読み込み
2. 読み込んだ画像に写っている人数をGravioの画像推論機能で数値化
3. Gravio内のデータベースに人数データを蓄積
4. Raspberry Pi上のブラウザからGravioのAPIへアクセスしデータを取得
5. 取得したデータをもとにブラウザのゲージ画面で混雑度をわかりやすく表示

構成は以下のようになります。
####物理構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/37a5b69a-24b5-c820-e520-751c73c93c28.png)

####論理構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/5d1e414d-6e92-2ed8-4b49-9dfd433e483b.png)


#使用したもの
###ハードウェア

- Raspberry Pi 3 Model B<br>OSバージョン：Raspbian GNU/Linux 9.8<br>カーネルバージョン：Lunux rasperrypi 4.14.98-v7+ #120
- Apple iPad 9.7インチ Wi-Fiモデル 32GB MR7G2J/A<br>（Gravio Studioでの設定に使用、Windows 10、もしくはMac OSのPCで代用可能）
- [BUFFALO 200万画素WEBカメラ](https://www.amazon.co.jp/dp/B01LXYHF71/ref=cm_sw_em_r_mt_dp_U_WYzRCbAQTG7W4)（Raspberry Piに接続）
- ディスプレイ　（Raspberry Piに接続できるもの、ダッシュボード表示用）

###ソフトウェア
- Gravio
 - Gravio Service（Raspberry Pi版）Version2.2.0-1550　
 - Gravio Studio（iPad版）Version2.0.4(314)
- Chromium　Version 72.0.3626.121

#Raspberry PiにGravio Serverをインストール
Raspberry PiにGravio Serverをインストールします。

まず、OSの状態を最新にするために、ネットワークへ接続しTerminal画面で下記コマンドを実行します。

```
sudo apt-get update
sudo apt-get upgrade
```

次に、[ダウンロードサイト](https://www.gravio.com/jp/product#Gravio-Server)より、Raspberry Pi版Gravio Serverのインストールファイルをダウンロードします。

そして、ダウンロード先のディレクトリで下記コマンドを実行しインストールします。

```
sudo apt install ./gravio_arm.deb
```

インストール後、下記コマンドでサーバーを起動します。

```
sudo systemctl enable gravioedge.service 
sudo systemctl enable gravioaction.service 
sudo systemctl enable graviocontrol.service
```

以上で、Raspberry PiへのGravio Serverのインストール、及び、起動が完了しました。

#Gravio StudioをiPadへインストールし、Raspberry Pi上のGravio Serverと接続する
Gravioの各種設定をGUIで行うGravio Studioは、Windows 10、Mac OS、iOS用が提供されております。
今回はiPadにiOS版のGravio Studioをインストールし、そちらからRaspberry Pi上で動作しているGravio Serverの挙動を設定します。

##iPadにGravio Studioをインストール
App Storeにて、"Gravio Studio"を検索しインストールします。
インストール後、Gravio Studioを起動し、ログインします。
（初めてGravioを使用する場合は、サインアップ画面にて登録後ログインします）

##Raspberry Pi上のGravio Serverへ接続

iPad版のGravio Studioでは、動作しているGravio ServerのIPアドレスを手動で設定する必要があります。
Raspberry Pi上のTerminalでIPアドレスを確認した後、動作しているGravio Serverを先に取得したIPをもとに追加することで、iPadからGravio Serverの設定が可能になります。
TerminalからのIPアドレスの確認するコマンドは下記のとおりです。


```
ip a
```

表示されるIPアドレスをメモします。

次に、iPadのGravio Studioの画面にて、右上に表示されている"+"をタップし、Gravio Serverを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/eb4e88a9-35b1-9b18-3f3e-16b5dcdbb629.png)

"サーバーの追加"画面で、以下を設定し"保存"をタップします。

|項目|内容|
|:---|:---|
|名前|任意（今回は”Raspberry Pi"と入力）|
|サーバー|直前にメモしたIPアドレス|
|暗号化通信を利用|有効（デフォルト設定）|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/272377f4-d366-cb05-109b-0f2b8b182c9f.png)

設定後、追加されたサーバーアイコンをタップすると、デバイス設定画面に遷移します。

#Gravio Server上の設定
USBカメラの画像に写っている人数を推論し、Gravio Server内のデータベースへ推論結果データを蓄積する設定をします。

##カメラの設定、カメラ画像解析による人数データ化設定
カメラを登録するエリア、およびレイヤーを追加します。
デバイス設定画面にて、画面左に表示されている”＋”をタップし、表示される画面で任意のエリア名を入力します。
入力後"追加"をタップします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/ea9b3dac-7e7f-82a3-852e-206539279aaa.png)

次に、レイヤーの設定画面が表示されます。
任意のレイヤー名を入力後、センサータイプに"BuildInAndUSBCamera"を選択し、"追加"をタップします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/0c79e5cd-b4d7-204e-2f6d-bcfee2798682.png)
追加されたレイヤーにカメラデバイスを追加します。
"追加"をタップ後、表示される画面で"BuildInAndUSBCamera"をタップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/afd041d5-8784-0c58-91a6-8449f900fb47.png)

次に、カメラの画像の処理方法について設定します。追加したデバイスに表示されている"i"をタップします。
画像の処理について、インスペクタ画面で以下のように設定します。

|項目|内容|
|:---|:---|
|キャプチャー形式|画像（デフォルト設定）|
|キャプチャー間隔|任意（今回は15秒に設定）|
|画像推論の実行|任意（今回は"NumberOfPeople-Lite"に設定）|
|画像の保存|OFF（デフォルト設定）|
|検出フレームの描画|OFF（デフォルト設定）|

![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/e4fdffca-e406-24ed-2318-1e6ba750e770.png)
最後に、スライドボタンをタップし、デバイスを有効にします。
以上の設定で、カメラ画像を基に人数を推論、およびその推論結果を人数データとしてGravio Server内に蓄積しはじめます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/bacebad1-4f07-0c08-7c3e-90096ca39eeb.png)

##推論結果データの確認
推論結果データをデータビューアで確認します。
まず、データビューアタブをタップします。
次に、右上の"LIVE"をタップし、リアルタイム表示を有効にします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/247209/a5a715df-a4a0-61d6-8322-36661842cac8.png)


推論された結果が"値"に表示され、データベースにデータが蓄積されていることが確認できます。
今回の場合は、先程インターバルに設定した15秒毎に新しいデータレコードが追加されます。

#ブラウザを利用する簡易BIツール「Gravioゲージ」の設定
混雑度をわかりやすくブラウザ上で表示することができる「Gravioゲージ」の設定をします。
今回使用するゲージはGitHubに掲載されている、[**Gravio_Guage**](https://github.com/HappehBunneh/gravio_gauge)を使用します。
ゲージは各種ブラウザで動作するように作られています。今回はRaspberry Pi上に標準インストールされているChromiumにて、ゲージを表示します。

それでは、ダウンロードサイト記載されている手順を参考に設定していきます。
##ゲージのダウンロードと解凍
[**ダウンロードサイト**](https://github.com/HappehBunneh/gravio_gauge)よりゲージのアプリケーションをダウンロードします。
"Clone or download"＞”Download ZIP"の順でクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/a25eab9b-3c49-8498-8db2-96d8ab4198fb.png)

ダウンロードしたファイルを右クリックし、"Extract Here"をクリックすることで、フォルダが解凍されます。

次にGravio Serverに蓄積されているデータを取得するためにCORS（Cross-Origin Resource Sharing）の設定をします。

##CORS設定
ブラウザ上で動作するGravio Gaugeから、Gravio ServerのAPIにアクセスするには、CORSを有効にする必要があります。
ChromiumでCORS機能を有効にするには、拡張機能のAllow-Control-Allow-Originを使用します。

それでは、ブラウザからGravio Serverへアクセスを許可する設定をしていきます。
まず、[**Allow-Control-Allow-Originサイト**](https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi/related?hl=en)の"Add to Chrome"をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/cd0d84b0-094b-8e01-6a41-e7d79e04ba97.png)

追加を許可すると、Chromiumブラウザのアドレスバー横にCORSアイコンが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/0ad5bb20-7ec3-16d1-155a-9f6cfe576dfa.png)

次に、Gravio Serverへのアクセスを許可します。
`https://「先程メモしたIPアドレス」:29444/gappapi`　をアドレスバーに入力し、サイトへのアクセスを許可します。
許可すると405エラーが表示されますが、無視して先に進みます。

これで、ブラウザからGravio Serverへアクセスができるようになりました。
次に、アプリケーションファイルの設定をします。
##main.jsの修正
先程解凍したフォルダ内の、main.jsファイルをダブルクリックで開き、テキストエディタ上で下記の3つを変更します。
　
 1. 推論モデルの設定<br>19行目に、"DataType"に"NumberOfPeople"が設定されています。<br>今回は、先程設定した"NumberOfPeople-Lite"へ変更します。<br>
 2. Gravio Serverアドレスの設定<br>25行目に設定されている<br>`https://10.48.1.61:29444/gappapi`を<br>`https://「先程メモしたIPアドレス」:29444/gappapi`に変更します。<br>
 3. ダミー値構文のコメントアウト <br>66行目に設定されている、<br>`recentValue = Math.floor(Math.random()*10)+1`をコメントアウトします。

修正後、ファイルを保存します。
以上で、データ更新を行うJavaScriptファイルの設定が完了しました。

##ゲージの表示
最後にブラウザで、ダッシュボードを表示します。
フォルダ内のindex.htmlをChromiumで開きます。
Gravioの検知人数データをもとに混雑度がゲージにリアルタイムで表示されます。

#実行結果
カメラに写っている人数を検知し、下図のようにブラウザで混雑度を可視化できました。
3人検知した場合は、Busyと表示され、人を検知していないときはEmptyと表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247209/f09a3e62-dc4a-5eab-4a74-7e1fbe198525.png)

main.jsのコードを書き換えることで、ゲージの色の変更や、Busyとなる人数の変更などが可能です。

#あとがき
市販のUSBカメラとRaspberry Piを使って、カメラに写っている人数を把握し、ゲージで可視化しました。
Gravio Gaugeに関しては無償で利用可能ですので、混雑度表示にかぎらず、簡易的なブラウザベースのBIツールをご検討の方はぜひ利用してみてください。
今後、他のセンサーを使用した可視化方法も考えていきますので、ぜひご期待ください。