顔認識APIを使って写真に黒縁メガネをかける

2013年3月15日(金)
薬師寺 国安

ドキュメントライブラリへのアクセス許可

今回はドキュメントライブラリ内のImageFileList.xmlファイルにアクセスしますので、ドキュメントライブラリへのアクセス許可と、xmlファイルの登録が必要です。

※)ただし、Windows ストアに申請する場合、ドキュメントライブラリにアクセスしていると、パッケージファイルのアップロードではねられてしまいます。
ローカルで自分で使用する分には問題ないのですが、Windows ストアに申請する場合は、「画像ライブラリ」にアクセス許可を与えて中にフォルダを作成し、そのフォルダの中にImageFileList.xmlを配置して、読み込むようにしたほうがいいでしょう。

ソリューションエクスプローラー内のpackage.appxmanifestをダブルクリックして開きます。「機能」タブをクリックし、「機能:」にある「ドキュメントライブラリ」にチェックを付けます(図3)。

図3:「機能」タブ内の「ドキュメントライブラリ」にチェックを付ける(クリックで拡大)

次に「宣言」タブをクリックし、左に表示されている「使用可能な宣言:」から「ファイルの種類の関連付け」を追加します。右に表示されるプロパティ内で、「名前」にxml、「サポートされるファイルの種類」内の「ファイルの種類」に.xmlと指定します(図4)。

図4:「宣言」タブ内で「名前」と「ファイルの種類」を設定する(クリックで拡大)

※今回使用するImageFileList.xmlファイルは、“参考記事”で作成されたXMLファイルです。

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックしてリスト2のコードを記述します。

ロジックコードを記述する

リスト2 (MainWindow.xaml.vb)

Option Strict On

クライアントとサーバーの両方で使用できる HTTP のコンポーネント(HTTP ヘッダー、およびメッセージなど)に関するクラスの含まれる、System.Net.Http名前空間をインポートします。

Imports System.Net.Http

シーケンシャルとランダムアクセスのストリームの読み書きをサポートするクラスの含まれる、Windows.Storage.Streams名前空間をインポートします。

Imports Windows.Storage.Streams

ネットワークで使用される多くのプロトコルに対し、インターフェイスを提供するクラスの含まれる、System.Net名前空間をインポートします。

Imports System.Net

ファイル、フォルダー、およびアプリケーションの設定を管理するクラスの含まれる、Windows.Storage名前空間をインポートします。

Imports Windows.Storage

XML ドキュメントオブジェクトモデル(DOM)をサポートするクラスの含まれる、Windows.Data.Xml.Dom名前空間をインポートします。

Imports Windows.Data.Xml.Dom

基本的な図形を定義するクラスの含まれる、Windows.UI.Xaml.Shapes名前空間をインポートします。

Imports Windows.UI.Xaml.Shapes

UIを提供するクラスの含まれる、Windows.UI名前空間を読み込みます。メガネの色を指定する場合等に必要です。

Imports Windows.UI

Public NotInheritable Class MainPage

  Inherits Page

メンバ定数変数に「取得した認証キー」を設定しておきます。

  ConstAppID As String = "取得した認証キー"

文字列型のリストである新しいmyImageListメンバ変数を宣言します。

  Dim myImageList As New List(Of String)

  Dim selectImageUri As String

Ellipseクラス型のメンバ変数myEllipseLeftとmyEllipseRightを宣言します。左目と右目のメガネになります。

  Dim myEllipseLeft As Ellipse
  Dim myEllipseRight As Ellipse

[サーバーから画像を取得]ボタンがクリックされた時の処理

ドキュメントライブラリにアクセスして、GetFileAsyncメソッドでImageFileList.xmlを取得します。

XMLドキュメントの読み込みと、解析の際に使用される設定の含まれる、XmlLoadSettingsクラスの新しいインスタンス、mySettingオブジェクトを作成します。DTDは含めないので、ProhibitDtdプロパティにFalseと指定します。外部エンティティ参照もしませんので、ResolveExternalsプロパティにFalseと指定します。

XmlDocumentクラスのLoadFromFileAsyncメソッドで、指定されたファイルからXMLドキュメントを非同期的に読み込みます。ドキュメントは指定された設定を使用して解析されます。

SelectNodesメソッドで要素のノードリストを取得し、ImageElement変数に格納します。

Countプロパティで要素のノードリストの個数を取得し、その個数分反復処理を行います。

繰り返し変数iに対応する要素の内容テキストを、ImageElement.ElementAt(i).InnerTextで取得し、変数myElementに格納します。リストのオブジェクトであるmyImageListにAddメソッドで要素の内容テキストを追加していきます。

参考記事”でサーバーに配置しておいたASP.NETファイルのImageDataフォルダー内にあるmyElementに格納されたファイル名を指定した文字列を作成し、myUrl変数に格納します。
CreateHttpメソッドで、指定したURI文字列用に新しいHttpWebRequestインスタンスを初期化した、myRequestオブジェクトを作成します。
MethodにGETを指定します。

GetResponseAsyncメソッドで、インターネット要求への応答を受け取ります。
GetResponseStreamでインターネットリソースから返されたデータストリームを取得し、変数myStreamで参照します。

メモリーに保存される入出力ストリームデータへのランダムアクセスを提供する、InMemoryRandomAccessStreamクラスの新しいインスタンス、myMemoryオブジェクトを作成します。
GetOutputStreamAtメソッドで、ストリームの指定された場所の出力ストリームを取得して、変数myOutputに格納します。CopyAsyncメソッドで、ソースストリームをコピー先のストリームにコピーします。この場合、Windowsランタイムの入力ストリームに変換された、myStream.AsInputStreamを、書きこまれる順次バイトストリームを表すmyOutputにコピーします。

新しいBitmapImageクラスのインスタンスbmpオブジェクトを作成します。
SetSourceメソッドに指定された場所の出力ストリームを取得している、myMemoryオブジェクトを指定します。

Imageの新しいインスタンスmyImageオブジェクトを作成し、WidthとHeightの値を指定します。Sourceメソッドにbmpオブジェクトを指定します。
GridViewにAddメソッドでmyImageオブジェクトを追加します。
サーバーからの画像が横1列に表示され、スクロールが可能になります。

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

  Private Async Sub serverButton_Click(sender As Object, e As RoutedEventArgs) Handles serverButton.Click
 
    Dim myStorageFolder As StorageFolder = Windows.Storage.KnownFolders.DocumentsLibrary
    Dim myXmlFile As StorageFile = Await myStorageFolder.GetFileAsync("ImageFileList.xml")
    Dim mySetting As New XmlLoadSettings
    mySetting.ProhibitDtd = False
    mySetting.ResolveExternals = False
    Dim xmldoc = Await XmlDocument.LoadFromFileAsync(myXmlFile, mySetting)
    Dim ImageElement As XmlNodeList = xmldoc.SelectNodes("//画像名")
 
    For i As Integer = 0 To ImageElement.Count - 1
      Dim myElement = ImageElement.ElementAt(i).InnerText
      myImageList.Add(myElement)
      Dim myUrl = "ユーザーのサーバー名/ImageFileUpload/ImageData/" &myElement
      Dim myRequest = HttpWebRequest.CreateHttp(myUrl)
      myRequest.Method = "GET"
      Using myResponse = Await myRequest.GetResponseAsync
        Using myStream = myResponse.GetResponseStream
          Dim myMemory As New InMemoryRandomAccessStream
          Dim myOutputAs IOutputStream= myMemory.GetOutputStreamAt(0)
          Await RandomAccessStream.CopyAsync(myStream.AsInputStream, myOutput)
          Dim bmp As New BitmapImage
          bmp.SetSource(myMemory)
          Dim myImage As New Image
          myImage.Width = 320
          myImage.Height = 240
          myImage.Source = bmp
          GridView1.Items.Add(myImage)
        End Using
      End Using
    Next
  End Sub
  • 顔認識APIを使って写真に黒縁メガネをかけるアプリサンプル

薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています