Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

Xamarin で Microsoft Cognitive Services を使うには - その1

こんにちは。エクセルソフトの田淵です。

Cogbot Advent Calendar 2018 - Qiita の 21日目のエントリーです。

qiita.com

明日もこのエントリーの続きでその2として書きたいと思います。

サンプルプロジェクトは以下に置いておきます。興味があれば見てみてください。

github.com

経緯

先日、Xamarin Advent Calendar 2018 - Qiita の 2日目の記事として、AWS Rekognition を使って顔認識を使うエントリーを書きました。

ytabuchi.hatenablog.com

上記記事の経緯は、先日の「初心者向けXamarinハンズオン! #5」Microsoft Cognitive Services の Face を使ったアプリ を作ってドキュメントをアップデートしたので、同じことを AWS でやったらどんな感じかな?というものでした。せっかく Face をやったので、その他の沢山のサービスも使ってみたいな。ということで、面白そうだったり、C#SDK があるサービスを色々触ってみることにします。

Cognitive Services を C#SDK で使う時の書き方ってこんな感じか。という入口にしてもらえると嬉しいです。

2018/12/20 時点での情報です。Cognitive Services は結構早いペースでサービスの統廃合や名称が変わったりするのでご注意ください。

Congnitive Services を使うための準備

大前提として、使うにはどうすれば良いか?という点ですが、Cognitive Services の各種ページで「〜を試す」って青いボタンをクリックすると以下の画像が出てきます。

f:id:ytabuchi:20181221115854p:plain:w600

  • 既存の Azure アカウント
  • 無料の Azure アカウント(評価アカウント)
  • ゲスト

で使えます。クレジットカードの登録は必要ですが無断で課金されることはないので、アカウントをお持ちでない方は無料の Azure アカウントを作っておくと良いでしょう。

IaaS には無料のプランはないのですが、例えば Web Apps のような PaaS の各種サービスであれば大体無料プランが用意されているので、ちょっと試したい。という時に便利です🙆🏻‍♂️

Azure のアカウントで Azure Portal にログインして、Cognitive Services 向けのリソースグループを作っておきましょう。このエントリーでは「Cognitive Services」というリソースグループを東南アジアに作成して Cognitive のサービスを纏めています。

f:id:ytabuchi:20181221131341p:plain:w600

各種サービスを作成するときに、「Resource Group」の欄から作成済みのリソースグループを選択してください。

f:id:ytabuchi:20181221132003p:plain:w300

余談ですが、Cognitive Services の各種サービスを作成すると、インスタンスが起動する訳ではなく、アクセスするためのキーを生成しているだけのようです。そのため、このエントリーでは各種サービス名を「〜Key」という名前にしています。

Xamarin で使う前準備

Xamarin.Forms で作っていきますので、Xamarin.Forms がビルドできる環境をご用意ください。

2018年12月現在の Visual Studio 2017 または Visual Studio for Mac の最新版を使っています。

使用する SDK .NET Standard 対応のものが多いので、

  1. 空のソリューションを作成
  2. .NET Standard 2.0 のライブラリプロジェクトを作成
  3. 確認用に .NET Core 2.1 のコンソールプロジェクトを作成
  4. 最後に Xamarin.Forms のプロジェクトを作成

という流れで、以下の構成にしました。各種 Cognitive Services を使う 〜Service クラスをそれぞれ用意している感じです。

f:id:ytabuchi:20181221133854p:plain:w450

動作を確認するたびにスマホでチェックするのも大変なので、ライブラリのコードを書いてコンソールで確認し、動作を確認してから最後に Xamarin.Forms の UI を書く。という流れでやっています。

それではいきましょう!

Cognitive Services とは

azure.microsoft.com

f:id:ytabuchi:20181214162638p:plain:w600

色々な方が解説しているので説明は省きますが、Azure の PaaS を使って AI でなんかした結果を返してくれるサービスです。(雑)

今日のその1 のエントリーは、視覚についてです。

Cognitive Services - Vision(視覚)

視覚の中にはいくつかのサービスがあります。

azure.microsoft.com

視覚サービスによりアプリとサービスがどのように画像やビデオのコンテンツを正確に識別および分析できるようになるかをご覧ください。どのサービスも無料でお試しいただけます。また、次の機能を備え、コンピューター ビジョンに対応したアプリとサービスをすばやく作成できます。

とのこと。AI と言えば!という感じのサービスですよね。

Computer Vision

主に画像解析を行います。

  • 画像の分類
  • 画像内のシーンおよびアクティビティ認識
  • 画像内の有名人とランドマークの認識
  • 画像内の光学式文字認識 (OCR)
  • 手書き認識

この中で、「画像内のシーンおよびアクティビティ認識」と「画像内の光学式文字認識 (OCR)」をやってみましょう。

Computer Vision - 画像内のシーンおよびアクティビティ認識

どんなことをしてくれて、どんなデータが返ってくるか?は以下のデモページの「画像の分析」を見てみてください。

azure.microsoft.com

例えば上記のデフォルトで選択されている電車とホームの画像は、特徴名と値で、「説明」の中に「captions」があり、その「text」が「people waiting at a train station」となっています。画像のアクティビティを認識してくれる。ということですね。

今回は caption の部分を SDK で取得します。

サービス作成

まずはサービスを作成しましょう。

リソース作成のブレードで「Computer Vision」を検索して作成します。

f:id:ytabuchi:20181221133120p:plain:w600

私は以下の設定で作成しました。今後も大体こんな感じで作成していくので、この後の作成時の説明は割愛します。

  • 名前:ComputerVisionKey
  • 場所:東南アジア
  • 価格レベル:F0
  • Resource Group:「Cognitive Services」

作成が終わったらリソースに移動し、Key メニューをクリックすると表示される Key を控えておきましょう。

f:id:ytabuchi:20181221140237p:plain:w600

ドキュメント

Computer Vision のページを開くと、赤枠のあたりに「ドキュメント」と「API」のリンクがあります。

f:id:ytabuchi:20181221134857p:plain:w600

大体どのサービスも同じサイト構成になっていますので、ドキュメントと API を見ながら開発を進めていきます。

画像内のシーンおよびアクティビティ認識は以下のサンプルを元に作っていきましょう。

docs.microsoft.com

当然ですが、API ドキュメント にあるように全て REST API として設計されているため、C# からであれば REST API のエンドポイントを HttpClient で叩けばすむ話なのですが、SDK でラップしてくれているので開発を楽に進められるようになるよ。ということですね。

NuGet パッケージとコード

NuGet から SDK .NET Standard ライブラリプロジェクトに追加します。NuGet パッケージマネージャーで、

Microsoft.Azure.CognitiveServices.Vision.ComputerVision」

を検索してインストールします。2018年12月時点の SDK のバージョンは 3.3.0 です。

詳細はサンプルコードを見てもらうとして、いくつかポイントを説明します。

VisualFeatureTypes

VisualFeatureTypes Enum は取得する情報を指定します。List で用意しておきます。

// 取得する属性を指定
private static readonly List<VisualFeatureTypes> features =
    new List<VisualFeatureTypes>()
{
    VisualFeatureTypes.Categories,
    VisualFeatureTypes.Description,
    VisualFeatureTypes.Tags
};
ComputerVisionClient とエンドポイント

ComputerVisionClient の引数に ApiKeyServiceClientCredentials("KEY") を渡してインスタンス化しています。2018年12月現在公開されている各種 SDK はこの形で Clinet をインスタンス化することが多いようです。

var computerVisionClient = new ComputerVisionClient(new ApiKeyServiceClientCredentials("<ENTER_KEY_HERE>")){ Endpoint = "<ENDPOINT_URI>"};

エンドポイントの URL はサービスを作ったリージョンによって異なりますので、ご注意ください。以下、API ドキュメントから引用します。

AnalyzeImageAsync メソッドと AnalyzeImageInStreamAsync メソッドの language 引数

API リファレンス によると、language パラメーターで英語、ポルトガル語、日本語、簡体中国語に対応しているような記述がありますので、

AnalyzeImageInStreamAsync(imageStream, visualFeatures, details, "ja") と日本語を指定するとちゃんと日本語で結果を返してくれます。

ImageAnalysis クラス

以下のように色々な情報が含まれています。

f:id:ytabuchi:20181221143011p:plain:w450

ただ今回は Caption だけを取得するので、GetCaption メソッドを用意して単純に analysis.Description.Captions[0].Text を返しています。

f:id:ytabuchi:20181221144931p:plain:w300

いい感じですね!

Computer Vision - 画像内の光学式文字認識 (OCR)

次は OCR です。先ほどのデモページ の「画像内のテキストの読み取り」を見てみてください。

OCR については説明不要かと思いますが、API ドキュメント によると Computer VisionOCR は以下の言語に対応しているようです。すごい!

サービス作成

画像認識と同じなので、先ほど作成した KEY を使用します。

ドキュメント

OCR は以下のサンプルを元に作成していきます。

docs.microsoft.com

NuGet パッケージとコード

同じ NuGet パッケージを使用します。

ComputerVisionClient とエンドポイント

別の OcrService クラスの ExtractLocalTextAsync メソッドを用意したので再度記述が必要ですが、中身は同じです。

RecognizePrintedTextInStreamAsync メソッドと OcrLanguages 引数

RecognizePrintedTextInStreamAsync メソッドの引数、1個目は detectOrientation で向きを自動認識してくれるので True が良いでしょう。2個目は画像の Stream で、3個目が言語です。

OcrLanguagesEnum で認識させたい各種言語を指定すれば良いのですが、指定なしで OcrLanguages.Unk(Unkown かな?)の自動認識になります。このままで日本語も認識してくれるので指定なしでも良いと思います。

日本語の表示は英語が混ざることが多いので、その場合はどちらかの認識を捨てなければいけません。

例えば以下のように確実に日本語だけの画像なら

f:id:ytabuchi:20181221154045p:plain:w300

ほぼ正確に読み取ってくれます。素晴らしいですよね!

f:id:ytabuchi:20181221154146p:plain:w300

が、例えば以下のような(こういうかなり小さい字でも読み取れます)日本語と英語が混じっている画像の場合は、英語部分が文字化けした日本語として読み取るか、英語部分のみを読み取るかのどちらかになってしまいます。

f:id:ytabuchi:20181221154225p:plain:w300

しっかりと読み取る場合には、2回言語設定を変えて読み取って比較してミックスする。などの処理が必要になるかもしれません。

OcrResult の処理

読み取り結果の OcrResult には読み取った区分ごとに Regions があり、その中に Lines があり、最後に Words があります。今回は取得したリージョンごとに Words を纏めてList<string> として返す GetAllText メソッドを用意しました。

Face

次は Face を触ってみましょう。以下がメインサイトです。

azure.microsoft.com

Face は以前の JXUG でやっているので、以下のドキュメントが参考になります。

github.com

サービス作成

「Face」で検索して、F0 の価格プランで作成しましょう。どのリージョンに作ったか?を覚えておいてください。

ドキュメント

以下のサンプルを元に実装していきましょう。

docs.microsoft.com

NuGet パッケージとコード

NuGet パッケージマネージャーで、Windows の場合は「プレリリースを含める」、macOS の場合は「プレリリースパッケージを表示する」のチェックボックスをオンにして、「Microsoft.Azure.CognitiveServices.Vision.Face」を検索してインストールします。2018年12月時点の SDK のバージョンは 2.2.0-preview です。

FaceClient

Endpoint は Computer Vision と同じく、作成したリージョンによって URL が変わるので注意してください。

今回は顔認識と感情読み取り機能を使用するだけなので、faceClientFaceDetectWith〜 のメソッドを使用していますが、Face 以外にも、FaceListPersonGroup などもあります。

それぞれの詳細は API ドキュメント を参照いただきたいのですが、Person Group では顔情報をグループに分けて登録し、学習させて、そのエンジンに対して顔認識の結果を確認する。などもできるようです。

Facebook の自動顔認識とかに近いイメージでしょうか。Qiita で試している方がいらっしゃったのでリンクを貼っておきます。

qiita.com

FaceAttributeType[] の設定

取得する情報を FaceAttributeType[] の配列に格納しておきます。

FaceAttributeTypeEnum が用意されていますので、必要な情報を追加してください。

f:id:ytabuchi:20181221172922p:plain:w300

DetectWithUrlAsyncDetectWithStreamAsync メソッド

URL で投げた画像を解析する DetectWithUrlAsync と、Stream を解析する DetectWithStreamAsync がありますが、基本的な使い方は同じです。

IList<DetectedFace> が返ってきますので、GetFaceEmotions メソッドを用意して、取得した年齢や性別などの情報を移し変えてます。

DetectedFace クラス

今回は学習も取得もしていませんが、顔を登録しておくと、FaceId が取得できます。また、写真のどの位置の顔なのか?は FaceRectangle で返ってきますので、例えば認識した顔に枠を着けてその上に年齢を表示する How-Old.net みたいなこともできますね。

f:id:ytabuchi:20181221175349p:plain:w600

自撮りだとこんな感じですね!(関係ないけど、私、最近すごい老けた気がしてる!w)

f:id:ytabuchi:20181221180026p:plain:w300

.NET Core のコンソール

ライブラリプロジェクトを参照して、コンソールでテストしてみましょう。

Console.WriteLine("Cognitive Services - Vision - Face - DetectFace");

var faceClient = new FaceService();
var faces = faceClient.GetRemoteEmotionsAsync(faceImage).Result;

Console.WriteLine($"Detected: {faces.Count} Person.");
foreach (var face in faces)
{
    Console.WriteLine($"Emotion Result:\n" +
        $"Age:{face.Age} Gender:{face.Gender} Happiness:{face.Happiness}%");
}


Console.WriteLine("Cognitive Services - Vision - ComputerVision - Image Analysis");

var analysisClient = new ImageAnalysisService();
var caption = analysisClient.AnalyzeRemoteImageAsync(meetupImage).Result;

Console.WriteLine($"Analysis Result:\n" +
    $"{caption}");


Console.WriteLine("Cognitive Services - Vision - ComputerVision - OCR");

var computerVisionClient = new OcrService();
var regions = computerVisionClient.ExtractRemoteTextAsync(ocrImage).Result;

Console.WriteLine($"Detedted: {regions.Count} Regions");
foreach (var region in regions)
{
    Console.WriteLine($"OCR Result:\n" +
        $"{region}");
}

こんな感じでデバッグも出来るので便利ですね!

Xamarin.Forms の実装

最後に Xamarin.Forms での実装です。写真を Media Plugin で撮ったり参照したりした後で、その写真を各サービスに投げています。コードの部分はそれこそ上記のコンソールとほぼ同じなので楽ですね。

github.com

Media Plugin で写真を撮る、または開くボタンの処理

private async void TakePictureButton_Clicked(object sender, EventArgs e)
{
    if (isPermissionGranted)
    {
        file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
        {
            Directory = "Sample",
            Name = "test.jpg",
            PhotoSize = PhotoSize.Medium
        });

        image.Source = ImageSource.FromFile(file.Path);
    }
    else
    {
        await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
        //On iOS you may want to send your user to the settings screen.
        //CrossPermissions.Current.OpenAppSettings();
    }
}

private async void OpenPicureButton_Clicked(object sender, System.EventArgs e)
{
    if (isPermissionGranted)
    {
        file = await CrossMedia.Current.PickPhotoAsync();

        image.Source = ImageSource.FromFile(file.Path);
    }
    else
    {
        await DisplayAlert("Permissions Denied", "Unable to take photos.", "OK");
        //On iOS you may want to send your user to the settings screen.
        //CrossPermissions.Current.OpenAppSettings();
    }
}

各ボタンをクリックした時の処理です。ホントにほぼ同じw

private async void AnalyzeButton_Clicked(object sender, EventArgs e)
{
    var client = new ImageAnalysisService();
    var caption = await client.AnalyzeLocalImageAsync(file.Path);

    await DisplayAlert("Image Analysis", caption, "OK");
}

private async void OcrButton_Clicked(object sender, EventArgs e)
{
    var client = new OcrService();
    var regions = await client.ExtractLocalTextAsync(file.Path);

    var sb = new StringBuilder();
    sb.Append($"Extracted Regions: {regions.Count}\n\n");
    foreach (var region in regions)
    {
        sb.Append($"OCR Result:\n{region}\n");
    }

    await DisplayAlert("OCR", sb.ToString(), "OK");
}

private async void FaceButton_Clicked(object sender, EventArgs e)
{
    var client = new FaceService();
    var faces = await client.GetLocalEmotionAsync(file.Path);

    if (faces == null)
        await DisplayAlert("Error", "Can not detect", "OK");

    var sb = new StringBuilder();
    sb.Append($"Detected: {faces.Count}\n\n");
    foreach (var face in faces)
    {
        sb.Append($"Emotion Rsult:\nAge:{face.Age}\nGender:{face.Gender}\nHappiness:{face.Happiness}%\n");
    }

    await DisplayAlert("Face", sb.ToString(), "OK");
}

まとめ

今日は 視覚 Vision のサービスをいくつか使ってみました。

.NET Standard で書けるので、Xamarin からも他のアプリからも結構簡単に呼び出せて良いですね。試すだけなら無料でできるのも魅力です。

明日は 言語 Languages と検索 Search をやってみたいと思います。(終わるかな?w

明日ではなかったし、とりあえず言語だけですが、次のエントリーもアップしました。時間があれば、Search をやってみたいと思います。

ytabuchi.hatenablog.com

Xamarin 気になった方は

Visual Studio 2017 をインストールして触ってみてください。手順書は こちらのエントリー をご覧ください。 学習用リソースJXUG リンクページ に参考資料を纏めてますので併せてどうぞ。

Xamarin の導入支援サービスを始めました。ベースは基本的なアプリを一緒に作ることで Xamarin を使えるようになって頂く内容ですが、ご要望に応じて講習内容のカスタマイズも可能です。詳しくは田淵までお問い合わせください(^^)

Xamarin 有償トレーニング : XLsoft エクセルソフト

Xamarin の情報が欲しい方はこのブログも購読いただいたり、私のTwitterアカウントをフォローいただいたりすると嬉しいです。

私が所属している エクセルソフト の宣伝を少しさせてください。弊社は開発者向けの様々なソフトウェアを扱っています。Office/PDF ファイルを .NET/Java で操作するライブラリ Aspose(アスポーズ)Windows アプリ、Web ページ、iOS/Android アプリの UI テストができる TestComplete などお勧めです(^^) また、Visual Studio Professional/Enterprise with MSDN も販売してますし、日本で売っていない海外のソフトウェア、開発ツールなどを弊社経由で日本円で購入頂くことも可能です。ご興味あれば 弊社ページ を覗いてみてください。

以上です。

エクセルソフト | ダウンロード | 学習用リソース | JXUG リンクページ | ブログ購読