Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

Microsoft Cognitive Services を使った表情分析 Web アプリ (.NET Core 版)

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

今回は オンライン画像 (URL) を入力すると、顔の表示位置と表情分析スコアを表示する Web アプリを作成します。ベースは Microsoft .NET Core (v1.1) の Web アプリケーションテンプレートを利用し、Cognitive Services Emotion API C# ライブラリーを用いて呼び出しを行います。

Bot Framework を利用した BOT 作成方法は Emotion API × Bot Framework 編 をご覧ください。
JavaScript で Emotion API を呼び出す方法については、Emotion API × JavaScript 編 をご覧ください。

この Web アプリは Visual Studio からローカル環境で稼働確認することが可能です。

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

開発環境

Visual Studio 2017

無償の Visual Studio 2017 Community でOKなので、既存の環境がない場合は、ダウンロードしてインストールします。
Visual Studio 2017 Community ダウンロードサイト

Microsoft アカウント

Cognitive Services (と必要に応じて Azure) サブスクリプションの申し込みに必要ですので、持っていない場合は取得しておきます。

Microsoft アカウント登録手続き

Cognitive Services サブスクリプション

試用は無料ですが、こちらの手順でサブスクリプション申し込みが必要です。

申し込み方法は Microsoft Cognitive Services サブスクリプション申し込み編 をご覧ください。

Web アプリの実装

Visual Studio 2017 による .NET Core アプリケーションの作成と構成

Visual Studio テンプレートから .NET Core アプリケーションの作成

Visual Studio を起動し、上部のメニューバーから ファイル>新規作成>プロジェクト を選択します。

Visual Studio > Visual C# > .NET Core をクリック、中央の列に表示される [ASP.NET Core Web アプリケーション (.NET Core)] をクリックします。ひとまず、(プロジェクトの)名前、(プロジェクトファイルが保存される)場所、ソリューション名 はデフォルトのままで右下の OK をクリックします。

ASP.NET Core テンプレートから [Web アプリケーション] を選択、[OK] をクリックすると、必要なコンポーネントが読み込まれ、プロジェクトが構成されます。

Cognitive Services Emotion API の C# ライブラリーのインストール

ソリューションエクスプローラーでプロジェクト名 (ソリューションの下) を右クリックして、NuGet パッケージの管理 を選択します。

参照 をクリックし、project oxford と入力して検索します。Microsoft.ProjectOxford.Emotion を選択し、インストール をクリックしてインストールします。

.NET Core のバージョンによって Microsoft.ProjectOxford.Emotion が対応していない場合は、Microsoft.ProjectOxford.Emotion.DotNetCore をご利用ください。

Emotion API のライブラリーと、依存関係のあるライブラリーが合わせて表示されますので、OK をクリックしてインストールします。

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

不要なページの削除

Views フォルダー をクリックして開きます。Views > Home フォルダー 配下のファイルをすべて選択し、delete または 右クリック>削除 をクリックして削除します。

Views > Shared フォルダー をクリックして開き、_Layout.cshtml をクリックして開きます。
36,37行目にある About, Contact のページへのリンクを削除します。この2行を削除する、またはコメントアウトします。

このテンプレートは Home, About, Contact の3ページで構成されており、この部分でナビゲーションバーを設定しています。今回は Home のみ使用します。

表示ページの作成

Views > Home フォルダー を右クリック、追加 > 新しい項目 をクリックします。

新しい項目の追加 画面で、画面中央の項目から MVC ビューページ を選択、画面下部の名前が Index.cshtml になっているのを確認して、[追加] をクリックします。

同様の手順で Result.cshtml という名前で MVC ビューページを追加します。

適時 Crtl+S または ツールバーから ファイル(ソリューション名)の保存 をクリックして保存しておきます。

画像 URL を取得して結果を表示するページの作成

画像 URL 取得ページ (Index.cshtml)

Views > Home フォルダー に作成した Index.cshtml をクリックして表示し、こちらを編集します。内容を一旦全部削除し、下記の内容に書き換えます。

Index.cshtml
@{
    ViewData["Title"] = "Microsoft Cognitive Services - Emotion API Sample";
}

<div class="row">
    <div class="col-md-12">
        <h2>Microsoft Cognitive Services - Emotion API Sample</h2>
        <p>分析したい画像のURLを入力してください。</p>
        @using (Html.BeginForm(
                            "Result",
                            "Home",
                            null,
                            FormMethod.Post
                            ))
        {
            @Html.TextBox("url", "", new { size = 100 })
            <input type="submit" value="分析する" />
        }
    </div>
</div>

画像 URL を Textbox で取得し、ボタンをクリックすると、Result.cshtml に遷移します。
[変更前]

[変更後]

結果表示ページ (Result.cshtml)

Views > Home フォルダー に作成した Result.cshtml をクリックして表示し、こちらも同様に内容を一旦全部削除し、下記の内容に書き換えます。

Result.cshtml
@{
    ViewData["Title"] = "Microsoft Cognitive Services - Emotion API Sample";
}

<div class="row">
    <div class="col-md-12">
        <h2>Microsoft Cognitive Services - Emotion API Sample</h2>
        <p>分析したい画像のURLを入力してください。</p>
        @using (Html.BeginForm(
                            "Index",
                            "Home",
                            null,
                            FormMethod.Post
                            ))
        {
            @Html.TextBox("url", "", new { size = 100, disabled = "disabled" })
            <input type="submit" value="リセット" />
        }
    </div>
</div>
<div class="row">
    <h3>@ViewData["Result"]</h3>
    <div class="col-md-2">
        <table border="0" cellpadding="0">
            <tr>
                <td>怒り</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Anger"])</td>
            </tr>
            <tr>
                <td>軽蔑</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Contempt"])</td>
            </tr>
            <tr>
                <td>ムカつき</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Disgust"])</td>
            </tr>
            <tr>
                <td>恐れ</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Fear"])</td>
            </tr>
            <tr>
                <td>喜び</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Happiness"])</td>
            </tr>
            <tr>
                <td>無表情</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Neutral"])</td>
            </tr>
            <tr>
                <td>悲しみ</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Sadness"])</td>
            </tr>
            <tr>
                <td>驚き</td>
                <td>: </td>
                <td>@Html.Encode(ViewData["Surprise"])</td>
            </tr>
        </table>
    </div>
    <div class="col-md-10">
        <img src="@ViewData["Url"]" width="400" />
    </div>
</div>

Result.cshtml も上の部分は Index.cshtml とほぼ同様です。Textbox を "disabled" に設定、ボタンをクリックすると、Index.cshtml に戻ります。
[変更後]

Emotion API を呼び出すロジックの記述

Index.schtml でボタンが押され、Result.schtml に遷移する際に Emotion API を呼び出して結果を取得、整形する動作を追加します。

HomeController.cs に Result() を追加

Controllers フォルダー をクリックして開きます。HomeController.cs をクリックして表示し、こちらを編集していきます。

冒頭に、先ほど追加した Microsoft.ProjectOxford.Emotion を追加し、デフォルトで記述されている About(), Contact() を削除します。

HomeController.cs
using Microsoft.ProjectOxford.Emotion;
using Microsoft.ProjectOxford.Emotion.Contract;

Result ページが呼び出される際の動作を、Result() として追加します。フォームからの入力(URL)を取得します。合わせて Emotion API を利用するための Subscription Key も設定しておきます。

HomeController.cs
[HttpPost]
public async Task<IActionResult> Result(string url)
{
    // 取得可否を設定
    var res = "";
    // フォームからの入力(URL)を取得
    ViewData["Url"] = url;

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

    // Emotion API を Call する EmotionServiceClient を生成
    // Emotion API を呼び出して結果を取得
    // 呼び出し結果を元に表示内容を作成
    // 結果を表示
    // ※次以降の項目で作成します
}

Emotion API の呼び出し

Subscription Key を使って EmotionServiceClient を生成、RecognizeAsync で呼び出す部分を記述します。

HomeController.cs
[HttpPost]
public async Task<IActionResult> Result(string url)
{
     : (中略)
    // Emotion API を Call する EmotionServiceClient を生成
    var eClient = new EmotionServiceClient(eApiKey);
    // 結果を取得する配列を定義
    Emotion[] eResult = null;

    // Emotion API を呼び出して結果を取得
    try
    {
        eResult = await eClient.RecognizeAsync(url);
    }
        catch (Exception e)
    {
        eResult = null;
    }

    // 呼び出し結果を元に表示内容を作成
    // 結果を表示
    // ※次以降の項目で作成します
}

結果の取得と整形

結果を配列に取得し、小数点6桁に整形して ViewData にセットします。
呼び出しに失敗する場合 (サブスクリプションキー不適合など) は eResult == null で検出します。呼び出しに成功した場合でも、結果なし (人間の顔を検出できなかった場合など) は eResult の読み取り例外で検出しています。

HomeController.cs
[HttpPost]
public async Task<IActionResult> Result(string url)
{
     : (中略)
    // 呼び出し結果を元に表示内容を作成
    if (eResult != null)
    {
        //表情スコアを取得
        try
        {
            res = "結果:";
            var eScores = eResult[0].Scores;

            // 検出された表情スコアをセット
            ViewData["Anger"] = Math.Round(eScores.Anger, 6).ToString("0.000000");
            ViewData["Contempt"] = Math.Round(eScores.Contempt, 6).ToString("0.000000");
            ViewData["Disgust"] = Math.Round(eScores.Disgust, 6).ToString("0.000000");
            ViewData["Fear"] = Math.Round(eScores.Fear, 6).ToString("0.000000");
            ViewData["Happiness"] = Math.Round(eScores.Happiness, 6).ToString("0.000000");
            ViewData["Neutral"] = Math.Round(eScores.Neutral, 6).ToString("0.000000");
            ViewData["Sadness"] = Math.Round(eScores.Sadness, 6).ToString("0.000000");
            ViewData["Surprise"] = Math.Round(eScores.Surprise, 6).ToString("0.000000");
        }
        catch (Exception e)
        {
            res = "検出できませんでした";
        }
    }
    else
    {
        res = "API の呼び出しに失敗しました";
    }

    // 結果を表示
    ViewData["Result"] = res;
    return View();
}

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

アプリケーションの動作確認

F5 または デバック>デバックの開始 をクリックして、プロジェクトのビルドおよび起動を行います。
ブラウザが起動したら、オンライン画像の URL (例えばこちら↓) をコピーして送信します。
https://msdnshared.blob.core.windows.net/media/2017/05/bluesky_20170521_002.jpg

分析結果の回答が返信されれば、アプリケーションは完成です。

EmotionServiceClient の生成で失敗する場合は、NuGet Microsoft.ProjectOxford.Emotion を一旦削除し、Microsoft.ProjectOxford.Emotion.DotNetCore をインストールしてご利用ください。(ソースコードはそのままで大丈夫です)

Appendix

同じソースを Azure Web App で Web 公開しています。動作確認にご利用ください。
http://emotionweb-netcore.azurewebsites.net/

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした