2011年12月26日月曜日

KINECT SDK 日本語で音声認識(VB+WPF)

KINECT SDKの音声認識サンプルプログラムはコンソールアプリでしたが、WPFでも動くようにしてみました。WPFの場合はUI部分と音声認識部分は別スレッドにする必要があります。

まずはXAMLソースです。

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

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="241" Width="668">
    <Grid Name="Grid1" Height="151">
     
        <TextBox Height="54" HorizontalAlignment="Left" Margin="0,12,0,0" Name="TextBox1" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.RowSpan="2" />
        <TextBox Height="54" HorizontalAlignment="Left" Margin="0,72,0,0" Name="TextBox2" VerticalAlignment="Top" Width="634" FontSize="20" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="2" />
    </Grid>
</Window>
--------------------------------------------------------------------------------- 

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

メインソースです。
--------------------------------------------------------------------------------- 

Imports Microsoft.Research.Kinect.Audio
Imports Microsoft.Research.Kinect.Nui
Imports Microsoft.Speech.AudioFormat
Imports Microsoft.Speech.Recognition
Imports System.Media
Imports System.IO
Imports System.Threading
Imports System.Windows.Threading

Class MainWindow
    Inherits Window

    Private nui As Runtime
    Private cam As Camera
    Private readerThread As Thread

    Const ri_ID As String = "SR_MS_ja-JP_TELE_10.0"

    Public Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        If Runtime.Kinects.Count > 0 Then
            ''KINECT初期化
            nui = Runtime.Kinects(0)
            nui.Initialize(RuntimeOptions.UseColor)
            cam = nui.NuiCamera

            camInit()
        Else
            MsgBox("KINECTが見つかりません。")
            Exit Sub
        End If

    End Sub

    Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

        ''音声認識スレッド
        readerThread = New Thread(New ThreadStart(AddressOf SpeechThread))

        ''スレッドスタート
        readerThread.Start()

    End Sub

    Private Sub SpeechThread()


        ''音声認識準備
        Dim source = New KinectAudioSource()

        With source
            .FeatureMode = True
            .AutomaticGainControl = False
            .SystemMode = SystemMode.OptibeamArrayOnly
        End With

        ''認識エンジン選択
        Dim ri As RecognizerInfo = GetKinectRecognizer()

        If IsNothing(ri) = True Then
            MsgBox("認識エンジンが見つかりませんでした。")
            Exit Sub
        End If

        Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
                                  Sub()
                                      TextBox1.Text = ri.Name
                                  End Sub))


        Dim sre As New SpeechRecognitionEngine(ri.Id)
        Dim w As New Choices

        With w
            .Add("うえ")
            .Add("した")
            .Add("最初")
            .Add("終わり")
        End With

        Dim gb As New GrammarBuilder

        gb.Culture = ri.Culture
        gb.Append(w)

        Dim g As New Grammar(gb)

        sre.LoadGrammar(g)

        AddHandler sre.SpeechRecognized, AddressOf SreSpeechRecognized
        AddHandler sre.SpeechRecognitionRejected, AddressOf SreSpeechRecognitionRejected


        Dim s As Stream = source.Start
        sre.SetInputToAudioStream(s,
                                  New SpeechAudioFormatInfo(EncodingFormat.Pcm,
                                                            16000,
                                                            16,
                                                            1,
                                                            32000,
                                                            2,
                                                            Nothing))



        sre.RecognizeAsync(RecognizeMode.Multiple)

    End Sub

    Private Sub camInit()
        ''カメラ初期位置
        cam.ElevationAngle = 0
    End Sub

    Private Sub camUp()
        ''カメラ上向き
        Dim nowangle = cam.ElevationAngle + 5
        If nowangle > 25 Then
            cam.ElevationAngle = 25
        Else
            cam.ElevationAngle = nowangle
        End If
    End Sub

    Private Sub camDown()
        ''カメラ下向き
        Dim nowangle = cam.ElevationAngle - 5
        If nowangle < -25 Then
            cam.ElevationAngle = -25
        Else
            cam.ElevationAngle = nowangle
        End If
    End Sub

    Private Function GetKinectRecognizer()
        Return SpeechRecognitionEngine.InstalledRecognizers().Where(Function(r) r.Id = ri_ID).FirstOrDefault
    End Function

    Private Sub SreSpeechRecognized(ByVal sender As Object, ByVal e As SpeechRecognizedEventArgs)
        Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
                                  Sub()
                                      TextBox2.Text = "認識しました:" & e.Result.Text
                                  End Sub))


        Select Case e.Result.Text
            Case "うえ"
                camUp()
            Case "した"
                camDown()
            Case "最初"
                camInit()
                ''Case "終わり"

        End Select
    End Sub

    Private Sub SreSpeechRecognitionRejected(ByVal sender As Object, ByVal e As SpeechRecognitionRejectedEventArgs)
        Me.Dispatcher.BeginInvoke(DispatcherPriority.Background, New Action(
                                  Sub()
                                      TextBox2.Text = "認識できません。"
                                  End Sub))

    End Sub

    Private Sub Window_Unloaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Unloaded

        ''KINECT終了
        nui.Uninitialize()

        ''スレッド終了
        readerThread.Abort()

        readerThread.Join()

    End Sub
End Class
--------------------------------------------------------------------------------- 
UIスレッドでは音声スレッドのスタートのみ行っています。
コンソール版での音声認識部分を音声認識スレッドとしています。

0 件のコメント:

コメントを投稿