こんにちは。エクセルソフトの田淵です。
Cogbot Advent Calendar 2018 - Qiita の 21日目のエントリーです。
明日もこのエントリーの続きでその2として書きたいと思います。
サンプルプロジェクトは以下に置いておきます。興味があれば見てみてください。
経緯
先日、Xamarin Advent Calendar 2018 - Qiita の 2日目の記事として、AWS Rekognition を使って顔認識を使うエントリーを書きました。
上記記事の経緯は、先日の「初心者向けXamarinハンズオン! #5」 で Microsoft Cognitive Services の Face を使ったアプリ を作ってドキュメントをアップデートしたので、同じことを AWS でやったらどんな感じかな?というものでした。せっかく Face をやったので、その他の沢山のサービスも使ってみたいな。ということで、面白そうだったり、C# の SDK があるサービスを色々触ってみることにします。
Cognitive Services を C# の SDK で使う時の書き方ってこんな感じか。という入口にしてもらえると嬉しいです。
2018/12/20 時点での情報です。Cognitive Services は結構早いペースでサービスの統廃合や名称が変わったりするのでご注意ください。
Congnitive Services を使うための準備
大前提として、使うにはどうすれば良いか?という点ですが、Cognitive Services の各種ページで「〜を試す」って青いボタンをクリックすると以下の画像が出てきます。
- 既存の Azure アカウント
- 無料の Azure アカウント(評価アカウント)
- ゲスト
で使えます。クレジットカードの登録は必要ですが無断で課金されることはないので、アカウントをお持ちでない方は無料の Azure アカウントを作っておくと良いでしょう。
IaaS には無料のプランはないのですが、例えば Web Apps のような PaaS の各種サービスであれば大体無料プランが用意されているので、ちょっと試したい。という時に便利です🙆🏻♂️
Azure のアカウントで Azure Portal にログインして、Cognitive Services 向けのリソースグループを作っておきましょう。このエントリーでは「Cognitive Services」というリソースグループを東南アジアに作成して Cognitive のサービスを纏めています。
各種サービスを作成するときに、「Resource Group」の欄から作成済みのリソースグループを選択してください。
余談ですが、Cognitive Services の各種サービスを作成すると、インスタンスが起動する訳ではなく、アクセスするためのキーを生成しているだけのようです。そのため、このエントリーでは各種サービス名を「〜Key」という名前にしています。
Xamarin で使う前準備
Xamarin.Forms で作っていきますので、Xamarin.Forms がビルドできる環境をご用意ください。
2018年12月現在の Visual Studio 2017 または Visual Studio for Mac の最新版を使っています。
使用する SDK が .NET Standard 対応のものが多いので、
- 空のソリューションを作成
- .NET Standard 2.0 のライブラリプロジェクトを作成
- 確認用に .NET Core 2.1 のコンソールプロジェクトを作成
- 最後に Xamarin.Forms のプロジェクトを作成
という流れで、以下の構成にしました。各種 Cognitive Services を使う 〜Service クラスをそれぞれ用意している感じです。
動作を確認するたびにスマホでチェックするのも大変なので、ライブラリのコードを書いてコンソールで確認し、動作を確認してから最後に Xamarin.Forms の UI を書く。という流れでやっています。
それではいきましょう!
Cognitive Services とは
色々な方が解説しているので説明は省きますが、Azure の PaaS を使って AI でなんかした結果を返してくれるサービスです。(雑)
今日のその1 のエントリーは、視覚についてです。
Cognitive Services - Vision(視覚)
視覚の中にはいくつかのサービスがあります。
視覚サービスによりアプリとサービスがどのように画像やビデオのコンテンツを正確に識別および分析できるようになるかをご覧ください。どのサービスも無料でお試しいただけます。また、次の機能を備え、コンピューター ビジョンに対応したアプリとサービスをすばやく作成できます。
とのこと。AI と言えば!という感じのサービスですよね。
Computer Vision
主に画像解析を行います。
- 画像の分類
- 画像内のシーンおよびアクティビティ認識
- 画像内の有名人とランドマークの認識
- 画像内の光学式文字認識 (OCR)
- 手書き認識
この中で、「画像内のシーンおよびアクティビティ認識」と「画像内の光学式文字認識 (OCR)」をやってみましょう。
Computer Vision - 画像内のシーンおよびアクティビティ認識
どんなことをしてくれて、どんなデータが返ってくるか?は以下のデモページの「画像の分析」を見てみてください。
例えば上記のデフォルトで選択されている電車とホームの画像は、特徴名と値で、「説明」の中に「captions」があり、その「text」が「people waiting at a train station」となっています。画像のアクティビティを認識してくれる。ということですね。
今回は caption の部分を SDK で取得します。
サービス作成
まずはサービスを作成しましょう。
リソース作成のブレードで「Computer Vision」を検索して作成します。
私は以下の設定で作成しました。今後も大体こんな感じで作成していくので、この後の作成時の説明は割愛します。
- 名前:ComputerVisionKey
- 場所:東南アジア
- 価格レベル:F0
- Resource Group:「Cognitive Services」
作成が終わったらリソースに移動し、Key メニューをクリックすると表示される Key を控えておきましょう。
ドキュメント
Computer Vision のページを開くと、赤枠のあたりに「ドキュメント」と「API」のリンクがあります。
大体どのサービスも同じサイト構成になっていますので、ドキュメントと API を見ながら開発を進めていきます。
画像内のシーンおよびアクティビティ認識は以下のサンプルを元に作っていきましょう。
当然ですが、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 ドキュメントから引用します。
- West US - westus.api.cognitive.microsoft.com
- West US 2 - westus2.api.cognitive.microsoft.com
- East US - eastus.api.cognitive.microsoft.com
- East US 2 - eastus2.api.cognitive.microsoft.com
- West Central US - westcentralus.api.cognitive.microsoft.com
- South Central US - southcentralus.api.cognitive.microsoft.com
- West Europe - westeurope.api.cognitive.microsoft.com
- North Europe - northeurope.api.cognitive.microsoft.com
- Southeast Asia - southeastasia.api.cognitive.microsoft.com
- East Asia - eastasia.api.cognitive.microsoft.com
- Australia East - australiaeast.api.cognitive.microsoft.com
- Brazil South - brazilsouth.api.cognitive.microsoft.com
- Canada Central - canadacentral.api.cognitive.microsoft.com
- Central India - centralindia.api.cognitive.microsoft.com
- UK South - uksouth.api.cognitive.microsoft.com
- Japan East - japaneast.api.cognitive.microsoft.com
AnalyzeImageAsync
メソッドと AnalyzeImageInStreamAsync
メソッドの language
引数
API リファレンス によると、language パラメーターで英語、ポルトガル語、日本語、簡体中国語に対応しているような記述がありますので、
AnalyzeImageInStreamAsync(imageStream, visualFeatures, details, "ja")
と日本語を指定するとちゃんと日本語で結果を返してくれます。
ImageAnalysis
クラス
以下のように色々な情報が含まれています。
ただ今回は Caption だけを取得するので、GetCaption
メソッドを用意して単純に analysis.Description.Captions[0].Text
を返しています。
いい感じですね!
Computer Vision - 画像内の光学式文字認識 (OCR)
次は OCR です。先ほどのデモページ の「画像内のテキストの読み取り」を見てみてください。
OCR については説明不要かと思いますが、API ドキュメント によると Computer Vision の OCR は以下の言語に対応しているようです。すごい!
- unk (AutoDetect)
- zh-Hans(中国語簡体字)
- zh-Hant(中国語)
- cs(チェコ語)
- da(デンマーク語)
- nl(オランダ語)
- en(英語)
- fi(フィンランド語)
- fr(フランス語)
- de(ドイツ語)
- el(ギリシャ語)
- hu(ハンガリー語)
- it(イタリア語)
- ja(日本語)
- ko(韓国語)
- nb(ノルウェー語)
- pl(ポーランド語)
- pt(ポルトガル語)
- ru(ロシア語)
- es(スペイン語)
- sv(スウェーデン語)
- tr(トルコ語)
- ar(アラビア語)
- ro(ルーマニア語)
- sr-Cyrl(セルビア式シリル)
- sr-Latn(セルビア語ラテン)
- sk(スロバキア語)
サービス作成
画像認識と同じなので、先ほど作成した KEY を使用します。
ドキュメント
OCR は以下のサンプルを元に作成していきます。
NuGet パッケージとコード
同じ NuGet パッケージを使用します。
ComputerVisionClient とエンドポイント
別の OcrService
クラスの ExtractLocalTextAsync
メソッドを用意したので再度記述が必要ですが、中身は同じです。
RecognizePrintedTextInStreamAsync
メソッドと OcrLanguages
引数
RecognizePrintedTextInStreamAsync
メソッドの引数、1個目は detectOrientation
で向きを自動認識してくれるので True
が良いでしょう。2個目は画像の Stream で、3個目が言語です。
OcrLanguages
の Enum で認識させたい各種言語を指定すれば良いのですが、指定なしで OcrLanguages.Unk
(Unkown かな?)の自動認識になります。このままで日本語も認識してくれるので指定なしでも良いと思います。
日本語の表示は英語が混ざることが多いので、その場合はどちらかの認識を捨てなければいけません。
例えば以下のように確実に日本語だけの画像なら
ほぼ正確に読み取ってくれます。素晴らしいですよね!
が、例えば以下のような(こういうかなり小さい字でも読み取れます)日本語と英語が混じっている画像の場合は、英語部分が文字化けした日本語として読み取るか、英語部分のみを読み取るかのどちらかになってしまいます。
しっかりと読み取る場合には、2回言語設定を変えて読み取って比較してミックスする。などの処理が必要になるかもしれません。
OcrResult
の処理
読み取り結果の OcrResult
には読み取った区分ごとに Regions
があり、その中に Lines
があり、最後に Words
があります。今回は取得したリージョンごとに Words
を纏めてList<string>
として返す GetAllText
メソッドを用意しました。
Face
次は Face を触ってみましょう。以下がメインサイトです。
Face は以前の JXUG でやっているので、以下のドキュメントが参考になります。
サービス作成
「Face」で検索して、F0 の価格プランで作成しましょう。どのリージョンに作ったか?を覚えておいてください。
ドキュメント
以下のサンプルを元に実装していきましょう。
NuGet パッケージとコード
NuGet パッケージマネージャーで、Windows の場合は「プレリリースを含める」、macOS の場合は「プレリリースパッケージを表示する」のチェックボックスをオンにして、「Microsoft.Azure.CognitiveServices.Vision.Face」を検索してインストールします。2018年12月時点の SDK のバージョンは 2.2.0-preview です。
FaceClient
Endpoint は Computer Vision と同じく、作成したリージョンによって URL が変わるので注意してください。
今回は顔認識と感情読み取り機能を使用するだけなので、faceClient
の Face
の DetectWith〜
のメソッドを使用していますが、Face
以外にも、FaceList
や PersonGroup
などもあります。
それぞれの詳細は API ドキュメント を参照いただきたいのですが、Person Group では顔情報をグループに分けて登録し、学習させて、そのエンジンに対して顔認識の結果を確認する。などもできるようです。
Facebook の自動顔認識とかに近いイメージでしょうか。Qiita で試している方がいらっしゃったのでリンクを貼っておきます。
FaceAttributeType[]
の設定
取得する情報を FaceAttributeType[]
の配列に格納しておきます。
FaceAttributeType
の Enum が用意されていますので、必要な情報を追加してください。
DetectWithUrlAsync
と DetectWithStreamAsync
メソッド
URL で投げた画像を解析する DetectWithUrlAsync
と、Stream を解析する DetectWithStreamAsync
がありますが、基本的な使い方は同じです。
IList<DetectedFace>
が返ってきますので、GetFaceEmotions
メソッドを用意して、取得した年齢や性別などの情報を移し変えてます。
DetectedFace
クラス
今回は学習も取得もしていませんが、顔を登録しておくと、FaceId
が取得できます。また、写真のどの位置の顔なのか?は FaceRectangle
で返ってきますので、例えば認識した顔に枠を着けてその上に年齢を表示する How-Old.net みたいなこともできますね。
自撮りだとこんな感じですね!(関係ないけど、私、最近すごい老けた気がしてる!w)
.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 で撮ったり参照したりした後で、その写真を各サービスに投げています。コードの部分はそれこそ上記のコンソールとほぼ同じなので楽ですね。
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 をやってみたいと思います。
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 も販売してますし、日本で売っていない海外のソフトウェア、開発ツールなどを弊社経由で日本円で購入頂くことも可能です。ご興味あれば 弊社ページ を覗いてみてください。
以上です。