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を使って、自分の手のひらに小さな分身を出現させてみる




