ぴよぴよエンジニアの日記

クラウドベンダーに勤める見習いSEの日記です。発言は私自身の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

Watson Developer Cloud .NET Standard SDK を Xamarin で使ってみた(Visual Recognition 編)

santea.hateblo.jp

前回に引き続き、Watson Developer Cloud .NET Standard SDK の内容です.


今回は、Visual Recognition の Detect Faces を使ってみます.




実装環境

  • macOS Sierra 10.12.5 (16F73)
  • Visual Studio for Mac 7.0.1 (build 24)
  • IBM.WatsonDeveloperCloud.VisualRecognition.v3 1.1.0
  • Xamarin.Forms 2.3.4.247



XAML

<?xml version="1.0" encoding="UTF-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WatsonSdkSample.VisualRecognition.VisualRecognitionPage1">
    <ContentPage.Content>
        <StackLayout>
            <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                <ActivityIndicator x:Name="indicator" 
                                   IsRunning="True" 
                                   IsVisible="False" 
                                   VerticalOptions="Center"
                                   HorizontalOptions="Center" />
                <Image x:Name="image" 
                       HorizontalOptions="Fill" 
                       VerticalOptions="Fill" 
                       Margin="5,12,5,0" />
            </Grid>
            <Label x:Name="label" 
                   HorizontalTextAlignment="Center" />
            <Button BackgroundColor="#2196F3" 
                    TextColor="White" 
                    Text="Pick Photo" 
                    Clicked="Handle_Clicked" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Image に選択した画像を表示し、Label に画像認識の結果を表示します.



XAML.cs

using System;
using System.Diagnostics;
using System.IO;
using IBM.WatsonDeveloperCloud.VisualRecognition.v3;
using Plugin.Media;
using Xamarin.Forms;

namespace WatsonSdkSample.VisualRecognition
{
	public partial class VisualRecognitionPage1 : ContentPage
	{
		private const string ApiKey = "XXXXXXXXXXXXXXXXXXX";
		private readonly VisualRecognitionService _visualRecognition;

		public VisualRecognitionPage1()
		{
			InitializeComponent();

			_visualRecognition = new VisualRecognitionService();
			_visualRecognition.SetCredential(ApiKey);
		}

		public async void Handle_Clicked(object sender, EventArgs e)
		{
			image.Source = null;
			indicator.IsVisible = true;

			await CrossMedia.Current.Initialize();

			if (!CrossMedia.Current.IsPickPhotoSupported)
			{
				await DisplayAlert("No Auth", "Picking images denied.", "OK");
				return;
			}

			var file = await CrossMedia.Current.PickPhotoAsync();

			if (file == null)
				return;

			/** 画像認識 **/
			var imageByteArray = ReadFully(file.GetStream());

			var result = _visualRecognition.DetectFaces(imageData: imageByteArray, imageDataName: file.AlbumPath,
				imageDataMimeType: "image/jpeg");

			var text = "";
			foreach (var face in result.Images[0].Faces)
			{
				text += string.Format("Left: {0}, Top: {1}, Width: {2}, Height: {3}, " +
									  "Gender: {4}, GenderScore: {5}, AgeMax: {6}, AgeMin: {7}, AgeScore: {8}, " +
									  "IdentifyName: {9}, IdentifyScore: {10}, IdentifyHierarchy: {11}",
							face.FaceLocation.Left,
							face.FaceLocation.Top,
							face.FaceLocation.Width,
							face.FaceLocation.Height,
							face.Gender.Gender,
							face.Gender.Score,
							face.Age.Max,
							face.Age.Min,
							face.Age.Score,
							face.Identity?.Name,
							face.Identity?.Score,
							face.Identity?.TypeHierarchy) + System.Environment.NewLine;
			}

			image.Source = ImageSource.FromStream(() =>
			{
				var stream = file.GetStream();
				file.Dispose();
				return stream;
			});
			label.Text = text;
			indicator.IsVisible = false;
		}

		private static byte[] ReadFully(Stream input)
		{
			using (var ms = new MemoryStream())
			{
				input.CopyTo(ms);
				return ms.ToArray();
			}
		}
	}
}

Visual Recognition の部分を抜粋して説明します.

_visualRecognition = new VisualRecognitionService();
_visualRecognition.SetCredential(ApiKey);

VisualRecognitionService を初期化します.
SetCredential で VisualRecognition の API KEY を設定します.



var result = _visualRecognition.DetectFaces(imageData: imageByteArray, imageDataName: file.AlbumPath,
				imageDataMimeType: "image/jpeg");

imageData に Plugin.Media で取得した Stream を byte[] に変換したものを渡します.

imageDataName にファイルパスを、imageDataMimeType に "image/jpeg" を渡します.
(本来は、imageDataName, imageDataMimeType どちらかを指定すればいい気がしますが、この辺はもう少しソースを読んで確認します)



foreach (var face in result.Images[0].Faces)
{
	text += string.Format("Left: {0}, Top: {1}, Width: {2}, Height: {3}, " +
						"Gender: {4}, GenderScore: {5}, AgeMax: {6}, AgeMin: {7}, AgeScore: {8}, " +
						"IdentifyName: {9}, IdentifyScore: {10}, IdentifyHierarchy: {11}",
				face.FaceLocation.Left,
				face.FaceLocation.Top,
				face.FaceLocation.Width,
				face.FaceLocation.Height,
				face.Gender.Gender,
				face.Gender.Score,
				face.Age.Max,
				face.Age.Min,
				face.Age.Score,
				face.Identity?.Name,
				face.Identity?.Score,
				face.Identity?.TypeHierarchy) + System.Environment.NewLine;
}

取得できる要素として、以下の情報が取得できます.

  • 認識した顔の座標情報
  • 性別
  • 年齢
  • 有名人の場合は名前およびタグ情報



実装結果

f:id:Santea:20170717221840p:plain:w450

私の写真で恐縮ですが、実装結果です.

私は25歳なので、少し若めの分析結果ですね.


github.com
ソースコードはこちらでご確認いただけます.



まとめ

今回は Watson Developer Cloud .NET Standard SDK の Visual Recognition の中の DetectFaces を使ってみました.

SDK が使えることで、余計な POCO を実装しなくてよかったり、HttpClient 回りを書かなくてよいので、スピーディーに実装できますね.

一つ気になったところとしては、async メソッドがあるとより使い方の幅が広がる気がしました.




以上です.