学生証と顔認証で本人確認してみる [3] 〜Node-REDを使ってシステムを構築しよう〜


昨日ぶりぶりです。たてしきと申します。
本人確認です(雑×2)
## お品書き
・[学生証と顔認証で本人確認してみる [1] 〜MS Azure、Face APIの利用準備をしよう〜](https://qiita.com/Tateshiki0529/items/8f51020df986aaadf798)
・[学生証と顔認証で本人確認してみる [2] 〜Face APIにユーザーを覚えさせよう〜](https://qiita.com/Tateshiki0529/items/bd6c38cb193d65235d71)
・**学生証と顔認証で本人確認してみる [3] 〜Node-REDを使ってシステムを構築しよう〜**  ←いまここ！
・~~学生証と顔認証で本人確認してみる [4] 〜実際に使ってみよう〜 (仮)~~ (執筆中)
## Node-REDの出番
今回の「作るシステム」の講義がNode-REDで行われているので採用します。
### Node-REDとはなんぞや

> Node-RED（ノード・レッド）は、IoTの一部としてハードウェアデバイス、API、オンラインサービスを相互に接続するためにもともとIBMによって開発された、ビジュアルプログラミング用のフローベースの開発ツールである。
> Node-REDは、 JavaScriptの関数を作成するのに使用できるWebブラウザーベースのフローエディターを提供する。アプリケーションの要素は、再利用するために保存や共有できるようになっている。ランタイムはNode.js上に構築されている。 Node-REDで作成されたフローは、JSONを使用して保存できる。バージョン0.14以降、MQTTノードは適切に構成されたTLS接続を確立することができるようになった。
>
> \- Wikipediaより引用

つまりは、Node.jsを簡単に組めるアプリケーションってことで。そういうことにしときます。

## Node-REDの準備
### ダウンロード・インストールしてみる
#### Raspberry Piの場合
Piならこれでいいです。

```shell-session:Console
$ sudo apt-get install nodered
```

#### Windowsの場合

https://nodered.jp/docs/getting-started/windows

これを参考にNode.jsとNode-REDを両方インストールしましょう。

### とりあえず起動してみる
```shell-session:Console
$ node-red
> node-red
```

### アクセスしてみる

`http://localhost:1880/`です。Piの場合は同じWi-Fiに接続してやって(モバイルホットスポットとか)プライベートIPを参照するのが手っ取り早いです。


## 一度Node-REDは置いておいて…
先に顔認証を実装してみます。ちなみに、[前回](https://qiita.com/Tateshiki0529/items/bd6c38cb193d65235d71)まではテスト用のAPIを利用していましたが、検証のために今回使うデータに差し替えさせていただきます。

- personGroupId `authlist` -> `tspglist`
- resource name `tsukuru-system-faceapi` -> `tsukuru-system-instance`
- 僕のPerson ID = `b90fda6e-****-****-****-e89d66e45272` (一応マスクしておきます)

### まずは顔写真を撮影しよう
何でもいいです。スマホのカメラでもPCの内蔵カメラでもWebカメラでも。撮影したらGooglePhotosにでもアップロードしておきましょう。

### URLを取得
いちいちコード組むのめんどいんでURLから渡してしまいます。GooglePhotoで写真を開いてF12でも右クリックでもいいので写真のURLをコピーしてきます。

### いよいよ顔認証
#### まずはFace IDを取得する
次に、[Cognitive Services APIs Reference - Face - Detect](https://japaneast.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236/console)にアクセスします。
今回はマスクを着用した状態とマスクを外した状態の僕の写真を使います。
パラメータはもう変更しなくても大丈夫です。リソース名とキーだけお忘れずに。
![detect-face1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/a6080bf8-83f9-b513-1d28-d482da577a6c.png)
![detect-face1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/aa8f138c-1020-a206-93c8-bed778ce1060.png)

```json:result
[{
    "faceId": "f61ae554-321b-41c0-b828-9bee6748329d",
    "faceRectangle": {
        "top": 320, 
        "left": 166,
        "width": 346,
        "height": 448   
    }
}]
```

今回もこの`faceId`を使うのでメモ。
![detect-face1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/c5658f55-8bfa-54da-dceb-00150a3e07c7.png)

#### 誰かを判別する
[Cognitive Services APIs Reference - Face - Verify](https://japaneast.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395239/console)にアクセスします。ほぼ入力項目はありません。
![verify-face1-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/eeb77d1b-5c19-f81b-a3d3-ce738c179a97.png)
bodyは少し注意が必要です。`largePersongroupId`となっているところを`personGroupId`と変更し、personGroupのID(ここでは`tspglist`)を入力します。
`faceIDs`はとりあえず一つだけでいいのでもう一つは消して、先ほど取得した`faceId`を入力してください。
`maxNumOfCandidatesReturned`は返り値のカウントなので`1`で、`confidenceThreshold`は類似度の閾値になるのでとりあえず今回は`0`にしておきます。
![verify-face1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/255f7f3d-8f67-ca09-da98-1b3c3008c2ea.png)
来ましたね。

```json:result
[{
    "faceId": "f61ae554-321b-41c0-b828-9bee6748329d",
    "candidates": [{
        "personId": "b90fda6e-****-****-****-e89d66e45272",
        "confidence": 0.92787
    }]
}]
```

`candidates[0]`の`personId`がグループ内で最も類似していた顔で、`confidence`が類似度です。
類似度は0～1で出力されるので、百分率に直してあげると、一致率は_**92.787%**_！100枚でこれはなかなかいいのでは…。
![verify-face1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/e31bf6de-6cd1-1f3d-f3be-cfcef19e54b9.png)

#### マスクをしてみる
今のご時世、マスクは欠かせないですよね。2枚目の画像でどれくらいの精度が出るのか試してみました。
![verify-face2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/0efa38d2-2cd5-3d26-c413-bd59d1593f3e.png)
一致率は_**72.34%**_！全体としてみるとやはり精度は低いですが、所詮大学関係者だけなのでキャンパス毎考えても多くても1,000人程度でしょう。関係者だけなら十分識別がつく一致率ではないでしょうか。
もしあれなら認証時の画像も登録していけば…。

## Node-REDに戻ります
### 全体図
テスト環境でのフローはこんな感じです。
**※`node-red-contrib-aedes`と`node-red-node-mysql`をインストール済み。**
![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1596729/236dd877-c0f1-3999-f4a4-74682cc01f2d.png)
顔認証のテストと同じ順にノードを並べてあるだけです。MySQL設定や詳しいノードの説明は次回、本番環境で実装する際に説明します。

## お疲れさまでした
大半が完成しましたね。次の記事でテスト＆ノード・DBの詳しい説明をしていきます。
次の記事は次の授業の日以降になるので、6/11以降の更新になります。お待ちいただけると幸いです。

## 追記 2021/06/05 21:10
やっぱり気になるのがパフォーマンスです。というわけで一連の動作が終了するまでの時間を測定してみました。
_8726ms_。うーん…さすがに時間かかりすぎでは…
実機で行う写真撮影はPythonと違って高速なので、もうちょっと改善されるとは思います。さすがに8秒もかかってたら行列出来ちゃう（笑）

前: [学生証と顔認証で本人確認してみる [2] 〜Face APIにユーザーを覚えさせよう〜](https://qiita.com/Tateshiki0529/items/bd6c38cb193d65235d71)
次: ~~学生証と顔認証で本人確認してみる [4] 〜実際に使ってみよう〜 (仮)~~ (執筆中)