Kinectを使った、音声によるデータ保存と検索のサンプル

2012年8月24日(金)
薬師寺 国安

参照の追加

VS2010のメニューから「プロジェクト(P)/参照の追加(R)」と選択して、各種コンポーネントを追加しておきます。今回追加するのは、Microsoft.KinectとMicrosoft.Speechの2つです。「.NET」タブ内に表示されていないDLLファイルは「参照」タブからDLLファイルを指定します。

Microsoft.Kinect.dllは、C:\Program Files\Microsoft SDKs\Kinect\v1.5\Assemblies内に存在しますので、これを指定します。

Microsoft.Speech.dllは
C:\Windows\assembly\GAC_MSIL\Microsoft.Speech\11.0.0.0__31bf3856ad364e35\に存在しますので、これを指定してください。このassemblyフォルダ内のGAC_MSILフォルダは「参照の追加(R)」の「参照」タブからでないと参照できません。
マイコンピューターからは、このフォルダは表示されませんので注意してください。

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbをダブルクリックして、リスト3のコードを記述します。

ロジックコードを記述する

リスト3 (MainWindow.xaml.vb)

1Option Strict On
2Imports Microsoft.Kinect
3Imports System.IO

音声認識を実装するためのクラスが含まれる、Microsoft.Speech.Recognition名前空間をインポートします。

Imports Microsoft.Speech.Recognition

音声認識用のオーディオ形式を表すクラスが含まれる、Microsoft.Speech.AudioFormat名前空間をインポートします。

Imports Microsoft.Speech.AudioFormat

1Class MainWindow

一つのKinectセンサーを表すメンバ変数Kinectを宣言します。

1Dim Kinect As KinectSensor

XML要素を表すXElementクラス型のメンバ変数xmldocを宣言します。

1Dim xmldoc As XElement

音声認識サービスを実行するためのアクセス権を提供するSpeechRecognitionEngineクラス用メンバ変数engineを宣言します。

1Dim engine As SpeechRecognitionEngine

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

Kinectセンサーを開始し、音声認識を開始するDataShowプロシージャを実行します。

1Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
2  DataShow()
3End Sub

Kinectセンサーを開始し、音声認識を開始する処理

bin\Debugフォルダ内のPersonalInfo.xmlを読み込みます。
Kinectセンサーを開始し、音声認識を開始するcreateSpeechRecognizerプロシージャを実行します。

01Private Sub DataShow()
02  xmldoc = XElement.Load("PersonalInfo.xml")
03  If KinectSensor.KinectSensors.Count = 0 Then
04    MessageBox.Show("KINECTが接続されておりません。")
05    Exit Sub
06  Else
07    Kinect = KinectSensor.KinectSensors(0)
08    Kinect.Start()
09    createSpeechRecognizer()
10  End If
11End Sub

認識させる言葉を登録し、音声認識を開始する処理

音声認識サービスを実行するためのアクセス権を提供する、SpeechRecognitionEngineクラスの新しいインスタンスengineオブジェクトを作成します。
要素を構成するための代替項目の一覧を表すChoicesクラスのインスタンス、sentenceオブジェクトを作成します。Choiceクラスは、GrammarBuilder オブジェクトからのみ直接使用されます。
Descendantsメソッドで、子孫要素であるすべての 要素のコレクションに対して、各要素を変数 result に格納しながら、以下の処理を繰り返します。

要素の値をAddメソッドで、認識させる言葉としてChoicesオブジェクトであるsentenceに追加します。また、Datain、Datasearch、Menu、Save、Continue、Endという語句も追加しておきます。

GrammarBuilderクラスは、単純な入力から複雑な Grammar(構文情報を取得管理するクラス)を構築するためのメカニズムを提供するクラスで、登録された言葉の構文(文法)設定を行い、SpeechRecognitionEngineへと設定します。
Appendメソッドで、登録した言葉を GrammarBuilder オブジェクトとして現在の GrammarBuilder に追加します。

文法のチェックされた言葉(myGrammerBuilder)で初期化された、新しいGrammerクラスのインスタンス、myGrammerオブジェクトを作成します。Grammerクラスは、構文情報を取得および管理するためにランタイムをサポートするクラスです。

SpeechRecognitionEngineクラスのLoadGrammerメソッドで、Grammar によって指定されたとおりに、特定の構文を同期的に読み込みます。

言葉が認識された際には、AddHandlerステートメントで言葉を認識した際に発生するSpeechRecognizedイベントに、イベントハンドラを指定します。

Confidenceプロパティで音声認識の信頼度を設定します。-1が低、0が標準、1が高信頼度となります。-1を指定するとどんな言葉でも反応する恐れがあります。1を指定するとなかなか認識してくれません。今回は信頼度が0.3より大きい場合に、指定した言葉を認識するよう指定しています。

認識された音声(speechArgs.Result.Text)を変数myNameに格納します。myNameの内容で条件分岐を行います。XML文書の要素の子要素の値が、変数myNameの値と同じである、要素を選択するクエリを定義します。結果クエリの個数が0の場合は、「氏名」の入力ボックスに「該当なし」と表示し、処理を抜けます。

定義したクエリ内を変数resultで反復処理しながら、「データ検索画面(この時点では非表示)」の各TextBoxに、該当する要素の内容テキストを表示します。

「Datain」と発声された場合は、メニューと検索画面を非表示にし、「データ入力」画面だけを表示します。

「Datasearch」と発声された場合は、Kinectセンサーを開始し、音声認識を開始するDataShowプロシージャを実行します。要素の個数を取得し、データがない場合は処理を抜けます。データが存在する場合は、各検索結果を表示するTextBoxを空に初期化し、「検索画面」だけを表示します。

「Menu」と発声された時は、「Menu」画面だけを表示します。

「Save」と発声された場合は、「年齢」入力欄に入力された値が数値かどうかを判別して、数値以外であった場合は、「年齢」の入力ボックスにフォーカスを移し、警告メッセージを表示して、処理を抜けます。入力されたデータをXMLに保存するDataSaveプロシージャを実行します。

「Continue」と発声された場合は、メッセージを表示するTextBlock内を空にし、各入力ボックスを空で初期化し、「氏名」の入力ボックスにフォーカスを移します。

「End」と発声された場合は、Kinectセンサーを停止し、音声認識も停止して、Environment.Exit(0)でプログラムを終了します。

Kinectの音声インターフェースは、Kinect.AudioSourceで提供されます。Startメソッドで音声入力を開始します。入力ストリームを取得し、SpeechRecognitionEngine クラスのSetInputToDefaultAudioDeviceメソッドで、SpeechRecognitionEngine の現在のインスタンスに、システム既定のオーディオ入力を割り当てます。

認識操作の後に、RecognizeAsync によって開始された認識を終了しないよう、RecognizeMode.Multipleを指定して、RecognizeAsyncメソッドで非同期音声認識を開始します。

001Private Sub createSpeechRecognizer()
002  engine = New SpeechRecognitionEngine()
003    Dim sentence = New Choices()
004  For Each result In From c In xmldoc.Descendants("情報") Select c
005    sentence.Add(result.Element("氏名").Value)
006  Next
007  sentence.Add("Datain")
008  sentence.Add("Datasearch")
009  sentence.Add("Menu")
010  sentence.Add("Save")
011  sentence.Add("Continue")
012  sentence.Add("End")
013 
014  Dim myGrammerBuilder = New GrammarBuilder
015  myGrammerBuilder.Append(sentence)
016  Dim myGrammer = New Grammar(myGrammerBuilder)
017  engine.LoadGrammar(myGrammer)
018 
019  AddHandler engine.SpeechRecognized, Sub(speechSender As Object, speechArgs As SpeechRecognizedEventArgs)
020    Dim confidence As Single = speechArgs.Result.Confidence
021    If confidence > 0.3 Then
022      Dim myName As String = speechArgs.Result.Text
023      Select Case myName
024        Case myName
025          Dim query = From c In xmldoc.Descendants("情報") Where c.Element("氏名").Value.Equals(myName) Select c
026            If query.Count = 0 Then
027              searchNameTextBox.Text = "該当なし"
028            End If
029            For Each result In query
030              searchNameTextBox.Text = result.Element("氏名").Value
031              searchAgeTextBox.Text = result.Element("年齢").Value
032              searchAddressTextBox.Text = result.Element("住所").Value
033              searchCompanyTextBox.Text = result.Element("勤務先").Value
034            Next
035            If myName = "Datain" Then
036              DataIn.Visibility = Windows.Visibility.Visible
037              myStackPanel.Visibility = Windows.Visibility.Collapsed
038              DataSearch.Visibility = Windows.Visibility.Collapsed
039            End If
040 
041            If myName = "Datasearch" Then
042              DataShow()
043              Dim myCountQuery = From c In xmldoc.Descendants("情報") Select c
044 
045              If myCountQuery.Count <= 0 Then
046                Exit Sub
047              Else
048                messageTextBlock.Text = String.Empty
049                searchNameTextBox.Text = String.Empty
050                searchAgeTextBox.Text = String.Empty
051                searchAddressTextBox.Text = String.Empty
052                searchCompanyTextBox.Text = String.Empty
053                myStackPanel.Visibility = Windows.Visibility.Collapsed
054                DataIn.Visibility = Windows.Visibility.Collapsed
055                DataSearch.Visibility = Windows.Visibility.Visible
056              End If
057            End If
058              If myName = "Menu" Then
059                DataIn.Visibility = Windows.Visibility.Collapsed
060                DataSearch.Visibility = Windows.Visibility.Collapsed
061                myStackPanel.Visibility = Windows.Visibility.Visible
062              End If
063             
064              If myName = "Save" Then
065                Try
066                  Dim myError As Integer = System.Convert.ToInt16(ageTextBox.Text, 10)
067                Catch ex As Exception
068                  ageTextBox.Focus()
069                  messageTextBlock.Text = "年齢が不正です。"
070                  Exit Sub
071                End Try
072                  DataSave()
073                End If
074 
075                If myName = "Continue" Then
076                  messageTextBlock.Text = String.Empty
077                  nameTextBox.Text = String.Empty
078                  ageTextBox.Text = String.Empty
079                  addressTextBox.Text = String.Empty
080                  companyTextBox.Text = String.Empty
081                  nameTextBox.Focus()
082                End If
083 
084                If myName = "End" Then
085                  If Kinect.IsRunning = True Then
086                    Kinect.Stop()
087                        Kinect.AudioSource.Stop()
088                        Environment.Exit(0)
089                      End If
090                    End If
091                  Case Else
092                    Exit Select
093                End Select
094              End If
095            End Sub
096  Dim audio As KinectAudioSource = Kinect.AudioSource
097 
098  Using s As Stream = audio.Start()
099    engine.SetInputToDefaultAudioDevice()
100    engine.RecognizeAsync(RecognizeMode.Multiple)
101  End Using
102End Sub
  • Kinectを使った、音声によるデータ保存と検索のサンプル

薬師寺国安事務所

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

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