Kinect v2の音声認識で「仮面」を選んで変身してみる

2015年1月6日(火)
薬師寺 国安

プログラムコード

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbにリスト3のコードを記述します。今回もだいぶ長いので、頑張って下さい。

名前空間の読み込みとクラスの作成

リスト3:MainWindow.xaml.vbの一部

Imports Microsoft.Kinect
Imports Microsoft.Speech.AudioFormat
Imports Microsoft.Speech.Recognition
Imports KinectSensor_KinectAudioStream

Public Class Mask
    Public Property 画像名 As String
End Class
Class MainWindow

名前空間の読み込みについては、第2回目の解説を参照してください。

Maskクラス内で、文字列型の「画像名」というプロパティを定義します。

メンバー変数の宣言

リスト4:MainWindow.xaml.vbの一部、リスト3の続き

Private xmldoc As XElement
Private myKinect As KinectSensor
Private myBodyFrameReader As BodyFrameReader
Private myBodies As Body()
Private myHandPositionX As Double
Private myHandPositionY As Double
Private myColorSpacePoint As ColorSpacePoint   (1)
Private myBytesPerPixel As Integer = 4
Private myColorFrameReader As ColorFrameReader = Nothing
Private colorBitmap As WriteableBitmap = Nothing
Private ColorImagePixelData As Byte()
Private BytesPerPixel As Integer = 4
Private point As DepthSpacePoint   (2)
Private SpeechEngine As SpeechRecognitionEngine
Const SpeechID As String = "SR_MS_ja-JP_Kinect_11.0"
Private myKinectAudioStream As KinectAudioStream
Private Index As Integer = 0
Private myImage As Image   (3)
Private myMask As String   (3)

ほとんどが、第2回目と同じですので、異なるメンバー変数の主なものだけ解説しておきます。

  1. カラー空間における2Dの位置を表す構造体のメンバー変数myColorSpacePointを宣言します。
  2. 距離空間における2Dの位置を表す構造体のメンバー変数pointを宣言します。
  3. Image型のメンバー変数、myImageとmyMaskを宣言します。

ウインドウが読み込まれた時の処理

リスト5:MainWindow.xaml.vbの一部、リスト4の続き

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
    xmldoc = XElement.Load("mask.xml")   (1)
    Dim maskList As New List(Of Mask)   (2)

    For Each result In From c In xmldoc.Descendants("画像名") Select c
        maskList.Add(New Mask With {.画像名 = "Images/" & result.Value}) (3)
    Next
    ListBox1.ItemsSource = maskList   (4)

    myKinect = KinectSensor.GetDefault   (5)
    If myKinect Is Nothing = False Then
        Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription   (6)
        myKinect.Open()   (7)
        myBodyFrameReader = myKinect.BodyFrameSource.OpenReader  (8)
        AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived   (9)
        myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {} (10)
        myColorFrameReader = myKinect.ColorFrameSource.OpenReader (11)
        Dim myColorFrameDescription As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra)    (12)
        ColorImagePixelData = New Byte(myColorFrameDescription.Width * myColorFrameDescription.Height * BytesPerPixel - 1) {}   (13)
        colorBitmap = New WriteableBitmap(myColorFrameDescription.Width, myColorFrameDescription.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing)   (14)
        AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived   (15)
        Dim myAudioBeamList As IReadOnlyList(Of AudioBeam) = myKinect.AudioSource.AudioBeams   (16)
        Dim myAudioStream = myAudioBeamList(0).OpenInputStream   (17)
        myKinectAudioStream = New KinectAudioStream(myAudioStream)    (18)
    End If

    SpeechEngine = New SpeechRecognitionEngine(SpeechID)    (19)
    Dim myWord As New Choices   (20)
    With myWord
        .Add("うえ")
        .Add("した")
    End With

    Dim myGrammarBuilder As New GrammarBuilder
    myGrammarBuilder.Culture = SpeechEngine.RecognizerInfo.Culture
    myGrammarBuilder.Append(myWord)      (21)
    Dim myGrammar As New Grammar(myGrammarBuilder)    (22)
    SpeechEngine.LoadGrammar(myGrammar)   (23)

    AddHandler SpeechEngine.SpeechRecognized, AddressOf speechEngine_SpeechRecognized   (24)
    myKinectAudioStream.SpeechActive = True   (25)
    SpeechEngine.SetInputToAudioStream(myKinectAudioStream, New SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, Nothing))    (26)
    SpeechEngine.RecognizeAsync(RecognizeMode.Multiple)    (27)
End Sub
  1. XElement.Loadメソッドで「Mask.xml」を読み込みます。
  2. Maskクラス型の新しいリストであるmaskListを作成します。
    全ての子孫要素「画像名」用の内容を変数resultに格納しながら、以下の処理を行います。
  3. maskListオブジェクトに、Maskクラスの「画像名」プロパティに、「画像名」要素の値を、フォルダー名である「Images」を連結して、Addメソッドで追加します。
  4. ListBox1のItemsSourceプロパティにmaskListオブジェクトを追加します。これで、ListBoxにマスク画像の一覧が表示されます。
  5. Kinectセンサーを使用可能にします。
    Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。
  6. 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
  7. Kinectを動作させます。
  8. BodyFrameSource.OpenReaderで、ボディ フレームのソース フレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
  9. myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
  10. ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
  11. myKinect.ColorFrameSource.OpenReaderで、カラー フレームのソース フレームのリーダーを作成し、myColorFrameReaderメンバー変数で参照します。
  12. カラー画像の情報を作成し、変数myColorFrameDescriptionで参照します。
  13. 配列変数ColorImagePixelDataを確保します。
  14. ピクセル データを格納するビットマップを作成し、変数colorBitmapで参照します。
  15. myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。
  16. オーディオビームを取得し、配列変数myAudioBeamListに格納します。
  17. OpenInputStreamで音声入力設定を行い、変数myAudioStreamで参照します。
  18. myAudioStreamで初期化された新しいKinectAudioStreamのインスタンスである、myKinectAudioStreamオブジェクトを作成します。
  19. 定数メンバー変数SpeechIDで初期化された、新しいSpeechRecognitionEngineのインスタンス、SpeechEngineオブジェクトを作成します。
  20. Choicesクラスは、要素を構成するための代替項目の一覧を表すクラスで、GrammarBuilder オブジェクトからのみ直接使用されます。認識させる言葉をAddメソッドで登録します。ここでは「うえ」と「した」の2語を登録しています。
  21. GrammarBuilderクラスは、単純な入力から複雑な Grammar(構文情報を取得管理するクラス)を構築するためのメカニズムを提供するクラスで、登録された言葉の構文(文法)を設定します。Appendメソッドで、登録した言葉(myWord)を myGrammarBuilder オブジェクトに追加します。
  22. 文法のチェックされた言葉(myGrammarBuilder)で初期化された、新しいGrammarクラスのインスタンス、myGrammarオブジェクトを作成します。Grammarクラスは、構文情報を取得および管理するためのランタイムをサポートするクラスです。
  23. SpeechRecognitionEngineクラスのLoadGrammarメソッドで、Grammar によって指定されたとおりに、特定の構文を同期的に読み込みます。
  24. SpeechEngine.SpeechRecognizedで音声が認識された時に、音声認識処理を行います。
  25. SpeechActiveプロパティにTrueを指定し、オーディオストリームの変換をアクティブにします。この記述がないと音声が認識されませんので、注意して下さい。
  26. SetInputToAudioStreamメソッドで認識エンジンに入力設定を行います。
  27. 複数の音声認識が可能なように、RecognizeMode.Multipleを指定して、RecognizeAsyncメソッドで非同期音声認識を開始します。
  • 音声認識で仮面を装着するKinect v2プログラム

    『作りながら学ぶKinect v2プログラミング開発』 第4回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。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メルマガ会員のサービス内容を見る

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