Cognitive Services の Face API の利用

前回の Cognitive Services の Computer Vision API の利用に引き続いて、
今回は Face API を .NET (C#) で試してみたいと思います。

Cognitive Services の各 API を利用するには、まずアカウントのページから
サブスクリプションを登録してサブスクリプション キーを入手します。

Visual Studio で新規のプロジェクトを作成して (ここでは WPF とします)、
NuGet で Microsoft.ProjectOxford.Face をインストールします。

画像から顔を検出するには、次のようなコードを記述します。
(これは完全なコードではなく、API を呼び出す部分のみです。)

FaceServiceClient.DetectAsync メソッドの第 1 引数で画像を指定します。
画像は、Web 上の URL で指定するか、Stream を介して直接送ります。
前回は URL を指定しましたが、今回は Stream を使っています。

また、returnFaceAttributes という引数で、何の判定をするか (年齢、性別、眼鏡の有無など) を
IEnumerable<FaceAttributeType> 型で指定します。
上のコードでは、すべての情報を取得するように指定しています。
目や鼻などの特徴点の座標を判定するには、returnFaceLandmarks 引数に true を指定します。

実行結果は Face[] 型で、人数分の顔情報が格納されています。

 

実際にサンプル アプリを作成して試してみましたが、以下の注意点があります。

  • Computer Vision API にも年齢・性別を推定する機能がありますが、同一の結果にはならないようです。
  • 20 回に 1 回くらいの割合でエラーとなることがあるため、try-catch ステートメントは必須です。
    アプリの要件によってはリトライも検討したほうがよいでしょう。
    画像ファイル自体が原因となる場合もあるようです (サイズが小さいなど)。
  • (本題の Face API とは直接関係ないですが) JPEG ファイルは DPI が異なる場合があり (既定では 96)、
    Image コントロールに直接読み込ませると DPI によりサイズが変化し、
    Face API から取得した座標のスケールと異なってしまいます。
    したがってこのサンプルでは、あらかじめ BitmapImage オブジェクトに画像を読み込ませて、
    その PixelWidth および PixelHeight プロパティを利用しています。

作成したサンプル
FaceWpf (GitHub)

FaceWpf

 

前回: Cognitive Services の Computer Vision API の利用

バージョン情報
.NET Framework 4.5
Microsoft.ProjectOxford.Face 1.1.0

参照
Face API
How to Detect Faces in Image
Face API (Reference)

Microsoft Cognitive Services を始める ~ 全21種のサービス概説と開発準備
de:code 2016 > DBP018-Microsoft Cognitive Services 入門 → サンプルコード解説

Cognitive Services の Computer Vision API の利用

広告
カテゴリー: サービス. タグ: , . 1 Comment »

Cognitive Services の Computer Vision API の利用

Microsoft Cognitive Services には現在、Preview のものを含めて 21 の API が用意されています。
今回は Computer Vision API を .NET (C#) で使ってみることにします。

Cognitive Services の各 API を利用するには、まずアカウントのページから
サブスクリプションを登録してサブスクリプション キーを入手します。

Visual Studio で新規のプロジェクトを作成して (ここでは WPF とします)、
NuGet で Microsoft.ProjectOxford.Vision をインストールします。

画像の分析をするには、次のようなコードを記述します。
(これは完全なコードではなく、API を呼び出す部分のみです。)

VisionServiceClient.AnalyzeImageAsync メソッドで、指定された画像に対してさまざまな分析ができます。

第 1 引数で画像を指定します。Web 上の URL で指定するか、Stream を介して直接送ります。
第 2 引数では、何の判定をするか (顔の判別が必要か、アダルト コンテンツの判定が必要かなど) を
IEnumerable<VisualFeature> 型で指定します。
上のコードでは、すべての情報を取得するように指定しています。

結果は AnalysisResult 型で返ってきます。
AnalysisResult は、プロパティが存在するだけのシンプルなクラスです。

 

次に、OCR (光学文字認識) も試してみます。
(これは完全なコードではなく、API を呼び出す部分のみです。)

OCR をするには、VisionServiceClient.RecognizeTextAsync メソッドを利用します。
オプション引数で言語を指定することもできます。既定では自動判別のようです。

 

実際にサンプル アプリを作成して試してみましたが、以下の注意点があります。

  • OCR では、日本語の場合は 1 文字で 1 単語になってしまうようです (下図参照)。
    今後の改善に期待します。
  • 20 回に 1 回くらいの割合でエラーとなることがあるため、try-catch ステートメントは必須です。
    アプリの要件によってはリトライも検討したほうがよいでしょう。
    画像ファイル自体が原因となる場合もあるようです (サイズが小さいなど)。

作成したサンプル
ComputerVisionWpf (GitHub)

ComputerVisionWpf

 

次回: Cognitive Services の Face API の利用

バージョン情報
.NET Framework 4.5
Microsoft.ProjectOxford.Vision 1.0.296

参照
Computer Vision API
How to Call Computer Vision API
Computer Vision API (Reference)

Microsoft Cognitive Services を始める ~ 全21種のサービス概説と開発準備
de:code 2016 > DBP018-Microsoft Cognitive Services 入門 → サンプルコード解説

センサーのデータを SignalR でホストする (5)

前回のセンサーのデータを SignalR でホストする (4) までで、

  • ASP.NET SignalR サービス (コンソール アプリケーション)
  • ASP.NET SignalR クライアント (HTML)
  • ASP.NET SignalR クライアント (コンソール アプリケーション)

を作成しました。

今回は、コンソール アプリケーションとして作成した ASP.NET SignalR サービスを
タスクバーの通知領域に常駐させるように変更したいと思います。

 

(5) サービスをタスクバーの通知領域に常駐させる

Windows のタスクバーの通知領域を利用するには、アイコン ファイル (.ico) が必須です。
まず、以下の手順でアイコンをリソースに登録します。

(1), (2) で作成したプロジェクトのプロパティを開き、[リソース] タブを選択します。
中央のリンクをクリックして、リソース ファイルを作成します。

リソース 1

通知領域に表示させるアイコン ファイル (.ico) を用意し、
エクスプローラーから下図の中央部分にドラッグ アンド ドロップします。

リソース 2

名前を ServiceIcon に変更しておきます。

リソース 3

 

次に、プロジェクトのプロパティの [アプリケーション] タブを選択し、
[出力の種類] を [Windows アプリケーション] に変更します。
これにより、コンソール画面を出現させずにアプリケーションを実行できます。

出力の種類

 

プロジェクトに System.Windows.Forms.dll への参照を追加して、
次のように Program クラスを変更していきます。


class Program
{
    const string SelfHostUrl = "http://localhost:8080";
    const string AppName = "Sensors Host";
    static IDisposable webApp;
    static NotifyIcon notifyIcon;

    static void Main(string[] args)
    {
        webApp = WebApp.Start(SelfHostUrl);
        ShowNotifyIcon();
        Application.Run();
    }

    static void ShowNotifyIcon()
    {
        var exitMenu = new ToolStripMenuItem("終了(&X)");
        exitMenu.Click += (o, e) => ExitApp();
        var contextMenuStrip = new ContextMenuStrip();
        contextMenuStrip.Items.Add(exitMenu);

        notifyIcon = new NotifyIcon
        {
            ContextMenuStrip = contextMenuStrip,
            Icon = Properties.Resources.ServiceIcon,
            Text = AppName,
            Visible = true,
        };

        notifyIcon.ShowBalloonTip(3000, AppName, "サービスを開始しました。", ToolTipIcon.Info);
    }

    static void ExitApp()
    {
        webApp.Dispose();
        notifyIcon.Dispose();
        Application.Exit();
    }
}


サービスのセルフホストを開始したら、Application.Run メソッドを呼び出します。
これによりブロックが起き、アプリケーションの実行状態が保持されます。

NotifyIcon オブジェクトを生成して Visible プロパティを true に設定することにより、
タスクバーの通知領域にアイコンが表示されるようになります。
また、[終了] メニューを ContextMenuStrip オブジェクトに追加しておきます。

 

これを実行します。
タスクバーの通知領域にアイコンとメッセージが表示されます。

Sensors Host (開始)

アイコンを右クリックすると、[終了] メニューが表示されます。

Sensors Host (終了)

 

前: センサーのデータを SignalR でホストする (4)

作成したサンプル
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5

参照
NotifyIcon クラス

センサーのデータを SignalR でホストする (4)

前回のセンサーのデータを SignalR でホストする (3) では、
ASP.NET SignalR サービスに対するクライアントを HTML で実装しました。
今回は同様のクライアントをコンソール アプリケーションで実装します。

 

(4) コンソール アプリケーションからサービスにアクセスする

まず、[新しいプロジェクトの追加] でコンソール アプリケーション プロジェクトを作成します。

準備として、次のものを参照に追加する必要があります。

  • ASP.NET SignalR .NET Client (Microsoft.AspNet.SignalR.Client)

作成したプロジェクトを右クリックして [Nuget パッケージの管理] を選択します。
上記のパッケージを検索してインストールします。

ASP.NET SignalR .NET Client

 

Program.cs を、次のように実装します。


class Program
{
    static void Main(string[] args)
    {
        Task.Run(() => StartConnection());

        Console.WriteLine("Press [Enter] to exit.");
        Console.ReadLine();
    }

    async static void StartConnection()
    {
        var connection = new HubConnection("http://localhost:8080/");
        connection.ConnectionSlow += () => Console.WriteLine("Connection is slow.");
        connection.Error += ex => Console.WriteLine(ex);

        var lightSensor = connection.CreateHubProxy("LightSensorHub");
        lightSensor.On<float>("NotifyIlluminanceInLux", NotifyIlluminanceInLux);
        var compass = connection.CreateHubProxy("CompassHub");
        compass.On<double>("NotifyHeadingMagneticNorth", NotifyHeadingMagneticNorth);

        await connection.Start();

        var illuminanceInLux = await lightSensor.Invoke<float>("GetIlluminanceInLux");
        NotifyIlluminanceInLux(illuminanceInLux);
        var headingMagneticNorth = await compass.Invoke<double>("GetHeadingMagneticNorth");
        NotifyHeadingMagneticNorth(headingMagneticNorth);
    }

    static void NotifyIlluminanceInLux(float illuminanceInLux)
    {
        Console.WriteLine("Light: {0} lx", illuminanceInLux);
    }

    static void NotifyHeadingMagneticNorth(double headingMagneticNorth)
    {
        Console.WriteLine("Compass: {0} °", headingMagneticNorth);
    }
}


HubConnection.CreateHubProxy メソッドで、Hub のプロキシを作成します。

サービス側から直接呼び出せるメソッドを定義するには、On メソッドを使います。
逆に、サービス側で定義されたメソッドを呼び出すには、Invoke メソッドを使います。

なお、サービスのパスを明示的に指定するには、

var connection = new HubConnection("http://localhost:8080/signalr", false);

のようにします。

 

では、これを実行します。
端末に手をかざしたり端末を回転したりすれば、サービス側からそれぞれのデータがプッシュ送信されます。

SensorsConsole

 

次回は、サービス側のアプリケーションを通知領域に常駐させるように変更します。

つづく

前: センサーのデータを SignalR でホストする (3)
次: センサーのデータを SignalR でホストする (5)

作成したサンプル
WinRT-SignalR-Sample (GitHub) (今回までの分)
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5
ASP.NET SignalR .NET Client 2.0

参照
Hubs API Guide – .NET Client (C#)

センサーのデータを SignalR でホストする (3)

前回のセンサーのデータを SignalR でホストする (2) では、サービス側を実装しました。
今回はクライアント側となる Web アプリケーションを実装します。

 

(3) ブラウザーからサービスにアクセスする

まず、[新しいプロジェクトの追加] で [ASP.NET 空の Web アプリケーション] を選択し、
Web アプリケーション プロジェクトを作成します。

準備として、次のものを参照に追加する必要があります。

  • jQuery
  • ASP.NET SignalR JavaScript Client (Microsoft.AspNet.SignalR.JS)

通常、Web アプリケーション プロジェクトで ASP.NET SignalR のクライアント側もサービス側も実装する場合は
ASP.NET SignalR (Microsoft.AspNet.SignalR) をインストールしますが、
今回はクライアント側のみを利用するため、ASP.NET SignalR JavaScript Client をインストールします。

また、現在のところ、ASP.NET SignalR JavaScript Client をインストールすると、
古いバージョンである jQuery 1.6.4 が同時に入ってしまうため、先に jQuery を個別にインストールしておきます。

作成したプロジェクトを右クリックして [Nuget パッケージの管理] を選択します。
上記のパッケージを検索してインストールします。

jQuery

ASP.NET SignalR JavaScript Client

 

プロジェクトに [HTML ページ] を追加し、名前を index.html とします。
index.html を次のように実装して、サービスからセンサーのデータを取得します。


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Sensors Client</title>
    <script src="Scripts/jquery-2.0.3.min.js"></script>
    <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
    <script src="http://localhost:8080/signalr/hubs"></script>
</head>
<body>
    <script type="text/javascript">
        $(function () {
            $.connection.hub.url = "http://localhost:8080/signalr";
            var appModel = { light: 0, compass: 0 };

            var lightSensor = $.connection.lightSensorHub;
            lightSensor.client.notifyIlluminanceInLux = function (illuminanceInLux) {
                appModel.light = illuminanceInLux;
                console.log("Light: %f lx", appModel.light);
            };
            var compass = $.connection.compassHub;
            compass.client.notifyHeadingMagneticNorth = function (headingMagneticNorth) {
                appModel.compass = headingMagneticNorth;
                console.log("Compass: %f °", appModel.compass);
            };

            $.connection.hub.start()
                .done(function () {
                    lightSensor.server.getIlluminanceInLux()
                        .done(lightSensor.client.notifyIlluminanceInLux);
                    compass.server.getHeadingMagneticNorth()
                        .done(compass.client.notifyHeadingMagneticNorth);
                });
        });
    </script>
</body>
</html>


サービス側から直接呼び出せるメソッドを定義するには、lightSensor.client.notifyIlluminanceInLux のように、
hub の client プロパティに関数を設定します。

逆に、サービス側で定義されたメソッドを呼び出すには、lightSensor.server.getIlluminanceInLux のように、
hub の server プロパティを経由して呼び出します。

これを実行します。
端末に手をかざしたり端末を回転したりすれば、サービス側からそれぞれのデータがプッシュ送信され、
ブラウザーのコンソールに値がレポートされます。

Sensors Client (コンソール)

 

あとは、GUI を追加すれば変化が視覚的にわかりやすくなります。
この先のコードは index.html (GitHub) をご覧ください。

Sensors Client 1

Sensors Client 2

 

次回は、コンソール アプリケーションでクライアントを作成します。

つづく

前: センサーのデータを SignalR でホストする (2)
次: センサーのデータを SignalR でホストする (4)

作成したサンプル
WinRT-SignalR-Sample (GitHub) (今回までの分)
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5
jQuery 2.0
ASP.NET SignalR JavaScript Client 2.0

参照
Tutorial: SignalR Self-Host

センサーのデータを SignalR でホストする (2)

前回のセンサーのデータを SignalR でホストする (1) では、
センサーのデータをトラッキングするコンソール アプリケーションを作成しました。

今回は、そのデータをリアルタイムで配信するサービスを ASP.NET SignalR で作成してみたいと思います。
ただし IIS 上の Web サービスとしてホストするわけではなく、コンソール アプリケーションでホストします。
そのためには、ASP.NET SignalR Self Host を利用します。

 

(2) ASP.NET SignalR でサービスをセルフホストする

準備として、次のものを参照に追加する必要があります。

  • ASP.NET SignalR Self Host (Microsoft.AspNet.SignalR.SelfHost)
  • Microsoft.Owin.Cors

Visual Studio で、前回作成したプロジェクトを右クリックして [Nuget パッケージの管理] を選択します。
上記のパッケージを検索してインストールします。

ASP.NET SignalR Self Host

Microsoft.Owin.Cors

 

では、実装です。
IIS 上の ASP.NET SignalR と同様に、サービスを表すクラスを Hub クラスの具象クラスとして実装します。

まず、照度センサーに対する LightSensorHub クラスを実装します。


public class LightSensorHub : Hub
{
    static readonly IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<LightSensorHub>();
    static readonly LightSensor lightSensor = LightSensor.GetDefault();

    public static void StartBroadcast()
    {
        lightSensor.ReportInterval = 500;
        lightSensor.ReadingChanged += (o, e) =>
        {
            Console.WriteLine("Light: {0} lx", e.Reading.IlluminanceInLux);
            hubContext.Clients.All.NotifyIlluminanceInLux(e.Reading.IlluminanceInLux);
        };
    }

    public float GetIlluminanceInLux()
    {
        return lightSensor.GetCurrentReading().IlluminanceInLux;
    }
}


クライアント側から直接呼び出すためのメソッドとして、GetIlluminanceInLux メソッドを定義しています。
逆に、クライアント側にプッシュ送信するためには、LightSensorHub クラスに対する IHubContext オブジェクトを取得します。

クライアント側から呼び出されたときであれば Hub.Clients プロパティからプッシュ送信できるのですが、
任意のタイミングでクライアント側にデータをプッシュするにはこのようにします。

電子コンパスに対しても同様に、CompassHub クラスを実装します。


public class CompassHub : Hub
{
    static readonly IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<CompassHub>();
    static readonly Compass compass = Compass.GetDefault();

    public static void StartBroadcast()
    {
        compass.ReadingChanged += (o, e) =>
        {
            var rounded = Math.Round(e.Reading.HeadingMagneticNorth, 3);
            Console.WriteLine("Compass: {0} °", rounded);
            hubContext.Clients.All.NotifyHeadingMagneticNorth(rounded);
        };
    }

    public double GetHeadingMagneticNorth()
    {
        return Math.Round(compass.GetCurrentReading().HeadingMagneticNorth, 3);
    }
}


 

Web サーバーを起動するためのクラスとして、Startup クラスを実装します。
Configuration メソッドに、起動時の構成を記述します。


class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCors(CorsOptions.AllowAll);
        app.MapSignalR();

        LightSensorHub.StartBroadcast();
        CompassHub.StartBroadcast();
    }
}


IAppBuilder.UseCors メソッドにより、CORS (Cross-Origin Resource Sharing) の設定をします。
要するにクロスドメインのアクセス許可ですが、AllowAll を指定することですべてのドメインからのアクセスを許可します。

ホストする URL のパスは既定で /signalr ですが、これを明示的に指定するには、

app.MapSignalR("/signalr", new HubConfiguration());

のようにします。

 

最後に、Main メソッドを書き換えます。
ポートを指定して、Web サーバーを起動します。


class Program
{
    const string SelfHostUrl = "http://localhost:8080";

    static void Main(string[] args)
    {
        using (WebApp.Start(SelfHostUrl))
        {
            Console.WriteLine("Press [Enter] to exit.");
            Console.ReadLine();
        }
    }
}


 

このようにして、リアルタイム双方向サービスをセルフホストできるようになります。
次回はクライアントとなる HTML アプリを作成します。

つづく

前: センサーのデータを SignalR でホストする (1)
次: センサーのデータを SignalR でホストする (3)

作成したサンプル
WinRT-SignalR-Sample (GitHub) (今回までの分)
WinRT-SignalR-Sample (GitHub)

バージョン情報
.NET Framework 4.5
ASP.NET SignalR Self Host 2.0
Microsoft.Owin.Cors 2.0

参照
Tutorial: SignalR Self-Host