※前ページからの続きです。
GridViewから任意の画像が選択された時の処理
リストであるmyImageList(要素の内容テキストを保持している)内の、GridViewから選択されたインデックスに該当する画像名を変数selectImageに格納します。選択された画像名をサーバーにアップしておいたASP.NETファイルのImageDataフォルダーと連結した文字列を作成して、変数selectImageUriに格納します。
640×480サイズのImageのSourceプロパティに、Uriクラスとして作成した、SelectImageUriを指定します。Image1に実寸の画像が表示されます。[黒縁メガネ]ボタンの使用を可能にします。
1 | Private Sub GridView1_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles GridView1.SelectionChanged |
2 | Dim selectImage As String = myImageList(GridView1.SelectedIndex) |
3 | selectImageUri = "ユーザーのサーバー名/ImageFileUpload/ImageData/" &selectImage |
4 | Image1.Source = New BitmapImage(New Uri(selectImageUri, UriKind.Absolute)) |
5 | glassesButton.IsEnabled = True |
[黒縁メガネ]ボタンがクリックされた時の処理
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が追加されていると、その処理が非同期で行われることを意味します。
01 | Private Async Sub glaseesButton_Click(sender As Object, e As RoutedEventArgs) Handles glassesButton.Click |
03 | Dim myHttpClient As New HttpClient |
04 | Dim result = Await myHttpClient.GetStringAsync(New Uri(imageUri, UriKind.Absolute)) |
05 | result = result.Replace("<results version=" &ChrW(34) & "1.0" &ChrW(34) & " xmlns=" &ChrW(34) & "http://xmlns.kaolabo.com/detect" &ChrW(34) & ">", "<results>") |
06 | Dim readXmldoc As XElement = XElement.Parse(result) |
07 | Dim x_no As Integer = 0 |
08 | Dim y_no As Integer = 0 |
09 | For Each myResult In From c In readXmldoc.Descendants("face") Select c |
10 | Dim left_eyeX = CInt(CInt(myResult.Element("left-eye").Attribute("x").Value)) |
11 | Dim left_eyeY = CInt(CInt(myResult.Element("left-eye").Attribute("y").Value)) |
12 | Dim faceHeight = CInt(myResult.Attribute("height").Value) |
13 | Dim right_eyeX = CInt(CInt(myResult.Element("right-eye").Attribute("x").Value)) |
14 | Dim right_eyeY = CInt(CInt(myResult.Element("right-eye").Attribute("y").Value)) |
16 | myEllipseRight = New Ellipse |
18 | If faceHeight<= 100 Then |
26 | .Fill = New SolidColorBrush(Colors.Gray) |
27 | .SetValue(Canvas.LeftProperty, right_eyeX - x_no) |
28 | .SetValue(Canvas.TopProperty, right_eyeY - y_no) |
29 | .Width = CInt(faceHeight / 4) |
30 | .Height = CInt(faceHeight / 4) |
31 | .Stroke = New SolidColorBrush(Colors.Black) |
36 | myEllipseLeft = New Ellipse |
38 | .Fill = New SolidColorBrush(Colors.Gray) |
39 | .SetValue(Canvas.LeftProperty, left_eyeX - x_no) |
40 | .SetValue(Canvas.TopProperty, left_eyeY - y_no) |
41 | .Width = faceHeight / 4 |
42 | .Height = faceHeight / 4 |
43 | .Stroke = New SolidColorBrush(Colors.Black) |
47 | myCanvas.Children.Add(myEllipseRight) |
48 | myCanvas.Children.Add(myEllipseLeft) |
[クリア]ボタンがクリックされた時の処理
左目のEllipseと右目のEllipseを非表示にします。
1 | Private Sub clearButton_Click(sender As Object, e As RoutedEventArgs) Handles clearButton.Click |
2 | myEllipseLeft.Visibility = Xaml.Visibility.Collapsed |
3 | myEllipseRight.Visibility = Xaml.Visibility.Collapsed |
今回はここまでです。ありがとうございました。