参照の追加
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)
2 | Imports Microsoft.Kinect |
音声認識を実装するためのクラスが含まれる、Microsoft.Speech.Recognition名前空間をインポートします。
Imports Microsoft.Speech.Recognition
音声認識用のオーディオ形式を表すクラスが含まれる、Microsoft.Speech.AudioFormat名前空間をインポートします。
Imports Microsoft.Speech.AudioFormat
一つのKinectセンサーを表すメンバ変数Kinectを宣言します。
1 | Dim Kinect As KinectSensor |
XML要素を表すXElementクラス型のメンバ変数xmldocを宣言します。
音声認識サービスを実行するためのアクセス権を提供するSpeechRecognitionEngineクラス用メンバ変数engineを宣言します。
1 | Dim engine As SpeechRecognitionEngine |
ウィンドウが読み込まれた時の処理
Kinectセンサーを開始し、音声認識を開始するDataShowプロシージャを実行します。
1 | Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded |
Kinectセンサーを開始し、音声認識を開始する処理
bin\Debugフォルダ内のPersonalInfo.xmlを読み込みます。
Kinectセンサーを開始し、音声認識を開始するcreateSpeechRecognizerプロシージャを実行します。
02 | xmldoc = XElement.Load("PersonalInfo.xml") |
03 | If KinectSensor.KinectSensors.Count = 0 Then |
04 | MessageBox.Show("KINECTが接続されておりません。") |
07 | Kinect = KinectSensor.KinectSensors(0) |
09 | createSpeechRecognizer() |
認識させる言葉を登録し、音声認識を開始する処理
音声認識サービスを実行するためのアクセス権を提供する、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メソッドで非同期音声認識を開始します。
001 | Private 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) |
007 | sentence.Add("Datain") |
008 | sentence.Add("Datasearch") |
011 | sentence.Add("Continue") |
014 | Dim myGrammerBuilder = New GrammarBuilder |
015 | myGrammerBuilder.Append(sentence) |
016 | Dim myGrammer = New Grammar(myGrammerBuilder) |
017 | engine.LoadGrammar(myGrammer) |
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 |
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 = "該当なし" |
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 |
035 | If myName = "Datain" Then |
036 | DataIn.Visibility = Windows.Visibility.Visible |
037 | myStackPanel.Visibility = Windows.Visibility.Collapsed |
038 | DataSearch.Visibility = Windows.Visibility.Collapsed |
041 | If myName = "Datasearch" Then |
043 | Dim myCountQuery = From c In xmldoc.Descendants("情報") Select c |
045 | If myCountQuery.Count <= 0 Then |
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 |
058 | If myName = "Menu" Then |
059 | DataIn.Visibility = Windows.Visibility.Collapsed |
060 | DataSearch.Visibility = Windows.Visibility.Collapsed |
061 | myStackPanel.Visibility = Windows.Visibility.Visible |
064 | If myName = "Save" Then |
066 | Dim myError As Integer = System.Convert.ToInt16(ageTextBox.Text, 10) |
067 | Catch ex As Exception |
069 | messageTextBlock.Text = "年齢が不正です。" |
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 |
084 | If myName = "End" Then |
085 | If Kinect.IsRunning = True Then |
087 | Kinect.AudioSource.Stop() |
096 | Dim audio As KinectAudioSource = Kinect.AudioSource |
098 | Using s As Stream = audio.Start() |
099 | engine.SetInputToDefaultAudioDevice() |
100 | engine.RecognizeAsync(RecognizeMode.Multiple) |