【发布时间】:2013-03-07 21:30:39
【问题描述】:
我正在编写一个应用程序,它可以接受多种不同的外部输入(键盘按下、动作手势、语音)并产生类似的输出(例如,在键盘上按“T”将与说出单词“旅行”大声说出来)。因此,我不希望任何输入管理器相互了解。具体来说,我不希望 Kinect 管理器(尽可能多地)了解语音管理器,反之亦然,即使我使用的是 Kinect 的内置麦克风(语音管理器应该与任何麦克风一起使用)。我在语音管理器中使用 System.Speech,而不是 Microsoft.Speech。
我遇到了一个问题,即一旦启用 Kinect 动作识别模块,语音模块就会停止接收输入。我已经尝试了很多东西,比如inverting the skeleton stream and audio stream,以不同的方式捕获音频流等等。我终于缩小了问题的范围:关于我如何初始化我的模块的一些事情与我的应用程序处理的方式不符事件。
在动作捕捉开始之前,该应用程序运行良好。如果我完全排除 Kinect 模块,这就是我的主要方法的外观:
// Main.cs
public static void Main()
{
// Create input managers
KeyboardMouseManager keymanager = new KeyboardMouseManager();
SpeechManager speechmanager = new SpeechManager();
// Start listening for keyboard input
keymanager.start();
// Start listening for speech input
speechmanager.start()
try
{
Application.Run();
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
}
我正在使用Application.Run(),因为我的 GUI 由外部程序处理。此 C# 应用程序的唯一工作是接收输入事件并根据该输入运行外部脚本。
键盘和语音模块都偶尔接收事件。另一方面,Kinect 会不断产生事件。如果我的手势很少发生,那么轮询循环可能是每次轮询之间等待时间的答案。但是,我正在使用 Kinect 来控制鼠标移动……我不能在骨架事件捕获之间等待,因为那样鼠标会很迟钝;我的骨架捕获循环需要尽可能保持不变。这提出了一个大问题,因为现在我不能让我的 Kinect 管理器在同一个线程上(或消息泵?我对差异有点模糊,因此我认为问题出在此处):根据我的理解它,在同一个线程上不允许键盘或语音事件始终如一地通过。相反,我想出了一个解决方案,让我的 Kinect 管理器从System.Windows.Forms 继承,以便它可以与Application.Run() 一起使用。
现在,我的主要方法如下所示:
// Main.cs
public static void Main()
{
// Create input managers
KeyboardMouseManager keymanager = new KeyboardMouseManager();
KinectManager kinectManager = new KinectManager();
SpeechManager speechmanager = new SpeechManager();
// Start listening for keyboard input
keymanager.start();
// Attempt to launch the kinect sensor
bool kinectLoaded = kinectManager.start();
// Use the default microphone (if applicable) if kinect isn't hooked up
// Use the kinect microphone array if the kinect is working
if (kinectLoaded)
{
speechmanager.start(kinectManager);
}
else
{
speechmanager.start();
}
try
{
// THIS IS THE PLACE I THINK I'M DOING SOMETHING WRONG
Application.Run(kinectManager);
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
由于某种原因,一旦 Kinect 传感器启动,Kinect 麦克风就会失去其“默认值”(如果此观察结果不正确,或者有解决方法,请告诉我)。因此,我需要在语音管理器中创建一个特殊的 start() 方法,如下所示:
// SpeechManager.cs
/** For use with the Kinect Microphone **/
public void start(KinectManager kinect)
{
// Get the speech recognizer information
RecognizerInfo recogInfo = SpeechRecognitionEngine.InstalledRecognizers().FirstOrDefault();
if (null == recogInfo)
{
Console.WriteLine("Error: No recognizer information found on Kinect");
return;
}
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(recogInfo.Id);
// Loads all of the grammars into the recognizer engine
loadSpeechBindings(recognizer);
// Set speech event handler
recognizer.SpeechRecognized += speechRecognized;
using (var s = kinect.getAudioSource().Start() )
{
// Set the input to the Kinect audio stream
recognizer.SetInputToAudioStream(s, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
// Recognize asycronous speech events
recognizer.RecognizeAsync(RecognizeMode.Multiple);
}
}
作为参考,Kinect 管理器中的start() 方法如下所示:
// KinectManager.cs
public bool start()
{
// Code from Microsoft Sample
kinect = (from sensorToCheck in KinectSensor.KinectSensors where sensorToCheck.Status == KinectStatus.Connected select sensorToCheck).FirstOrDefault();
// Fail elegantly if no kinect is detected
if (kinect == null)
{
connected = false;
Console.WriteLine("Couldn't find a Kinect");
return false;
}
// Start listening
kinect.Start();
// Enable listening for all skeletons
kinect.SkeletonStream.Enable();
// Obtain the KinectAudioSource to do audio capture
source = kinect.AudioSource;
source.EchoCancellationMode = EchoCancellationMode.None; // No AEC for this sample
source.AutomaticGainControlEnabled = false; // Important to turn this off for speech recognition
kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(allFramesReady);
connected = true;
return true;
}
所以当我禁用动作捕捉时(通过让我的 main() 看起来类似于第一个代码段),语音识别工作正常。当我启用动作捕捉时,动作效果很好,但没有语音被识别。在这两种情况下,键盘事件总是有效的。没有错误,通过跟踪我发现语音管理器中的所有数据都已正确初始化......它似乎就像语音识别事件消失了一样。如何重新组织此代码以便输入模块可以独立工作?我是否使用线程,或者只是 Application.Run() 以不同的方式?
【问题讨论】:
-
您使用的是哪个 SDK 和哪个 Kinect:XBox 还是 Windows?另外,您使用的是哪个版本的 Speech API?
-
我使用的是 SDK 版本 1,我在 Windows 上使用的是 kinect。我正在使用 System.Speech 版本 4
标签: c# multithreading event-handling kinect-sdk