Kinectを使ったバーチャル試着室で着せ替えシミュレーション
コントロールの配置
ツールボックスからデザイン画面上にListBoxコントロール1個、KinectColorViwerコントロールを1個配置します。次に
次に、KinectColorViewerを選択し、プロパティの[その他]パネルにあるKinectの「データバインドの適用」を選択します。ElementNameにKinectSensorChooser1を指定し、「パス」にKinectを指定します(図2)。
書き出されるXAMLをリスト2のように編集します。レイアウトは図3になります。
リスト2 書き出され編集されたXAMLコード(MainWindow.xaml)
- (1)
要素のWindowStateにMaximizedを指定して全画面表示とします。 - (2)
プロパティ要素内に、KeyがListBoxTemplateという名前の 要素を配置します。中に 要素を配置しMarginプロパティに10を指定して余白を設けます。 要素内に 要素を配置し、Width、Height、Sourceプロパティにデータをバインドします。ここで指定する名称はVBコード内で定義されたプロパティ名です。 - (3)KinectColorViewerのKinectプロパティにデータバインドが適用されています。
- (4)ListBoxのItemTemplateプロパティで(1)で定義したListBoxTemplateを参照します。
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowState="Maximized" Title="MainWindow" Height="1026" Width="976" xmlns:my="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers"> ■(1) <Window.Resources> ■(2) <DataTemplate x:Key="ListBoxTemplate"> ■(2) <StackPanel Margin="10"> ■(1) <Image Source="{Binding 画像名}" Width="{Binding 幅}" Height="{Binding 高さ}" Stretch="Fill"/> ■(2) </StackPanel> ■(2) </DataTemplate> ■(2) </Window.Resources> ■(2) <Canvas> <ListBox Height="884" HorizontalAlignment="Left" Margin="685,0,0,0" Name="ListBox1" VerticalAlignment="Top" Width="226" ItemTemplate="{StaticResource ListBoxTemplate}"/> ■(4) <my:KinectColorViewer Height="480" HorizontalAlignment="Left" Name="KinectColorViewer1" VerticalAlignment="Top" Width="640" Kinect="{Binding ElementName=KinectSensorChooser1, Path=Kinect}" /> ■(3) <Canvas x:Name="ImageArea" Width="640" Height="480" Margin="0,0,310,60"> <Image Height="95" HorizontalAlignment="Left" Name="fashionImage" Stretch="Fill" VerticalAlignment="Top" Width="81" /> <my:KinectSensorChooser Height="142" Name="KinectSensorChooser1" Width="175" Canvas.Left="444" Canvas.Top="320" /> </Canvas> </Canvas> </Window>
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックしてリスト3のコードを記述します。
ロジックコードを記述する
リスト3 (MainWindow.xaml.vb)
Option Strict On Imports Microsoft.Kinect
音声認識用のオーディオ形式を表すクラスが含まれる、Microsoft.Speech.AudioFormat名前空間をインポートします。
Imports Microsoft.Speech.AudioFormat
音声認識を実装するためのクラスが含まれる、Microsoft.Speech.Recognition名前空間をインポートします。
Imports Microsoft.Speech.Recognition Imports Coding4Fun.Kinect.Wpf Imports System.Windows.Media.Imaging Imports System.IO
Fashionクラス内にString型の「画像名」「幅」「高さ」プロパティを定義しています。XAMLコード内でのバインディングに使用されています。
Public Class FashionInfo Property 画像名 As String Property 幅 As String Property 高さ As String End Class Class MainWindow
深度情報が認識可能なプレイヤーの数(6)で初期化された定数メンバ変数、skeletonCountを宣言します。
Const skeletonCount As Integer = 6
認識可能なプレイヤーの数分の配列を持った、Skeletonクラス型のメンバ配列変数allSkeletonsを宣言しておきます。-1しているのは、添え字は0から始まるためです。
Dim allSkeletons(skeletonCount - 1) As Skeleton
1個のKinectセンサーを表すメンバ変数kinectを宣言します。
Dim kinect As KinectSensor
XML要素を表すメンバ変数xmldocを宣言します。
Dim xmldoc As XElement
音声認識サービスを実行するためのアクセス権を提供するSpeechRecognitionEngineクラス用メンバ変数engineを宣言します。
Dim engine As SpeechRecognitionEngine Dim words As String
ListBox内の項目のインデックスに該当するメンバ変数で、0で初期化しておきます。
Dim index As Integer = 0
ウインドウが読み込まれた時の処理
XElement.Loadメソッドでbin\Debugフォルダ内のXML文書ファイル(fashion.xml)を読み込みます。FashionInfoクラス型の新しいリストであるmyFashionInfoオブジェクトを作成します。
要素のコレクション内を変数resultで反復処理しながら、以下の処理を繰り返します。
新しいFashionInfoクラスの「画像名」プロパティに、Image/という文字列を連結した要素の値を指定します。「幅」プロパティにはダブル型に変換した、要素の属性”幅”の値を指定します。「高さ」プロパティには、ダブル型に変換した、要素の属性”高さ”の値を指定します。
これらの値の指定されたFashionInfoクラスを、AddメソッドでmyFashionInfoオブジェクトに追加していきます。ListBoxのItemsSourceプロパティにmyFashionInfoオブジェクトを指定します。ListBox内に服の一覧が表示されます。
fashionImageのSourceプロパティに0番目の要素の値を、画像を配置しているImage/というフォルダ名と連結して指定します。Widthプロパティには0番目の要素の属性”幅”を指定し、Heightプロパティには、0番目の要素の属性”高さ”を指定します。fashionImage内にListBoxのインデックスが0番目の画像(先頭の画像)が表示されます。
Kinectセンサーを取得し、Kinectを動作させます。
要素を構成するための代替項目の一覧を表すChoicesクラスのインスタンス、sentenceオブジェクトを作成します。Choiceクラスは、GrammarBuilder オブジェクトからのみ直接使用されます。Addメソッドで、認識させる言葉として「上」「下」「消去」「おわり」という語句をChoicesオブジェクトであるsentenceに追加します。
GrammarBuilderクラスは、単純な入力から複雑な Grammar(構文情報を取得管理するクラス)を構築するためのメカニズムを提供するクラスで、登録された言葉の構文(文法)設定を行い、SpeechRecognitionEngineへと設定します。
Appendメソッドで、登録した言葉を GrammarBuilder オブジェクトとして現在の GrammarBuilder に追加します。音声認識サービスを実行するためのアクセス権を提供する、SpeechRecognitionEngineクラスの新しいインスタンスを作成します。
文法のチェックされた言葉(builder)で初期化された、新しいGrammerクラスのインスタンス、myGrammerオブジェクトを作成します。Grammerクラスは、構文情報を取得および管理するためにランタイムをサポートするクラスです。
SpeechRecognitionEngineクラスのLoadGrammerメソッドで、Grammar によって指定されたとおりに、特定の構文を同期的に読み込みます。
言葉が認識された際には、AddHandlerステートメントで言葉を認識した際に発生するSpeechRecognizedイベントに、イベントハンドラを指定します。
Confidenceプロパティで音声認識の信頼度を設定します。-1が低、0が標準、1が高信頼度となります。-1を指定するとどんな言葉にでも反応する恐れがあります。1を指定するとなかなか認識してくれません。今回は信頼度が0.5より大きい場合に、指定した言葉を認識するよう指定しています。
認識された音声(speechArgs.Result.Text)を変数wordsに格納します。wordsの内容で条件分岐を行います。
「上」と発声された場合は、メンバ変数indexを1ずつ減算します。ListBoxの選択されたインデックスにindexの値を指定します。fashionImageのSourceプロパティにindex番目の要素の値を、画像を配置しているImage/というフォルダ名と連結して指定します。
Widthプロパティにはindex番目の要素の属性”幅”を指定し、Heightプロパティには、index番目の要素の属性”高さ”を指定します。fashionImage内にListBoxのインデックスがindex番目の画像が表示されます。
「下」と発声された場合は、メンバ変数indexを1ずつ増加します。ListBoxの選択されたインデックスにindexの値を指定します。fashionImageのSourceプロパティにindex番目の要素の値を、画像を配置しているImage/というフォルダ名と連結して指定します。
Widthプロパティにはindex番目の要素の属性”幅”を指定し、Heightプロパティには、index番目の要素の属性”高さ”を指定します。fashionImage内にListBoxのインデックスがindex番目の画像が表示されます。
「消去」と発声された場合は、fashionImageを非表示にします。
「おわり」と発声された場合は、Kinectセンサーを停止し、音声認識も停止して、Environment.Exit(0)でプログラムを終了します。
Kinectの音声インターフェースは、Kinect.AudioSourceで提供されます。Startメソッドで音声入力を開始します。入力ストリームを取得し、SpeechRecognitionEngine クラスのSetInputToDefaultAudioDeviceメソッドで、SpeechRecognitionEngine の現在のインスタンスに、システム既定のオーディオ入力を割り当てます。
認識操作の後に、RecognizeAsync によって開始された認識を終了しないよう、RecognizeMode.Multipleを指定して、RecognizeAsyncメソッドで非同期音声認識を開始します。
スケルトン・トラッキングの移動パラメータを指定するTransformSmoothParametersクラスの各プロパティを設定します。
Smoothingで平滑化の程度を指定します。値は0~1.0の間で、デフォルトは0.5です。値が大きいほど平滑化されます。
Correctionで、平滑化の緩急を指定します。値は0~1.0の間で、デフォルトは0.5です。値が小さいほど、平滑化に緩急を付けるため動作が低下します。
Predictionでスムーズに動作させるために予測されたフレームの数を取得します。
JitterRadiusでジッタ処理の対象にする半径(メートル)を指定します。デフォルトは0.05(5cm)です。
MaxDeviationRadiusで、フィルタされた値と生データとの誤差の許容最大値(メートル)を設定します。デフォルトは0.04(4cm)です。
EnableメソッドにTransformSmoothParametersを指定して、スケルトンを有効にします。
AddHandlerステートメントで、RGBカメラ、距離カメラ、スケルトンのフレームが更新された時に発生する、AllFramesReadyイベントにkinect_AllFramesReadyイベントハンドラを追加します。
Enableメソッドで、RGBカメラ、距離カメラを有効にします。
Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded xmldoc = XElement.Load("fashion.xml") Dim myFashionInfo As New List(Of FashionInfo) For Each result In From c In xmldoc.Descendants("画像名") Select c With myFashionInfo .Add(New FashionInfo With {.画像名 = "Image/" & result.Value, .幅 = CStr(CInt(result.Attribute("幅").Value) / 2), .高さ = CStr(CInt(result.Attribute("高さ").Value) / 2)}) End With Next ListBox1.ItemsSource = myFashionInfo ListBox1.SelectedIndex = 0 fashionImage.Visibility = Windows.Visibility.Visible fashionImage.Source = New BitmapImage(New Uri("Image/" & xmldoc.Descendants("画像名")(index).Value, UriKind.Relative)) fashionImage.Width = CDbl(xmldoc.Descendants("画像名")(index).Attribute("幅").Value) fashionImage.Height = CDbl(xmldoc.Descendants("画像名")(index).Attribute("高さ").Value) If KinectSensor.KinectSensors.Count = 0 Then MessageBox.Show("Kinectを接続してください") Exit Sub Else kinect = KinectSensor.KinectSensors(0) kinect.Start() Dim sentence As Choices = New Choices With sentence .Add("上") .Add("下") .Add("消去") .Add("おわり") End With Dim builder As GrammarBuilder = New GrammarBuilder builder.Append(sentence) Dim myGrammer As Grammar = New Grammar(builder) engine = New SpeechRecognitionEngine() engine.LoadGrammar(myGrammer) AddHandler engine.SpeechRecognized, Sub(speechSender As Object, speechArgs As SpeechRecognizedEventArgs) words = speechArgs.Result.Text Dim myConfidence = speechArgs.Result.Confidence If myConfidence > 0.5 Then Select Case words Case "上" If index <= 0 Then index = 0 Else index = index - 1 End If ListBox1.SelectedIndex = index fashionImage.Visibility = Windows.Visibility.Visible fashionImage.Source = New BitmapImage(New Uri("Image/" & xmldoc.Descendants("画像名")(index).Value, UriKind.Relative)) fashionImage.Width = CDbl(xmldoc.Descendants("画像名")(index).Attribute("幅").Value) fashionImage.Height = CDbl(xmldoc.Descendants("画像名")(index).Attribute("高さ").Value) Case "下" If index >= ListBox1.Items.Count - 1 Then index = ListBox1.Items.Count - 1 Else index = index + 1 End If ListBox1.SelectedIndex = index fashionImage.Visibility = Windows.Visibility.Visible fashionImage.Source = New BitmapImage(New Uri("Image/" & xmldoc.Descendants("画像名")(index).Value, UriKind.Relative)) fashionImage.Width = CDbl(xmldoc.Descendants("画像名")(index).Attribute("幅").Value) fashionImage.Height = CDbl(xmldoc.Descendants("画像名")(index).Attribute("高さ").Value) Case "消去" fashionImage.Visibility = Windows.Visibility.Collapsed Case "おわり" If kinect Is Nothing = False Then If kinect.IsRunning = True Then kinect.Stop() kinect.Dispose() engine.RecognizeAsyncStop() End If End If Environment.Exit(0) End Select End If End Sub Dim audio As KinectAudioSource = kinect.AudioSource Using s As Stream = audio.Start() engine.SetInputToDefaultAudioDevice() engine.RecognizeAsync(RecognizeMode.Multiple) End Using End If Dim myParam As New TransformSmoothParameters With myParam .Smoothing = 0.75F 'スムージングの量を取得 .Correction = 0.0F '補正の量を取得 .Prediction = 0.0F '予測されたフレームの数を取得。 .JitterRadius = 0.05F '取得またはジッタ低減 (メートル) に半径を設定。 .MaxDeviationRadius = 0.4F 'フィルタの位置がrawデータから逸脱できる最大半径を取得 End With kinect.SkeletonStream.Enable(myParam) AddHandler kinect.AllFramesReady, AddressOf kinect_AllFramesReady kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30) kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30) End Sub
Kinectを使ったバーチャル試着室を作るサンプル
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 声で選んだアイテムをプレイヤーの身体に装着・連動させるKinectサンプル
- Kinect v2の音声認識で「仮面」を選んで変身してみる
- お花とクラウディアさんを合成して表示するプログラムを作る
- Kinectで手の動きとカーソルを連動して操作するサンプル
- 手を動かして画面上の写真を左右にスライドさせるKinectサンプル
- センサーの範囲内にいる人間を見つけて撮影・保存するKinectサンプル
- Kinectで手の動きに合わせてモニタ上の画像を動かすサンプル
- Kinectで人体を認識して棒人間を動かすサンプル
- 読み込んだ画像に装飾を施し、PictureHUBに保存する
- Kinectを使って、自分の手のひらに小さな分身を出現させてみる