Webカメラ + Azure Logic Apps + Azure Face API で訪問記録

# はじめに
Azureのサービスを利用してWebカメラの前に現れた人を記録する環境を構築したため、一例として記載します。

# 構築イメージ
![observation.png](https://qiita-image-store.s3.amazonaws.com/0/109302/4815cf6e-854f-7617-c180-c6a1b1b594ef.png)

- カメラの画像は、Webカメラ + Raspberry Pi + Windows 10 IoT Core + UWP で定期的にAzure Storageにアップロードするようにしました。
- Azure Functionsを
    - トリガー: Azure Storageへの格納
    - アクション: Logic Appsをキックするように設定しました。[Azure Functionsの設定](#azurefunctionsの設定)
- Logic AppsはFace APIのDetect facesを使用して画像に人がいるか否かを判断しています。存在した場合はDocumentDBにjsonと画像を格納します。

# [Azure Storageの設定](http://qiita.com/kwhrkzk/items/1e56dd127879dcec20c6#azure-storage%E3%81%AE%E8%A8%AD%E5%AE%9A)

# [Webカメラの設定](http://qiita.com/kwhrkzk/items/1e56dd127879dcec20c6#%E7%94%BB%E5%83%8F%E9%80%81%E4%BF%A1%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AE%E8%A8%AD%E5%AE%9A)

# Azure Functionsの設定
参考
https://docs.microsoft.com/ja-jp/azure/connectors/apis-list
https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-azure-functions
https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-http-endpoint

[ベースのお話はこちらに記載しています。](http://qiita.com/kwhrkzk/items/1e56dd127879dcec20c6#azure-functions%E3%81%AE%E8%A8%AD%E5%AE%9A)
今回はアクションだけが異なります。
そもそもとして、Logic Appsが直接Storageのトリガーを受けれれば良かったのですが、2017/03時点ではトリガーは[ポーリングトリガー](https://docs.microsoft.com/ja-jp/azure/connectors/apis-list)しか用意されていませんでした。
![blob.png](https://qiita-image-store.s3.amazonaws.com/0/109302/dbf3eb49-443e-94e6-063e-dc24470b1db1.png)
![blob2.png](https://qiita-image-store.s3.amazonaws.com/0/109302/2337e5ce-e714-d4b1-c9a1-80e0aaa72e0f.png)

Azure FunctionsにはAzure Storageの変更をトリガーにする仕組みが存在していたため、Azure Functions -> Azure Logic Appsを起動するようにしました。
([Azure Logic AppsからAzure Functionsを動作させる方法はこちら](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-azure-functions))
Azure FunctionsからAzure Logic Appsを呼ぶためのトリガーとして[要求(Request)](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-http-endpoint)を使用しました。
![request.png](https://qiita-image-store.s3.amazonaws.com/0/109302/0b8f0bd0-231d-0475-a34b-fb24afef6a55.png)
この要求をトリガーとして選択してJSONスキーマを入力すると図のようにPOST用のURLが発行されるため、そのURLに対してPOSTするようにAzure Functionsのアクションを記載すればトリガーにできました。

```csharp:run.csx
#r "Microsoft.WindowsAzure.Storage"
#r "Newtonsoft.Json"
#r "System.Net"
#r "Newtonsoft.Json"

using System;
using System.Text;
using Newtonsoft.Json;
using System.Net.Http;
using Microsoft.WindowsAzure.Storage.Blob;

public static void Run(ICloudBlob image, TraceWriter log)
{
    var httpClient = new System.Net.Http.HttpClient();

    var payload = new {
        url = image.Uri.ToString()
    };

    var stringPayload = Newtonsoft.Json.JsonConvert.SerializeObject(payload);

    var httpContent = new System.Net.Http.StringContent(stringPayload, System.Text.Encoding.UTF8, "application/json");

    httpClient.PostAsync("https://prod-30.japaneast.logic.azure.com:443/workflows/~~~", httpContent).Wait();
}
```

要求本文のJSONスキーマは、サンプルのペイロード～～のリンクをクリックして、今回格納したJSONの例を貼り付けると勝手に生成してくれました。今回は

```json
{url: "http://~~~"}
```

というjsonを定義しています。

# Logic Appsの設定
Azure ポータルからLogic Appsを作成します。
また、Logic AppsからFace APIを使用するため、Cognitive Services APIs (プレビュー)も作成します。
Logic Apps デザイナー画面に遷移して要求をトリガーとして選択して次のアクションにDetect facesを選択します。
![faceapi.png](https://qiita-image-store.s3.amazonaws.com/0/109302/2532a4fb-beac-a1d9-9412-cb64b5be4690.png)

選択するとAPI KEYを求められるため、Cognitive Services APIs (プレビュー)からコピーして貼り付けて作成します。(Cognitive Services APIs内Keysを選択すると表示されます。)
![apikey.png](https://qiita-image-store.s3.amazonaws.com/0/109302/af50e663-9888-545a-cdbe-1b5b4051920e.png)

次に解析する画像の位置を指定します。ここでは要求のjsonで取得するurlをそのまま指定します。jsonで定義した要素名が候補として現れるのは便利だと思いました。
![detect.png](https://qiita-image-store.s3.amazonaws.com/0/109302/b819e187-b06f-a4ac-c236-45cb6cfe3e54.png)

これ以降のアクションについては今回はDocumentDBにjsonと画像のurlを格納するだけにしました。やりたいことによってこの後の解析処理が変わってくると思います。
![documentdb.png](https://qiita-image-store.s3.amazonaws.com/0/109302/99066f84-bf56-ab19-4a5e-5c0d83cc2dee.png)

# 構築後の感想
画像解析がかなり手軽に使用できるのが素晴らしいと思いました。
今回はただの人検知だけでしたが、特定の誰かが訪問したら通知だとか、一定期間カメラの前を通り過ぎた人の人数を算出するとかできそうです。
Emotion APIを使用すれば、観客の笑った人数を算出するなんてことも可能かと。

Azure Logic Appsに存在しないトリガーもHTTP POSTでキックすれば良いのでどうとでもなりそうです。
(Storageのプッシュトリガーくらいは用意しておいて欲しかったですけど)

Logic Appsの動作の確認は大変でした。
Azure Functionsのように入力を指定できないので、自分でPOSTを送信しなくちゃいけなかったです。
その後の処理も長ければ長いほど大変だと思います。
ロジックアプリコードビューで直接中身をいじれますが、C#とは別物でした。
これがC#とかで書けてLogic Appsに変換されるとかになるとかなり楽になる気がします。