2014年7月20日日曜日

KINECT V2で音声認識(SDK2.0β C#)

7月15日からKINECT for Windows V2が発売されました。SDK2.0もパブリックベータ版が同時に公開されています。

今回はハードが大幅に変更になっているのでSDKも色々変わっています。

ColorやDepthの解説はぼちぼちブログやIT系メディアで紹介されていますが、音声認識関連はなかなか出てこないです。

取り急ぎSDKのSpeechサンプルを参考にして簡単なプログラムを作ってみました。

開発環境は

Windows8.1Pro 64bit
Visual Studio Pro 2012

です。

その他 KINECT SDK2.0 及び SpeechPlatform SDK 11.0,LanguagePack_jaJPもインストールしてください。

サンプルプログラムはC#+WPFで作成しています。

最初にプロジェクトを新しく作成してから、SDK2.0βのSpeech Basics-WPFプロジェクトよりKinectAudioStream.csファイルをインポートして、namespaceを変更してください。

MainWindow.xaml
<Window x:Class="speech_jp.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" Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="tb1" HorizontalAlignment="Left" Height="30" Margin="10,82,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="497" FontSize="20"/>
        <TextBox x:Name="tb2" HorizontalAlignment="Left" Height="30" Margin="10,153,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="497" FontSize="20"/>
        <Label Content="認識した単語" HorizontalAlignment="Left" Margin="10,52,0,0" VerticalAlignment="Top" Width="107"/>
        <Label Content="信頼度" HorizontalAlignment="Left" Margin="10,123,0,0" VerticalAlignment="Top" Width="74"/>

    </Grid>
</Window>

説明:
 テキストボックスを2つ配置しています。


MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;
using Microsoft.Kinect;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

namespace speech_jp
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        //KINECT
        KinectSensor kinect=null;

        //AudioStream
        KinectAudioStream convertStream=null;

        //音声認識エンジン
        SpeechRecognitionEngine engine;

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

        //英語音声認識エンジンのID
        //const string engin_id = "SR_MS_en-US_Kinect_11.0";

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

        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //KINECTの準備
            try
            {
                kinect = KinectSensor.GetDefault();
                if (kinect == null)
                {
                    throw new Exception("KINECTを開けません。");
                }

                //KINECTの使用開始
                kinect.Open();

                //音声入力設定
                IReadOnlyList<AudioBeam> audioBeamList = kinect.AudioSource.AudioBeams;
                Stream audioStream = audioBeamList[0].OpenInputStream();

                //audioStreamのビット変換
                convertStream = new KinectAudioStream(audioStream);


            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                Close();
            }

            //音声認識エンジン設定
            engine = new SpeechRecognitionEngine(engin_id);

            //認識するワード
            var word = new Choices();

            word.Add("ハンバーグ");
            word.Add("ラーメン");
            word.Add("焼肉");
            word.Add("すし");
            word.Add("スパゲッティ");
            word.Add("卵焼き");
            word.Add("ぎゅう丼");
            word.Add("うどん");
            word.Add("からあげ");

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

            //言語設定
            gb.Culture = engine.RecognizerInfo.Culture;

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

            //グラマー作成
            var g = new Grammar(gb);

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

            //イベントの登録
            engine.SpeechRecognized += engine_SpeechRecognized;
            engine.SpeechRecognitionRejected += engine_SpeechRecognitionRejected;

            //オーディオストリームの変換をアクティブにする
            convertStream.SpeechActive = true;

            //認識エンジンに入力設定
            engine.SetInputToAudioStream(convertStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));

            //非同期で連続認識の開始
            engine.RecognizeAsync(RecognizeMode.Multiple);
           
        }

        void engine_SpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
        {
            tb1.Text = "認識できません。";
            tb2.Text = "";
        }

        void engine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            //認識信頼度の閾値
            //(認識信頼度 -1<0<1 -1が低信頼度 0が標準 1が高信頼度 数字が大きいほど認識率が厳しくなる)
            const double ConfidenceThreshold = 0.6;

            if (e.Result.Confidence >= ConfidenceThreshold)
            {
                //認識した単語を表示
                tb1.Text = e.Result.Text;
                tb2.Text = e.Result.Confidence.ToString();
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            //終了処理
            if (kinect != null)
            {
                kinect.Close();
                kinect = null;
            }
        }
    }
}



説明:
 大きく変わったのはマイクで録音した時のオーディオフォーマットが変更になっているところです。V1の時はPCM 16bitだったのがV2ではPCM 32bit floatになっています。音声認識エンジンへの入力フォーマットはPCM 16bitの必要があるので32bitfloat->16bitへの変換が必要になります。
 今回はSDKのサンプルプログラムから変換用クラスをそのままインポートして利用しています。
 また、音声ストリームの指定方法が少し変更になっていますね。AudioBeam配列から選択するように変わりました。
 音声認識部分についてはSpeechPlatformのバージョンは以前と変わっていないので特に変更はありません。


入力音声を配列で取得できるということは複数人の音声を識別できそうです。
現在はまだそこまで調べていないので何とも言えないのですが。できるならイントロクイズとかに使えるかもしれないですね。

0 件のコメント:

コメントを投稿