2012年9月8日土曜日

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

前回の音声認識サンプルではプログラム内で認識したい言葉を記述していましたが、SpeechPlatform自体はSRGS(Speech Recognition Grammar Specification)形式でのGrammar設定もできるようになっています。SRGSはxmlですので決められたタグを用いて、柔軟に認識させたい言葉、文章を記述することができます。

まずはGrammarファイルです。今回は2つ用意しました。

greeting.xml
------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8" ?>
<grammar xml:lang="ja-JP" version="1.0"
xmlns="http://www.w3.org/2001/06/grammar"
tag-format="semantics/1.0" root="greeting">

  <rule id="greeting">
    <one-of>
      <item>おはよう</item>
      <item>こんにちは</item>
      <item>こんばんは</item>
    </one-of>
  </rule>

</grammar>
------------------------------------------------------------------------------
前半はほぼ固定された内容になります。rootエレメントは自由に記述できます。
ruleタグのidエレメントも自由に記述することができます。
itemタグで認識させたい内容を記述するのですが、one-ofタグがない場合には連続した言葉として登録されます。one-ofタグでくくることによりitemタグ毎の言葉として登録することができるようになります。

次は文章を表すSRGSの記述方法です。

main.xml
------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<grammar xml:lang="ja-JP" version="1.0" 
xmlns="http://www.w3.org/2001/06/grammar"
tag-format="semantics/1.0" root="main">

  <rule id="main">
    <item>
      <ruleref uri="#fruits" />
      を
      <ruleref uri="#verb" />
    </item>
  </rule>

  <rule id="fruits" scope="public">
      <one-of>
        <item>みかん</item>
        <item>りんご</item>
        <item>すいか</item>
        <item>なし</item>
        <item>ぶどう</item>
      </one-of>
  </rule>

  <rule id="verb" scope="public">
      <one-of>
        <item>とる</item>
        <item>かう</item>
        <item>むく</item>
        <item>たべる</item>
      </one-of>
  </rule>

</grammar>
------------------------------------------------------------------------------
rulerefタグを使うことで別に記述したruleタグの内容を当てはめることができるようになります。
このファイルの場合mainのところで「fruitsの内のどれか1つ」 + 「を」 + 「verb」の内のどれか一つという文章を定義しています。
フルーツ5種類×動詞4種類=20種類の文章を定義していることになります。
rulerefタグで参照されるruleタグではscopeエレメントにpublicを指定してください。

以上のファイルをUTF-8形式で保存してください。

プロジェクト>追加>既存の項目で2つのファイルを追加してください。

画面設定です。
MainWindows.xaml
------------------------------------------------------------------------------
<Window x:Class="KinectSpeech2forSDK15.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="50" HorizontalAlignment="Left" Margin="12,90,0,0" Name="textBox1" VerticalAlignment="Top" Width="479" TextAlignment="Center" FontSize="36" Text="" />
    </Grid>
</Window>
------------------------------------------------------------------------------
テキストボックスを1つ配置しています。

メインプログラムです。
MainWindows.xaml.cs
------------------------------------------------------------------------------
using System;
using System.Windows;

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

namespace KinectSpeech2forSDK15
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private KinectSensor kinect;
        private KinectAudioSource audio;
        private SpeechRecognitionEngine sre;

        //日本語音声認識エンジンの名前
        const string sreName = "SR_MS_ja-JP_Kinect_11.0";

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

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

        }

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

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

            //Grammarファイルを読み込む(SRGS形式)
            var greet = new Grammar("../../greeting.xml");
            var ma = new Grammar("../../main.xml");

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

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

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

            //KINECTのマイク入力
            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;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closed(object sender, EventArgs e)
        {
            if (kinect != null)
            {
                if (kinect.IsRunning == true)
                {
                    kinect.AudioSource.Stop();
                    kinect.Stop();
                    sre.RecognizeAsyncStop();
                }
            }
        }

    }
}
------------------------------------------------------------------------------
プログラムの基本的な部分は以前のサンプルとほぼ一緒です。
Grammarを指定する部分でSRGS形式で記述したxmlファイルを読み込んでいます。

KINECTにおける音声認識の目的はPCを音声でコントロールすることがメインのようです。
ただ、SpeechPlatformは現在LyncServerにも含まれていますので、コミュニケーションアイテムとしての可能性もあるのではないかと思います。

参考としてKINECTを使ったこんなプロジェクトもあるようです。



0 件のコメント:

コメントを投稿