echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

Micorosoft Cognitive Serviceの「Face API」をXamarin.Formsで使用する

概要

昨日(2018/11/17)、「初心者向けXamarinハンズオン」に参加したのですが、そこMicrosoft社の「Azure Face API」(顔検出・認識・分析API)を試してきたので、メモ。

イベントページ:https://jxug.connpass.com/event/96679/

※すでに終了してます。

使用方法

公式サイトから、下記いずれかのアカウントを取得する。

※この記事の内容は、「7日間試用版」で実施。

公式サイト:https://azure.microsoft.com/ja-jp/services/cognitive-services/face/

コーディング

公式サイトの左側ツリーの「クイックスタート」内に記載されている、

上記サンプルコードのうち、該当する方を参考にコーディングする。

※本記事は「クライアントSDK使用」にて実施。

サンプルソース

下記を参照。

※下記ソースは、「初心者向けXamarinハンズオン」の下記「本家リポジトリ」の

  • HandsOnLab/Start/DevDaysSpeakers/DevDaysSpeakers.Shared/View/DetailsPage.xaml.cs

の内容を、「手順書」の内容を基に編集したものです。

本家リポジトリhttps://github.com/jxug/dev-days-labs-ja/tree/master/hands-on

手順書:https://github.com/jxug/dev-days-labs-ja/tree/master/hands-on

※コメントが記載してない箇所は、「Xamarinハンズオン」に関係しますが「Face API」には直接関係ない処理です。

using System;
using DevDaysSpeakers.Model;
using Xamarin.Essentials;
using Xamarin.Forms;

// Face API関連のインポート
using Microsoft.Azure.CognitiveServices.Vision.Face;
using Microsoft.Azure.CognitiveServices.Vision.Face.Models;

using System.Threading.Tasks;
using System.Collections.Generic;

namespace DevDaysSpeakers.View
{
    public partial class DetailsPage : ContentPage
    {
        // エントリポイント
        private const string faceEndpoint =
            "https://westcentralus.api.cognitive.microsoft.com";

        // 取得したキー(キー1またはキー2)
        private const string subscriptionKey = "(Input Your Key)";

        // 取得したい(顔の)情報を配列で設定。
        private static readonly FaceAttributeType[] faceAttributes =
            { FaceAttributeType.Age, FaceAttributeType.Gender, FaceAttributeType.Emotion };

        readonly Speaker speaker;

        public DetailsPage(Speaker speaker)
        {
            InitializeComponent();

            SetActivityIndicatorProperty(false);

            this.speaker = speaker;
            BindingContext = this.speaker;

            ButtonSpeak.Clicked += ButtonSpeak_Clicked;
            ButtonWebsite.Clicked += ButtonWebsite_Clicked;
            ButtonDetectFace.Clicked += ButtonDetectFace_Clicked;
        }

        private async void ButtonSpeak_Clicked(object sender, EventArgs e)
        {
            await TextToSpeech.SpeakAsync(this.speaker.Description);
        }

        private void ButtonWebsite_Clicked(object sender, EventArgs e)
        {
            if (speaker.Website.StartsWith("http"))
                Device.OpenUri(new Uri(speaker.Website));
        }

        // 「顔を検出」ボタンクリック処理
        private async void ButtonDetectFace_Clicked(object sender, EventArgs e)
        {
            // FaceClientクラスの設定
            var faceClient = new FaceClient(
                new ApiKeyServiceClientCredentials(subscriptionKey),
                new System.Net.Http.DelegatingHandler[] { });
            faceClient.Endpoint = faceEndpoint;

            // インターネット上の顔画像ファイルのパス。(speaker.Avaterにパス情報が格納されています。)
            var remoteImageUrl = speaker.Avatar;

            // ローカル上の顔画像ファイルのパス
            // var localImagePath = @"<LocalImage>";

            try
            {
                SetActivityIndicatorProperty(true);

                // リモートの顔画像から情報を取得。
                // (ローカルの場合は「DetectWithStreamAsync()」メソッドを使用。)
                IList<DetectedFace> faceList = await faceClient.Face.DetectWithUrlAsync(
                    remoteImageUrl, true, false, faceAttributes);

                // 取得できなかった場合
                if (faceList.Count == 0 || faceList == null)
                    return;

                SetActivityIndicatorProperty(false);

                // 取得できた場合、そこから情報(年齢・性別・感情(幸福度))を取得し、メッセージボックスを表示。
                var age = faceList[0].FaceAttributes.Age;
                var gender = faceList[0].FaceAttributes.Gender;
                var emotion = (faceList[0].FaceAttributes.Emotion.Happiness * 100.000).ToString();

                var message = string.Format("年齢:{0}、性別:{1}、幸福度:{2} %", age, gender, emotion);
                await DisplayAlert("FaceAPI", message, "OK");
            }
            catch (APIErrorException exApi)
            {
                throw new Exception(exApi.Message.ToString());
            }
            catch (Exception ex)
            {
                await DisplayAlert("FaceAPI Exception", ex.ToString(), "OK");
            }
            finally
            {
                SetActivityIndicatorProperty(false);
            }
        }

        private void SetActivityIndicatorProperty(bool value)
        {
            AILoading.IsRunning = value;
            AILoading.IsVisible = value;
        }
    }
}

ポイントとしては、

※下記のインポート(using)

※取得したい(顔の)情報(FaceAttributeType)をFaceAttributeType配列で設定。

FaceAtteributeについては、下記ページが参考になります。

参考ページ:Microsofrt AzureのFace APIを使って笑顔をAIに判断してもらおう

※エントリポイント、キーの設定

※リモート/ローカル画像に応じたメソッド実施(DetectWithUrlAsync/DetectWithStreamAsync)

でしょうか。

ハマった点

  • Azureアカウントの場合、EntryPointのURLは公式ソースと違い「国・地域」を反映させたものじゃないとダメ。 (7日間試用版の場合、公式ソース同様「westcentralus」で問題ないです。)

  • 発行されるEntryPointのURLの末尾に「Face/(バージョン)」と書かれているが、実際には「Face/(バージョン)」は不要。(ドメイン名まででよい。てか、公式ソースがそうなってるし...ちゃんと読めよ...)

実行結果

f:id:Makky12:20181118185932j:plain

てか、Face API(Cognitive Service)に限らず、Azureとか、どんどん触れていきたいと思いました。