2011年12月10日土曜日

KINECT SDK 日本語で音声認識

先日の英語バージョンをちょっと変更して日本語も認識できるようにしてみました。

予め以下のランゲージパックをダウンロードしてインストールしてください。

http://www.microsoft.com/download/en/details.aspx?id=21924より

「MSSpeech_SR_ja-JP_TELE.msi」をダウンロードしてください。

リストの下の方には「MSSpeech_TTS_ja-JP_Haruka.msi」がありますがこちらは音声合成用のランゲージパックになりますので間違えないようにしてください。
それから最新のSpeechPlatfprmのバージョンは11ですが、ランゲージパックはバージョンに依存するみたいですので間違えないようにしましょう。KINECTの環境は10.2になります。

次にソースコードです。

---------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Research.Kinect.Nui;        //追加
using Microsoft.Research.Kinect.Audio;      //追加
using Microsoft.Speech.Recognition;         //追加
using Microsoft.Speech.AudioFormat;         //追加


namespace SpeechElevation
{
    public partial class Program
    {
        static Runtime nui;
        static Camera cam;

        public static void Main(string[] args)
        {
            //初期化
            if (Runtime.Kinects.Count == 0)
            {
                return;
            }

            nui = Runtime.Kinects[0];
            nui.Initialize(RuntimeOptions.UseColor);
            cam = nui.NuiCamera;

            //カメラの位置を初期化
            CamInit();

            //オーディオソース
            using (var source = new KinectAudioSource())
            {
                source.FeatureMode = true;
                source.AutomaticGainControl = false;  //音声認識のときは必ずfalse
                source.SystemMode = SystemMode.OptibeamArrayOnly;

                //認識エンジンの選択
                RecognizerInfo ri = GetKinectRecognizer();

                if (ri == null)
                {
                    Console.WriteLine("認識エンジンが見つかりません。");
                    return;
                }

                Console.WriteLine("認識エンジン: {0}", ri.Name);

                //認識エンジンの準備
                using (var sre = new SpeechRecognitionEngine(ri.Id))
                {
                    //認識する語句の準備
                    var wd = new Choices();
                    wd.Add("ぜろ");
                    wd.Add("うえ");
                    wd.Add("した");
                    wd.Add("最初");   //漢字も使える

                    var gb = new GrammarBuilder();
                    //GrammerBuilderのCultureと認識エンジンのCultureを合わせる
                    gb.Culture = ri.Culture;
                    gb.Append(wd);

                    var g = new Grammar(gb);

                    sre.LoadGrammar(g);

                    //イベントハンドラの追加
                    sre.SpeechRecognized += SreSpeechRecognized;
                    sre.SpeechHypothesized += SreSpeechHypothesized;
                    sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;

                    //認識の開始
                    using (Stream s = source.Start())
                    {
                        sre.SetInputToAudioStream(s,
                                                  new SpeechAudioFormatInfo(
                                                      EncodingFormat.Pcm, 16000, 16, 1,
                                                      32000, 2, null));

                        Console.WriteLine("認識開始:");

                        sre.RecognizeAsync(RecognizeMode.Multiple);

                        Console.ReadLine();

                    }
                }
            }
        }

        private static RecognizerInfo GetKinectRecognizer()
        //認識エンジンを直に設定
        {
            return SpeechRecognitionEngine.InstalledRecognizers().Where(r => r.Id == "SR_MS_ja-JP_TELE_10.0").FirstOrDefault();
        }

        static void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {
            Console.WriteLine("\n認識できません。");
        }

        static void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
        {
            Console.Write("\r入力音声: \t{0}", e.Result.Text);
        }

        static void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            Console.WriteLine("\n認識しました。: \t{0}", e.Result.Text);

            switch (e.Result.Text)
            {
                case "うえ":
                    CamUp();
                    break;
                case "した":
                    CamDown();
                    break;
                case "ぜろ":
                    CamInit();
                    break;
                case "最初":
                    CamInit();
                    break;
            }

        }

        //カメラを上に
        static void CamUp()
        {
            var nowangle = cam.ElevationAngle + 5;

            if (nowangle > 25)
            {
                cam.ElevationAngle = 25;
            }
            else
            {
                cam.ElevationAngle = nowangle;
            }
        }
        //カメラを下に
        static void CamDown()
        {
            var nowangle = cam.ElevationAngle - 5;

            if (nowangle < -25)
            {
                cam.ElevationAngle = -25;
            }
            else
            {
                cam.ElevationAngle = nowangle;
            }
        }

        //カメラを水平に
        static void CamInit()
        {
            cam.ElevationAngle = 0;
        }

    }

}

---------------------------------------------------------------------------------

変更したところはテキストの色を変えていますが、一番のキモは認識エンジンに読み込ませるランゲージパックの名前です。
このことから他の言語でも同じくランゲージパックをインストールしてあげれば問題なく動作すると思います。
すこし謎なのが、なぜわざわざKINECT用にランゲージパックを用意しているのかですが、実際にSpeechPlatform用en-USランゲージパックとKINECT用では内容が少し違うようです。推測ですがKINECT用は文法関係の辞書に何か手を加えてあるのかもしれません。容量はKINECT用の方が大きいですので。

しかし、SpeechPlatformの情報は少ないです。
今は単語レベルでの認識までですが、短めの文章なんかも認識できるのか試してみたいです。

0 件のコメント:

コメントを投稿