2012年9月2日日曜日

KINECTサンプル(C#) Speech for SDK1.5

今回のサンプルは音声認識です。
KINECTにはアレイマイクが内蔵されています。
このマイク入力を利用して音声でPCなどをコントロールすることができます。
ただ、一部誤解があるのですが、KINECT自体に音声を認識する機能は持っていません。あくまでもマイクの機能があるだけです。音声認識自体はPC上の音声認識エンジンで行われます。

最初に音声認識のための参照設定が必要です。

参照の追加で「C:\Program Files\Microsoft SDKs\Speech\v11.0\Assembly\Microsoft.Speech.dll」を直接選択してください。

あと忘れずに日本語認識エンジンもインストールする必要があります。
DeveloperToolKitのKinect Speech Language PacksからWEBサイトに移動して「KinectSpeechLanguagePack_ja-JP.exe」をダウンロードしてインストールしてください。

次に画面のサンプルです。


MainWindow.xaml
------------------------------------------------------------------------------

<Window x:Class="KinectSpeechforSDK15.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Closed="Window_Closed">
    <Grid>
        <TextBox Height="66" HorizontalAlignment="Left" Margin="12,94,0,0" Name="textBox1" VerticalAlignment="Top" Width="479" FontSize="40" Text="" TextAlignment="Center" />
        <TextBox Height="24" HorizontalAlignment="Left" Margin="148,193,0,0" Name="textBox2" VerticalAlignment="Top" Width="195" TextAlignment="Center" />
    </Grid>
</Window>
------------------------------------------------------------------------------
今回はテキストボックスを2つ配置しています。上のテキストボックスには認識した言葉を表示します。下のテキストボックスには認識した時の信頼度を表示しています。

次はプログラム本体です。

MainWindow.xaml.cs
------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO;

using Microsoft.Kinect;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;


namespace KinectSpeechforSDK15
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        
        private KinectSensor kinect;
        private SpeechRecognitionEngine sre;
        
        //日本語音声認識エンジンの名前
        const string sreName="SR_MS_ja-JP_Kinect_11.0";
        
        //英語音声認識エンジンの名前
        //const string sreName = "SR_MS_en-US_Kinect_11.0";

        /// <summary>
        /// 
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            if (KinectSensor.KinectSensors.Count == 0)
            {
                MessageBox.Show("KINECTが見つかりません.");
                Close();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //KINECTの初期化
            kinect = KinectSensor.KinectSensors[0];

            //音声認識エンジンの初期化
            sre = new SpeechRecognitionEngine(sreName);

            //認識したい単語の設定
            var word = new Choices();

            //好きな単語を登録する。一部の漢字も使えるし、なぜか英語も使える
            word.Add("おはよう");
            word.Add("こんにちは");
            word.Add("こんばんは");
            word.Add("キネクト");
            word.Add("終わり");
            word.Add("STOP");
            word.Add("START");
            word.Add("上");
            word.Add("下");
            word.Add("さいしょ");

            //グラマービルダーの設定
            var gb = new GrammarBuilder();

            //グラマービルダーの言語設定を認識エンジンに合わせる
            gb.Culture = sre.RecognizerInfo.Culture;

            //グラマービルダーに単語を登録
            gb.Append(word);

            //グラマービルダーをもとにグラマーを設定
            var g = new Grammar(gb);

            //認識エンジンにグラマーを登録
            sre.LoadGrammar(g);

            //イベントの登録
            sre.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(sre_SpeechRecognized);
            sre.SpeechRecognitionRejected += new EventHandler<SpeechRecognitionRejectedEventArgs>(sre_SpeechRecognitionRejected);

            //KINECTのスタート
            kinect.Start();

            //KINECTのマイク入力
            KinectAudioSource audio = kinect.AudioSource;
            audio.AutomaticGainControlEnabled = false;
            audio.EchoCancellationMode = EchoCancellationMode.None;

            //マイク入力開始
            Stream s = audio.Start();

                //オーディオフォーマットの設定
                var speechAudioFormat = new SpeechAudioFormatInfo(EncodingFormat.Pcm,
                                                                    16000,
                                                                    16,
                                                                    1,
                                                                    32000,
                                                                    2,
                                                                    null);

                //認識エンジンに入力ストリームとフォーマットを指定
                sre.SetInputToAudioStream(s, speechAudioFormat);

                //認識開始(非同期、複数認識を有効にする。) 
                //※認識が可能になるのが数秒かかる
                sre.RecognizeAsync(RecognizeMode.Multiple);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void sre_SpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {
            textBox1.Text = "認識できません。";
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            //認識信頼度が0.7以上のときに認識したことにする 
            //(認識信頼度 -1<0<1 -1が低信頼度 0が標準 1が高信頼度 数字が大きいほど認識率が厳しくなる) 
            if (e.Result.Confidence >= 0.7)
            {
                //認識した単語の表示
                textBox1.Text = e.Result.Text;
                //認識信頼度の表示
                textBox2.Text = e.Result.Confidence.ToString();

                //KINECTの角度を変更する。(範囲は -27°~ 27°)
                switch (e.Result.Text)
                {
                    case "上":
                        if (kinect.ElevationAngle + 5 < 27)
                        {
                            kinect.ElevationAngle += 5;
                        }

                        break;

                    case "下":
                        if (kinect.ElevationAngle - 5 > -27)
                        {
                            kinect.ElevationAngle -= 5;
                        }

                        break;

                    case "さいしょ":
                        kinect.ElevationAngle = 0;

                        break;
                }
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            if (kinect != null)
            {
                if (kinect.IsRunning==true)
                {
                    kinect.AudioSource.Stop();
                    kinect.Stop();
                    sre.RecognizeAsyncStop();
                    kinect.Dispose();
                }
            }
        }
    }
}
------------------------------------------------------------------------------


最初に青字の部分が追加になっています。
オーディオ入出力を扱うのでSysytem.IOが必要になります。
後の2行は音声認識のために追加が必要です。

おおまかな処理の流れは
「認識エンジンの選択」>「認識エンジンにグラマー(単語など)を登録」>「認識エンジンに音声入力を指定」>「認識の開始」となります。

認識エンジンの選択では日本語以外の認識エンジンも選択できます。
KINECT用には現在12種類のエンジンがあるのですが、それ以外にも「http://www.microsoft.com/en-us/download/details.aspx?id=27224」でまだ多くの認識エンジンが公開されています。KINECT用にない言語を認識させたい場合にはインストールして利用することができます。(ファイル名に「SR」と入っているのが認識エンジンです。「TTS」と入っているのは音声合成エンジンなので間違えないようにしてください。)

今回のサンプルでは認識させたい言葉を直接プログラム内で記述しています。それ以外にXMLファイルに記述する方法などもあります。

おまけで「上」、「下」、「さいしょ」の言葉でKINECTの首ふりをするようにしました。
ただし連続で行うと例外が発生することもあるので少し間を開けて実行してください。(SDK1.5では連続でチルトモーターを動かせないようになっている気もしますが。)




0 件のコメント:

コメントを投稿