WPF教程之 语音识别-让WPF听

音频与视频:

语音识别-让WPF听

在前面的文章中我们提到我们可以使用 SpeechSynthesizer 类把文字变成语音. 这篇文章中我们反过来, 把语音变成文字, 使用 System.Speech 中的 SpeechRecognition 类. 默认的情况下你的解决方案不包括这个引用, 不过我们可以很简答的添加它. 不同版本的Visual Studio有点不同, 不过它大概长这样:

WPF教程之 语音识别-让WPF听WPF教程之 语音识别-让WPF听

添加完引用之后, 我们来做一个非常简单的语音识别:

<Window x:Class="WpfTutorialSamples.Audio_and_Video.SpeechRecognitionTextSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SpeechRecognitionTextSample" Height="200" Width="300">
    <DockPanel Margin="10">
        <TextBox Margin="0,10" Name="txtSpeech" AcceptsReturn="True" />
    </DockPanel>
</Window>
using System;
using System.Speech.Recognition;
using System.Windows;

namespace WpfTutorialSamples.Audio_and_Video
{
	public partial class SpeechRecognitionTextSample : Window
	{
		public SpeechRecognitionTextSample()
		{
			InitializeComponent();
			SpeechRecognizer speechRecognizer = new SpeechRecognizer();
		}
	}
}


WPF教程之 语音识别-让WPF听

就这样, 上面截图中的文字是 SpeechRecognizer 通过我的耳麦听写并插入到输入框中的.

SpeechRecognizer对象初始化的时候, Windows 启动语音识别程序, 处理剩下的事情, 把听写的结果输入到活动的程序中, 在我的电脑中, 语音识别程序长这样:

WPF教程之 语音识别-让WPF听


如果你从来没有使用过语音识别程序的话, Windows 会使用向导来帮助你开始使用和做些微小的调整

第一个例子允许你听写文字到你的应用程序中, 这很好, 但如果你要听到指令怎么办? Windows 和 WPF 会一起把你的按钮控件变成可以通过语音识别程序点到的指令, 你不用做什么, 就像这样:

<Window x:Class="WpfTutorialSamples.Audio_and_Video.SpeechRecognitionTextCommandsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SpeechRecognitionTextCommandsSample" Height="200" Width="300">
    <DockPanel Margin="10">
        <WrapPanel DockPanel.Dock="Top">
            <Button Name="btnNew" Click="btnNew_Click">New</Button>
            <Button Name="btnOpen" Click="btnOpen_Click">Open</Button>
            <Button Name="btnSave" Click="btnSave_Click">Save</Button>
        </WrapPanel>
        <TextBox Margin="0,10" Name="txtSpeech" AcceptsReturn="True" TextWrapping="Wrap" />
    </DockPanel>
</Window>
using System;
using System.Speech.Recognition;
using System.Windows;

namespace WpfTutorialSamples.Audio_and_Video
{
	public partial class SpeechRecognitionTextCommandsSample : Window
	{
		public SpeechRecognitionTextCommandsSample()
		{
			InitializeComponent();
			SpeechRecognizer recognizer = new SpeechRecognizer();
		}

		private void btnNew_Click(object sender, RoutedEventArgs e)
		{
			txtSpeech.Text = "";
		}

		private void btnOpen_Click(object sender, RoutedEventArgs e)
		{
			MessageBox.Show("Command invoked: Open");
		}

		private void btnSave_Click(object sender, RoutedEventArgs e)
		{
			MessageBox.Show("Command invoked: Save");
		}
	}
}

WPF教程之 语音识别-让WPF听

你可以试下在运行上面的例子的时候说出一些指令, 比如, “New” 或者 “Open”. 这会允许你听写文字到文本框中, 同时使用语音指令控制按钮, 这很酷吧?

特定的指令

在上面的例子中, Windows 会自动的进入听写模式并在文本框获得焦点额度同时, Window会尝试区分语音指令和听写文字, 然而, 某些时候, 这很困难,

上面的例子专注于听写和UI的互动, 下面我们来尝试关注特定的语音指令, 这也意味着我们将忽略听写, 就算文本框已经获得焦点.

我们将使用 SpeechRecognitionEngine 而不是 SpeechRecognizer. 这两个类最大的不同在于 SpeechRecognitionEngine 不会需要 Windows 语音识别程序运行也不需要语音识别向导, 它只关注于你在类中配置的特定语法.

在下一个例子中, 我们将会输入一些语音指定到 语音识别引擎. 我们希望它听到一个指令(属性) 和 一个值. 我们将用听到的属性和值来改变Label控件文字的颜色大小和粗细. 在我给出完整的例子前, 我想指出指令是怎么添加到语音识别引擎中的.

GrammarBuilder grammarBuilder = new GrammarBuilder();
Choices commandChoices = new Choices("weight", "color", "size");
grammarBuilder.Append(commandChoices);

Choices valueChoices = new Choices();
valueChoices.Add("normal", "bold");
valueChoices.Add("red", "green", "blue");
valueChoices.Add("small", "medium", "large");
grammarBuilder.Append(valueChoices);

speechRecognizer.LoadGrammar(new Grammar(grammarBuilder));

我们使用 GrammarBuilder来定义一些语法规则. 它有几个添加方法, 最简单的是Append(). 这个方法接受一个choices列表. 我们实例化 Choices 并加入语音指令的第一部分(命令/属性)的选项.

现在每次你使用 GrammerBuilder 的 Append 方法的时候, 你指示它听取一个单词. 对于这个例子而言, 我们希望听取两个单词, 一个用于 命令/属性, 另一个用于值(大小/颜色/粗细), 所以我们创建了两个Choices, Append 到了 GrammerBuilder 里面.

最后, 我们把整个语法 使用 LoadGrammer() 载入到了 GrammarBuilder 实例里.

以上就是指令怎么添加到语音识别引擎中的, 来看看完整的例子:

<Window x:Class="WpfTutorialSamples.Audio_and_Video.SpeechRecognitionCommandsSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SpeechRecognitionCommandsSample" Height="200" Width="325"
        Closing="Window_Closing">
    <DockPanel>
        <WrapPanel DockPanel.Dock="Bottom" HorizontalAlignment="Center" Margin="0,10">
            <ToggleButton Name="btnToggleListening" Click="btnToggleListening_Click">Listen</ToggleButton>
        </WrapPanel>
        <Label Name="lblDemo" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48">Hello, world!</Label>
    </DockPanel>
</Window>
using System;
using System.Globalization;
using System.Speech.Recognition;
using System.Windows;
using System.Windows.Media;

namespace WpfTutorialSamples.Audio_and_Video
{
	public partial class SpeechRecognitionCommandsSample : Window
	{
		private SpeechRecognitionEngine speechRecognizer = new SpeechRecognitionEngine();

		public SpeechRecognitionCommandsSample()
		{
			InitializeComponent();
			speechRecognizer.SpeechRecognized += speechRecognizer_SpeechRecognized;

			GrammarBuilder grammarBuilder = new GrammarBuilder();
			Choices commandChoices = new Choices("weight", "color", "size");
			grammarBuilder.Append(commandChoices);

			Choices valueChoices = new Choices();
			valueChoices.Add("normal", "bold");
			valueChoices.Add("red", "green", "blue");
			valueChoices.Add("small", "medium", "large");
			grammarBuilder.Append(valueChoices);

			speechRecognizer.LoadGrammar(new Grammar(grammarBuilder));
			speechRecognizer.SetInputToDefaultAudioDevice();
		}

		private void btnToggleListening_Click(object sender, RoutedEventArgs e)
		{
			if(btnToggleListening.IsChecked == true)
				speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
			else
				speechRecognizer.RecognizeAsyncStop();
		}

		private void speechRecognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
		{
			lblDemo.Content = e.Result.Text;
			if(e.Result.Words.Count == 2)
			{
				string command = e.Result.Words[0].Text.ToLower();
				string value = e.Result.Words[1].Text.ToLower();
				switch(command)
				{
					case "weight":
						FontWeightConverter weightConverter = new FontWeightConverter();
						lblDemo.FontWeight = (FontWeight)weightConverter.ConvertFromString(value);
						break;
					case "color":
						lblDemo.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString(value));
						break;
					case "size":
						switch(value)
						{
							case "small":
								lblDemo.FontSize = 12;
								break;
							case "medium":
								lblDemo.FontSize = 24;
								break;
							case "large":
								lblDemo.FontSize = 48;
								break;
						}
						break;
				}
			}
		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			speechRecognizer.Dispose();
		}
	}
}

WPF教程之 语音识别-让WPF听

截图中就是例子运行后我说了 “weight bold” 和 “color blue” 的结果, 很酷吧?

这个例子语法相关的已经解释了, 这个程序的界面也非常简单, 让我们来看下剩下的代码吧.

我们使用 ToggleButton 来启用或禁用识别, 对应的方法是 RecognizeAsync() 和 RecognizeAsyncStop(). RecognizeAsync() 使用一个参数来告诉识别引擎这是一个单一指令识别或多指令识别. 比如, 我们想要程序接受多个指令, 这个参数就是 Multiple. 按下这个按钮就会启动识别, 按钮按下的时候就是识别已启用, 按钮松开的时候就是识别已禁用, 按钮视觉上指示引擎的状态.

在语法建立完后最有意思的地方在于我们怎么解释指令, 我们在SpeechRecognitionCommandsSample() 中订阅了 SpeechRecognized 事件. 我们使用完全识别的文本来更新label控件的内容, 然后我们使用 e.Result.Words 来处理指令具体的要求.

首先我们检查确实有两个单词, 如果确实有两个, 那么我们根据情况分别处理.

对于粗细和颜色, 我们可以使用对应的FontWeightConverter/ColorConverter转换指令的String值到label控件可以处理的形式, 然而对于大小, 我们手动处理因为我们选择的单词不是可以自动转换的形式. 请注意你应该处理异常, 应为如果识别结果为 “weight blue” 的话你将试图为label控件的粗细设定为蓝色, 这当然会引发异常.

小结

正如你所看到的, WPF中的语音识别是简单而强大的, 你可以同过听写和(或)识别语音指令的方式来为你的应用程序提供额外的输入方式.

作者:admin,如若转载,请注明出处:https://www.web176.com/wpf/15955.html

(0)
打赏 支付宝 支付宝 微信 微信
adminadmin
上一篇 2023年4月19日
下一篇 2023年4月19日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注