Kinect v2を使った「じゃんけんゲーム」を作る
2014年12月16日(火)

XMLファイルの作成(Jyanken.xml)
VS2013メニューの[プロジェクト]ー[新しい項目の追加]を選択して、表示される画面から「データ」を指定し、表示される項目から「XMLファイル」を選択します。名前には「Jyanken.xml」と指定し、最後に「追加」ボタンをクリックします(図6)。
するとXMLエディターが起動しますので、リスト2のXMLを記述します。
リスト2 Jyanken.xml
1 | <?xml version="1.0" encoding="utf-8" ?> |
2 | <じゃんけん> |
3 | <画像名>グー.png</画像名> |
4 | <画像名>チョキ.png</画像名> |
5 | <画像名>パー.png</画像名> |
6 | </じゃんけん> |
追加したXMLファイルを選択してプロパティを表示します。「ビルドアクション」に「コンテンツ」、「出力ディレクトリーコピー」に「常にコピーする」と指定して下さい(図7)。この設定を忘れるとエラーになりますので、注意してください。

図7:XMLファイルのプロパティを設定した
プログラムコード
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示されるMainWindow.xam.vbに、リスト3以降のコードを記述します。かなり分量が多いですが、がんばって下さい。
名前空間の読み込み
リスト3(MainWindow.xaml.vbの一部)
1 | Imports System.ComponentModel (1) |
2 | Imports Microsoft.Kinect (2) |
3 | Imports Microsoft.Speech.AudioFormat (3) |
4 | Imports Microsoft.Speech.Recognition (4) |
5 | Imports KinectSensor_KinectAudioStream (5) |
6 | Imports System.IO |
7 | Public Class MainWindow |
- コンポーネントやコントロールの実行時動作、およびデザイン時動作を実装するためのクラスが用意されているSystem.ComponentModel名前空間を読み込みます。
- Kinectを扱うためのクラスが含まれるMicrosoft.Kinect名前空間を読み込みます。
- 音声認識用のオーディオ形式を表すクラスが含まれるMicrosoft.Speech.AudioFormat名前空間を読み込みます。
- 音声認識を実装するためのクラスが含まれるMicrosoft.Speech.Recognition名前空間を読み込みます。
- オーディオストリームのクラスを提供するKinectSensor_KinectAudioStream名前空間を読み込みます。これは、ソリューションエクスプローラー内のDLLフォルダーに配置したKinectAudioStreamを、参照設定に追加したものです。
メンバー変数の宣言
リスト4 (MainWindow.xaml.vbの一部、リスト3の続き)
01 | Private myKinect As KinectSensor (1) |
02 | Private myBodyFrameReader As BodyFrameReader (2) |
03 | Private myColorFrameReader As ColorFrameReader = Nothing (3) |
04 | Private colorBitmap As WriteableBitmap = Nothing (4) |
05 | Private BytesPerPixel As Integer = 4 (5) |
06 | Private ColorImagePixelData As Byte() (6) |
07 | Private Rnd As Random (7) |
08 | Private RandomNumber As Integer |
09 | Private SpeechEngine As SpeechRecognitionEngine (8) |
10 | Const SpeechID As String = "SR_MS_ja-JP_Kinect_11.0" (9) |
11 | Private myKinectAudioStream As KinectAudioStream (10) |
12 | Private Index As Integer = 0 |
13 | Private myBodies As Body() (11) |
14 | Private myBodyDrawingGroup As New DrawingGroup (12) |
15 | Private myRect As Rect (13) |
16 | Private JyankenImage As String |
17 | Private xmldoc As XElement (14) |
18 | Private flagImage As String |
19 | Private player_Score As Integer = 0 |
20 | 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を宣言します。
ウインドウが読み込まれた時の処理
リスト5 (MainWindow.xaml.vbの一部、リスト4の続き)
01 | Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded |
02 | myKinect = KinectSensor.GetDefault |
03 | xmldoc = XElement.Load("Jyanken.xml") (1) |
04 |
05 | Try |
06 | If myKinect Is Nothing = False Then |
07 | Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription (2) |
08 | myKinect.Open() (3) |
09 | myBodyFrameReader = myKinect.BodyFrameSource.OpenReader (4) |
10 | AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived (5) |
11 | myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {} (6) |
12 | myRect = New Rect(0, 0, myDepthDescription.Width, myDepthDescription.Height) (7) |
13 | myColorFrameReader = myKinect.ColorFrameSource.OpenReader |
14 | AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived (8) |
15 | Dim myColorFrameDescripton As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra) (9) |
16 | BytesPerPixel = myColorFrameDescripton.BytesPerPixel (10) |
17 | ReDim ColorImagePixelData(myColorFrameDescripton.Width * myColorFrameDescripton.Height * BytesPerPixel – 1) (11) |
18 | colorBitmap = New WriteableBitmap(myColorFrameDescripton.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing) (12) |
19 | Dim myAudioBeamList As IReadOnlyList(Of AudioBeam) = myKinect.AudioSource.AudioBeams (13) |
20 | Dim myAudioStream = myAudioBeamList(0).OpenInputStream (14) |
21 | myKinectAudioStream = New KinectAudioStream(myAudioStream) (15) |
22 | End If |
23 | Catch |
24 | myKinect.Close() |
25 | myKinect = Nothing |
26 | End Try |
27 | SpeechEngine = New SpeechRecognitionEngine(SpeechID) (16) |
28 | Dim myWord As New Choices |
29 | With myWord |
30 | .Add(“じゃんけんぽん”) (17) |
31 | End With |
32 |
33 | Dim myGrammerBuilder As New GrammarBuilder |
34 | myGrammerBuilder.Culture = SpeechEngine.RecognizerInfo.Culture |
35 | myGrammerBuilder.Append(myWord) (18) |
36 | Dim myGrammer As New Grammar(myGrammerBuilder) (19) |
37 | SpeechEngine.LoadGrammar(myGrammer) (20) |
38 |
39 | AddHandler SpeechEngine.SpeechRecognized, AddressOf speechEngine_SpeechRecognized (21) |
40 | myKinectAudioStream.SpeechActive = True (22) |
41 | SpeechEngine.SetInputToAudioStream(myKinectAudioStream, New SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, Nothing)) (23) |
42 | SpeechEngine.RecognizeAsync(RecognizeMode.Multiple) (24) |
43 | 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を動的に作成して、ジェスチャーで文字を表示させるサンプル