Kinect v2を使った「じゃんけんゲーム」を作る
2014年12月16日(火)
XMLファイルの作成(Jyanken.xml)
VS2013メニューの[プロジェクト]ー[新しい項目の追加]を選択して、表示される画面から「データ」を指定し、表示される項目から「XMLファイル」を選択します。名前には「Jyanken.xml」と指定し、最後に「追加」ボタンをクリックします(図6)。
するとXMLエディターが起動しますので、リスト2のXMLを記述します。
<?xml version="1.0" encoding="utf-8" ?> <じゃんけん> <画像名>グー.png</画像名> <画像名>チョキ.png</画像名> <画像名>パー.png</画像名> </じゃんけん>
追加したXMLファイルを選択してプロパティを表示します。「ビルドアクション」に「コンテンツ」、「出力ディレクトリーコピー」に「常にコピーする」と指定して下さい(図7)。この設定を忘れるとエラーになりますので、注意してください。
プログラムコード
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示されるMainWindow.xam.vbに、リスト3以降のコードを記述します。かなり分量が多いですが、がんばって下さい。
名前空間の読み込み
Imports System.ComponentModel (1) Imports Microsoft.Kinect (2) Imports Microsoft.Speech.AudioFormat (3) Imports Microsoft.Speech.Recognition (4) Imports KinectSensor_KinectAudioStream (5) Imports System.IO Public Class MainWindow
- コンポーネントやコントロールの実行時動作、およびデザイン時動作を実装するためのクラスが用意されているSystem.ComponentModel名前空間を読み込みます。
- Kinectを扱うためのクラスが含まれるMicrosoft.Kinect名前空間を読み込みます。
- 音声認識用のオーディオ形式を表すクラスが含まれるMicrosoft.Speech.AudioFormat名前空間を読み込みます。
- 音声認識を実装するためのクラスが含まれるMicrosoft.Speech.Recognition名前空間を読み込みます。
- オーディオストリームのクラスを提供するKinectSensor_KinectAudioStream名前空間を読み込みます。これは、ソリューションエクスプローラー内のDLLフォルダーに配置したKinectAudioStreamを、参照設定に追加したものです。
メンバー変数の宣言
Private myKinect As KinectSensor (1) Private myBodyFrameReader As BodyFrameReader (2) Private myColorFrameReader As ColorFrameReader = Nothing (3) Private colorBitmap As WriteableBitmap = Nothing (4) Private BytesPerPixel As Integer = 4 (5) Private ColorImagePixelData As Byte() (6) Private Rnd As Random (7) Private RandomNumber As Integer Private SpeechEngine As SpeechRecognitionEngine (8) Const SpeechID As String = "SR_MS_ja-JP_Kinect_11.0" (9) Private myKinectAudioStream As KinectAudioStream (10) Private Index As Integer = 0 Private myBodies As Body() (11) Private myBodyDrawingGroup As New DrawingGroup (12) Private myRect As Rect (13) Private JyankenImage As String Private xmldoc As XElement (14) Private flagImage As String Private player_Score As Integer = 0 Private computer_Score As Integer = 0
- KinectSensorクラスのメンバー変数myKinectを宣言します。
- ボディフレームのリーダーを表すBodyFrameReaderクラスのメンバー変数myBodyFrameReaderを宣言します。
- カラーフレームリーダーを表すクラスであるColorFrameReader型のメンバー変数myColorFrameReaderを宣言します。
- WriteableBitmapクラス型のメンバー変数colorBitmapを宣言します。WriteableBitmapは、書き込みおよび更新が可能なBitmapSource を提供するクラスで、BitmapSourceは単一の一定なピクセルセットを、特定のサイズおよび解像度で表わすクラスを意味します。
- Integer型のメンバー変数BytePerPixelを宣言し、「4」で初期化しておきます。この値は、32ビットフルカラーのRGB形式で、各カラーチャネルに割り当てられる「bits per pixel(BPP)」が「8」のため、Bgr32を「8」で除算した「4」バイトを意味します。「青」、「緑」、「赤」では24ビットしか使用されませんが、残りの8ビットは「Alpha(不透明度)」に使用されることが多いです。値を直接指定する代わりに以下のように記述しても同じです。
CInt(PixelFormats.Bgr32.BitsPerPixel / 8) - バイト型の配列であるメンバー変数ColorImagePixelDataを宣言します。
- 乱数を発生させるRandomクラス型のメンバー変数Rndを宣言します。
- 音声認識サービスを実行するためのアクセス権を提供するクラスであるSpeechRecognitionEngineクラス用のメンバー変数SpeechEngineを宣言します。
- 日本語音声認識エンジンのIDを、メンバー定数として宣言します。
- KinectAudioStreamクラス型のメンバー変数myKinectAudioStreamを宣言します。
- 単一のボディを表す配列のBody()クラス型のメンバー変数myBodiesを宣言します。
- 1つの描画として操作できる描画のコレクションを表す、DrawingGroupのインスタンスmyBodyDrawingDroupメンバー変数を宣言します。
- 四角形の幅、高さ、および位置を表すRect構造体のメンバー変数myRectを宣言します。
- XMLを表すXElementクラス型のメンバー変数xmldocを宣言します。
ウインドウが読み込まれた時の処理
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded myKinect = KinectSensor.GetDefault xmldoc = XElement.Load("Jyanken.xml") (1) Try If myKinect Is Nothing = False Then Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription (2) myKinect.Open() (3) myBodyFrameReader = myKinect.BodyFrameSource.OpenReader (4) AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived (5) myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {} (6) myRect = New Rect(0, 0, myDepthDescription.Width, myDepthDescription.Height) (7) myColorFrameReader = myKinect.ColorFrameSource.OpenReader AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived (8) Dim myColorFrameDescripton As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra) (9) BytesPerPixel = myColorFrameDescripton.BytesPerPixel (10) ReDim ColorImagePixelData(myColorFrameDescripton.Width * myColorFrameDescripton.Height * BytesPerPixel – 1) (11) colorBitmap = New WriteableBitmap(myColorFrameDescripton.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing) (12) Dim myAudioBeamList As IReadOnlyList(Of AudioBeam) = myKinect.AudioSource.AudioBeams (13) Dim myAudioStream = myAudioBeamList(0).OpenInputStream (14) myKinectAudioStream = New KinectAudioStream(myAudioStream) (15) End If Catch myKinect.Close() myKinect = Nothing End Try SpeechEngine = New SpeechRecognitionEngine(SpeechID) (16) Dim myWord As New Choices With myWord .Add(“じゃんけんぽん”) (17) End With Dim myGrammerBuilder As New GrammarBuilder myGrammerBuilder.Culture = SpeechEngine.RecognizerInfo.Culture myGrammerBuilder.Append(myWord) (18) Dim myGrammer As New Grammar(myGrammerBuilder) (19) SpeechEngine.LoadGrammar(myGrammer) (20) AddHandler SpeechEngine.SpeechRecognized, AddressOf speechEngine_SpeechRecognized (21) myKinectAudioStream.SpeechActive = True (22) SpeechEngine.SetInputToAudioStream(myKinectAudioStream, New SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, Nothing)) (23) SpeechEngine.RecognizeAsync(RecognizeMode.Multiple) (24) End Sub
- 最初に、Kinectセンサーを使用可能にします。XElement.Loadメソッドで「Jyanken.xml」を読み込みます。
Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。 - 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
- Kinectを動作させます。
- BodyFrameSource.OpenReaderで、ボディフレームのソースフレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
- myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
- ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
- 距離フレームプロパティのWidthとHeightで初期化された、新しいRectを、変数myRectで参照します。
- myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。
- カラー画像の情報を作成(BGRAフォーマット)し、変数myColorFrameDescriptonで参照します。
- カラーフレームのプロパティBytesPerPixelで、ピクセル データのサイズ (ピクセルあたりのバイト) を取得し、メンバー変数BytesPerPixelに格納します。
- 動的配列変数ColorImagePixelDataを確保します。
- ピクセル データを格納するビットマップを作成し、変数colorBitmapで参照します。
- オーディオビームを取得し、配列変数myAudioBeamListに格納します。
- OpenInputStreamで音声入力設定を行い、変数myAudioStreamで参照します。
- myAudioStreamで初期化されたKinectAudioStreamのインスタンスである、myKinectAudioStreamオブジェクトを作成します。
- 定数メンバー変数SpeechIDで初期化されたSpeechRecognitionEngineのインスタンス、SpeechEngineオブジェクトを作成します。
- Choicesクラスは、要素を構成するための代替項目の一覧を表すクラスで、GrammarBuilder オブジェクトからのみ直接使用されます。認識させる言葉をAddメソッドで登録します。ここでは「じゃんけんぽん」と登録しています。
- GrammarBuilderクラスは、単純な入力から複雑な Grammar(構文情報を取得管理するクラス)を構築するためのメカニズムを提供するクラスで、登録された言葉の構文(文法)の設定を行います。Appendメソッドで、登録した言葉(myWord)を myGrammarBuilder オブジェクトに追加します。
- 文法のチェックされた言葉(myGrammerBuilder)で初期化された、新しいGrammerクラスのインスタンス、myGrammerオブジェクトを作成します。Grammerクラスは、構文情報を取得および管理するためにランタイムをサポートするクラスです。
- SpeechRecognitionEngineクラスのLoadGrammerメソッドで、Grammar によって指定されたとおりに、特定の構文を同期的に読み込みます。
- SpeechEngine.SpeechRecognizedで音声が認識された時に、音声認識処理を行います。
- SpeechActiveプロパティにTrueを指定し、オーディオストリームの変換をアクティブにします。この記述がないと音声が認識されませんので、注意して下さい。
- SetInputToAudioStreamメソッドで認識エンジンに入力設定を行います。
- 複数の音声認識が可能なように、RecognizeMode.Multipleを指定して、RecognizeAsyncメソッドで非同期音声認識を開始します。
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。
全文検索エンジンによるおすすめ記事
- Kinect v2の音声認識で「仮面」を選んで変身してみる
- Kinect v2を使って、机の上のリンゴをつかんで移動してみる
- Kinect v2のジェスチャーでBing Mapsを未来的に直感操作する
- Kinect v2で実現する打楽器のバーチャル演奏
- Kinect v2のカメラから画像を取り込んで表示する基本プログラム
- Kinectで人体を認識して棒人間を動かすサンプル
- Kinectの音声認識を使ってWebブラウザを操作するサンプル
- 声で選んだアイテムをプレイヤーの身体に装着・連動させるKinectサンプル
- Kinectを使って、自分の手のひらに小さな分身を出現させてみる
- KinectButtonを動的に作成して、ジェスチャーで文字を表示させるサンプル