Windows 8 Store Applicationプログラミング(応用編) 9

顔認識APIを使って写真に黒縁メガネをかける(3ページ目)

※前ページからの続きです。

GridViewから任意の画像が選択された時の処理

リストであるmyImageList(要素の内容テキストを保持している)内の、GridViewから選択されたインデックスに該当する画像名を変数selectImageに格納します。選択された画像名をサーバーにアップしておいたASP.NETファイルのImageDataフォルダーと連結した文字列を作成して、変数selectImageUriに格納します。
640×480サイズのImageのSourceプロパティに、Uriクラスとして作成した、SelectImageUriを指定します。Image1に実寸の画像が表示されます。[黒縁メガネ]ボタンの使用を可能にします。

  Private Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged
    Dim selectImage As String = myImageList(GridView1.SelectedIndex)
    selectImageUri = "ユーザーのサーバー名/ImageFileUpload/ImageData/" &selectImage
    Image1.Source = New BitmapImage(New Uri(selectImageUri, UriKind.Absolute))
    glassesButton.IsEnabled = True
  End Sub

[黒縁メガネ]ボタンがクリックされた時の処理

API へのリクエストは、apikeyや画像のurlなどの条件を下記のような URL で指定します(REST)。

apikeyには「認証キー」を指定します。urlには作成したメンバ変数selectImageUriオブジェクトを指定します。
Dim imageUri As String = String.Format("https://kaolabo.com/api/detect?apikey={0}&url={1}", AppID, selectImageUri)

新しいHttpClientのインスタンスmyHttpClientオブジェクトを作成します。HttpClientクラスは、URIで識別されたリソースにHTTP要求を送信し、そのリソースからHTTP応答を受信するためのクラスです。

GetStringAsyncメソッドで、指定したURIにGET要求を送信し、非同期操作で応答本体を文字列として返し、変数resultに格納します。
このままだと、名前空間が付加されていて、うまくXMLの内容を取得できませんので、ルート要素とその内容だけのXMLに、Replaceメソッドで書き換えます。
一人だけの顔を認識して返されるデータは図5のようなデータです。

図5:一人を認識して返されたXMLデータ(クリックで拡大)

書き換えた結果XMLを、XElement.Parseメソッドで読み込みます。

Descendantsメソッドで、子孫要素であるすべての要素(図5参照)のコレクションに対して、各要素を変数myResultに格納しながら、顔の高さや左右の目の”x”、”y”属性の値を取得し、数値に変換して各変数に格納します。

Ellipseの新しいインスタンスmyEllipseRight(右目のメガネ)を作成します。
顔の高さ”height”属性の値が100より小さかった場合、大きかった場合の、メガネの位置を調整する数値を変数に格納しておきます。

myEllipseRightをGrayで塗りつぶします。
SetValueメソッドでLeftPropertyとTopPropertyに値を指定して、メガネを表示する右目の位置を設定します。メガネの直径は顔の高さの1/4の大きさとしています。
メガネの縁を黒縁にし、縁の太さを2に設定します。Opacityに0.8を指定して半透明化しておきます。

次に左目のメガネを作成します。右目の設定とまったく同じです。

myCanvasとい名前のCanvasにAddメソッドでmyEllipseRight(右目のメガネ)とmyEllipseLeft(左目のメガネ)を追加します。これで、人物上の両目に半透明のグレーで黒縁のメガネが表示されます。

非同期処理で行われるため、メソッドの先頭にAsyncを追加します。Asyncが追加されていると、その処理が非同期で行われることを意味します。

  Private Async Sub glaseesButton_Click(sender As Object, e As RoutedEventArgs) Handles glassesButton.Click
    Dim imageUri As String = String.Format("https://kaolabo.com/api/detect?apikey={0}&url={1}", AppID, selectImageUri)
    Dim myHttpClient As New HttpClient
    Dim result = Await myHttpClient.GetStringAsync(New Uri(imageUri, UriKind.Absolute))
    result = result.Replace("<results version=" &ChrW(34) & "1.0" &ChrW(34) & " xmlns=" &ChrW(34) & "http://xmlns.kaolabo.com/detect" &ChrW(34) & ">", "<results>")
    Dim readXmldoc As XElement = XElement.Parse(result)
    Dim x_no As Integer = 0
    Dim y_no As Integer = 0
    For Each myResult In From c In readXmldoc.Descendants("face") Select c
      Dim left_eyeX = CInt(CInt(myResult.Element("left-eye").Attribute("x").Value))
      Dim left_eyeY = CInt(CInt(myResult.Element("left-eye").Attribute("y").Value))
      Dim faceHeight = CInt(myResult.Attribute("height").Value)
      Dim right_eyeX = CInt(CInt(myResult.Element("right-eye").Attribute("x").Value))
      Dim right_eyeY = CInt(CInt(myResult.Element("right-eye").Attribute("y").Value))

      myEllipseRight = New Ellipse
 
      If faceHeight<= 100 Then
        x_no = 20
        y_no = 15
      Else
        x_no = 20
        y_no = 40
      End If
      With myEllipseRight
        .Fill = New SolidColorBrush(Colors.Gray)
        .SetValue(Canvas.LeftProperty, right_eyeX - x_no)
        .SetValue(Canvas.TopProperty, right_eyeY - y_no)
        .Width = CInt(faceHeight / 4)
        .Height = CInt(faceHeight / 4)
        .Stroke = New SolidColorBrush(Colors.Black)
        .StrokeThickness = 2
        .Opacity = 0.8
      End With

      myEllipseLeft = New Ellipse
      With myEllipseLeft
        .Fill = New SolidColorBrush(Colors.Gray)
        .SetValue(Canvas.LeftProperty, left_eyeX - x_no)
        .SetValue(Canvas.TopProperty, left_eyeY - y_no)
        .Width = faceHeight / 4
        .Height = faceHeight / 4
        .Stroke = New SolidColorBrush(Colors.Black)
        .StrokeThickness = 2
        .Opacity = 0.8
      End With
      myCanvas.Children.Add(myEllipseRight)
      myCanvas.Children.Add(myEllipseLeft)
    Next
  End Sub

[クリア]ボタンがクリックされた時の処理

左目のEllipseと右目のEllipseを非表示にします。

  Private Sub clearButton_Click(sender As Object, e As RoutedEventArgs) Handles clearButton.Click
    myEllipseLeft.Visibility = Xaml.Visibility.Collapsed
    myEllipseRight.Visibility = Xaml.Visibility.Collapsed
  End Sub
End Class

今回はここまでです。ありがとうございました。

この記事のキーワード

この記事をシェアしてください

人気記事トップ10

人気記事ランキングをもっと見る