人工知能パーツ Microsoft Cognitive Services を使った表情分析アプリを作ろう！ (Emotion API × Bot Framework 編)

#Microsoft Cognitive Services を使った表情分析 BOT
Microsoft Cognitive Services は 画像、文章、言語、情報を処理する機能を API 経由で利用できるサービスです。
Cognitive Services の一つである Emotion API では、画像を分析して人間の顔やその表情を数値化し、結果を JSON 形式で取得することができます。

今回は オンライン画像 (URL) を入力すると、顔の表示位置と表情分析スコアを表示する BOT を作成します。ベースは Microsoft Bot Framework (v3.0) テンプレートを利用し、Cognitive Services Emotion API C# ライブラリーを用いて呼び出しを行います。
> JavaScript で Emotion API を呼び出す方法については、[Emotion API × JavaScript 編](http://qiita.com/annie/items/96b37ef94885510c1b6b) をご覧ください。

この BOT アプリは Bot Framework Channel Emulator を使ってローカル環境で稼働確認することが可能です。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_01.png)

また、Web 公開 & Bot Framework に登録すると、埋め込み可能な Web Chat が利用できます。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_02.png)

#Bot Framework & Cognitive Services 利用に必要な環境、サブスクリプションの準備

##開発環境
###Visual Studio 2015、Bot Framework Template & Bot Framework Channel Emulator
無償の Visual Studio 2015 Community でOKなので、既存の環境がない場合は、ダウンロードしてインストールします。
[Visual Studio 2015 Community ダウンロードサイト](https://www.visualstudio.com/ja-jp/products/visual-studio-community-vs.aspx)
[Visual Studio 2015 用の C# テンプレート](http://aka.ms/bf-bc-vstemplate)
[Bot Framework Channel Emulator (Windows版)](https://aka.ms/bf-bc-emulator) ※Mac/Linux は [Console版](https://aka.ms/bfemulator) をご利用ください
>Bot Framework 開発環境の作り方は、[Microsoft Bot Framework v3.0 からはじめる BOT 開発: Bot Framework を使うための開発環境](http://qiita.com/annie/items/edc26c0ee9603e84a2e4#bot-framework-%E3%82%92%E4%BD%BF%E3%81%86%E3%81%9F%E3%82%81%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83) をご覧ください。

##Microsoft アカウント
Cognitive Services (と必要に応じて Azure) サブスクリプションの申し込みに必要ですので、持っていない場合は取得しておきます。
>[Microsoft アカウント登録手続き](https://www.microsoft.com/ja-jp/msaccount/signup/default.aspx)

##Cognitive Services サブスクリプション
試用は無料ですが、こちらの手順でサブスクリプション申し込みが必要です。
>申し込み方法は [Microsoft Cognitive Services サブスクリプション申し込み編](http://qiita.com/annie/items/ba6392b7d1a7647adc4b) をご覧ください。


#BOT アプリの実装
##Bot アプリケーションの作成
[Visual Studio テンプレートから Bot アプリケーションの作成](http://qiita.com/annie/items/edc26c0ee9603e84a2e4#visual-studio-%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%8B%E3%82%89-bot-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90) と同じ手順で、新規 Bot アプリケーションを作成します。今回は EmotionBot という名称で作成しています。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_03.png)


##Cognitive Services Emotion API の C# ライブラリーのインストール
ソリューションエクスプローラーでプロジェクト名 (ソリューションの下) を右クリックして、*NuGet パッケージの管理* を選択します。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_04.png)

*参照* をクリックし、*project oxford* と入力して検索します。*Microsoft.ProjectOxford.Emotion* を選択し、*インストール* をクリックしてインストールします。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_05.png)

Emotion API のライブラリーと、依存関係のあるライブラリーが合わせて表示されますので、*OK* をクリックしてインストールします。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_06.png)

インストールが終了したら、NuGet のウインドウを閉じます。

##会話のハンドリングの記述
*Controllers* フォルダー をクリックして開きます。*MessagesController.cs* をクリックして表示し、こちらを編集していきます。

冒頭に、先ほど追加した Microsoft.ProjectOxford.Emotion を追加します。合わせて System.Collections.Generic も追加しておきます。

```MessagesController.cs
using Microsoft.ProjectOxford.Emotion;
using Microsoft.ProjectOxford.Emotion.Contract;
using System.Collections.Generic;
```
>[2017/3/25追記]
Bot Framework テンプレートのバージョンによっては、System.Linq が追加されていない場合がありますので、こちらも追加してください。


デフォルトで記述されている Post 部分を削除し、下記の通り置き換えます。
メッセージやり取りを行う ConnectorClient を生成、デフォルトの回答を作成して(Activity.CreateReply)、返答する(ConnectorClient.Conversations.ReplyToActivityAsync)、という動作を行うコードです。

```MessagesController.cs
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{

    // メッセージやり取りを行う ConnectorClient を生成
    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));

    // Emotion API の Subscription Key をセット
    // Emotion API を Call する EmotionServiceClient を生成
    // 入力値(URL) を元に Emotion API を Call
    // ※次以降の項目で作成します

    // デフォルトの返答 (初回、または写真判定ができなかったとき))
    Activity reply = activity.CreateReply("顔の表情を判定します。写真のURLを送ってね。");

    // Call 結果を元に 返答を作成
    // ※次以降の項目で作成します

    // メッセージ、および http ステータス Accepted(=200) を返答
    await connector.Conversations.ReplyToActivityAsync(reply);
    return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);

}
```

Crtl+S または ツールバーから *ファイル* ＞ *(ソリューション名)の保存* をクリックして *MessagesController.cs* を保存します。

###BOT の動作確認
ここで一旦 BOT の動作確認を行います。、F5 または デバック＞デバックの開始 をクリックして、プロジェクトのビルドおよび起動を行います。ブラウザが起動して Bot Framework のデフォルト画面が表示されたら、Bot Framework Channel Emulator を起動してアクセスを行います。
Bot Framework Channel Emulator の上部中央にある *Bot Url* に、起動しているブラウザと同じ URL (デフォルトでは http://localhost:xxxx) に **/api/messages** を追加したアドレス (http://localhost:xxxx/api/messages) を指定します。
何か文字を入力して送信すると、Activity.CreateReply で指定したデフォルトの回答が返信されることを確認してください。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_07.png)


##Emotion API を呼び出すロジックの記述
Emotion API の サブスクリプションキー を予め emotionApiKey にセットします。
それを使って EmotionServiceClient を作成、EmotionServiceClient.RecognizeAsync で呼び出して、得られる結果を emotionResult に取得します。

```MessagesController.cs
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{

    // メッセージやり取りを行う ConnectorClient を生成
    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));

    // Emotion API の Subscription Key をセット
    // お持ちの Subscription Key を YOUR_SUBSCRIPTION_KEY 部分にコピーしてください
    const string emotionApiKey = "YOUR_SUBSCRIPTION_KEY";

    // Emotion API を Call する EmotionServiceClient を生成
    EmotionServiceClient emotionServiceClient = new EmotionServiceClient(emotionApiKey);
    Emotion[] emotionResult = null;

    // 入力値(URL) を元に Emotion API を Call
    try
    {
        emotionResult = await emotionServiceClient.RecognizeAsync(activity.Text);
    }
    catch (Exception e)
    {
        emotionResult = null;
    }

    // デフォルトの返答 (初回、または写真判定ができなかったとき))
    Activity reply = activity.CreateReply("顔の表情を判定します。写真のURLを送ってね。");

    // Call 結果を元に 返答を作成
    // ※次以降の項目で作成します

    // メッセージ、および http ステータス Accepted(=200) を返答
    await connector.Conversations.ReplyToActivityAsync(reply);
    return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);

}
```

##表情スコアを回答にセットするロジックの記述
得られた8種類の表情スコアを KeyValuePair に代入して、スコア数値が一番大きいものを取得して回答にセットします。

```MessagesController.cs
public virtual async Task<HttpResponseMessage> Post([FromBody] Activity activity)
{

    // メッセージやり取りを行う ConnectorClient を生成
    :
    中略
    :
    // デフォルトの返答 (初回、または写真判定ができなかったとき))
    Activity reply = activity.CreateReply("顔の表情を判定します。写真のURLを送ってね。");

    // Call 結果を元に 返答を作成
    if (emotionResult != null)
    {
        //表情スコアを取得
        //Emotion[] emotionScores = emotionResult[0].Scores;
        var emotionScores = emotionResult[0].Scores; //20170325:ライブラリ変更により var に変更

        //取得したスコアを KeyValuePair に代入、スコア数値の大きい順に並び替える
        IEnumerable<KeyValuePair<string, float>> emotionList = new Dictionary<string, float>()
        {
            { "怒ってる", emotionScores.Anger},
            { "軽蔑してる", emotionScores.Contempt },
            { "うんざりしてる", emotionScores.Disgust },
            { "怖がってる", emotionScores.Fear },
            { "楽しい", emotionScores.Happiness},
            { "特になし", emotionScores.Neutral},
            { "悲しい", emotionScores.Sadness },
            { "驚いてる", emotionScores.Surprise}
        }
        .OrderByDescending(kv => kv.Value)
        .ThenBy(kv => kv.Key)
        .ToList();

        //スコア数値の一番大きい表情を取得してメッセージにセット
        KeyValuePair<string, float> topEmotion = emotionList.ElementAt(0);
        string topEmotionKey = topEmotion.Key;
        float topEmotionScore = topEmotion.Value;

        reply = activity.CreateReply
            (
                "顔の表情を判定しました。" 
                + (int)(topEmotionScore * 100) + "% " + topEmotionKey + "顔だと思うよ。"
            );
    }

    // メッセージ、および http ステータス Accepted(=200) を返答
    :
    中略
    :

}
```

忘れずに *MessagesController.cs* を保存しておきます。

#アプリケーションの動作確認
F5 または デバック＞デバックの開始 をクリックして、プロジェクトのビルドおよび起動を行います。ブラウザが起動して Bot Framework のデフォルト画面が表示されたら、Bot Framework Channel Emulator を起動してアクセスを行います。
まず何かメッセージを入力すると、デフォルトの回答が返信されます。その後、オンライン画像の URL (例えばこちら↓) をコピーして送信します。
https://emotionwebsto.blob.core.windows.net/handson/emotionweb_happiness.jpg

分析結果の回答が返信されれば、BOT アプリケーションは完成です。
![](https://msdnshared.blob.core.windows.net/media/2016/09/bluesky_20160913_01.png)

#Appendix
同じソースを Azure Logic App で Web 公開し、Bot Framework に登録を行って、利用可能になった Web Chat を貼り付けています。動作確認にご利用ください。
http://emotionbotsample.azurewebsites.net/
>Azure での Web 公開、Bot Framework の登録、Web Chat の設定方法については、[Microsoft Bot Framework v3.0 からはじめる BOT 開発: Azure で Web 公開＆お手軽 Web Chat を試す](http://qiita.com/annie/items/590fa480719ed93998df) をご覧ください。

また、完成形のソースコードを GitHub にて公開しました。
https://github.com/a-n-n-i-e/CognitiveEmotionAPI-EmotionBot