模拟机械运动及其语音控制的研究
摘 要:在云计算、智能移动设备和物联网、互联网快速发展的今天,便利成为人们消费的最大动力,而计算机交互界面的革新是首当其冲的,作为交互技术,语音识别,无疑不会褪去其重要的角色作用。本论文介绍以VC6.0和Microsoft Speech SDK5.1为开发工具,开发语音交互界面应用程序,实现语音控制模拟机械臂完成简单动作和关闭程序的完整过程。其中,将重点探讨库的加载、直线旋转算法、语法库的提取、语法命令的准确匹配等等问题。最后,指出本系统的不足及一些改进方案,并对计算机语音交互进行一番总结和展望。
关键词:计算机交互 语音控制 旋转算法 准确匹配 展望
中国图书分类号:TP391.42
Motion of Simulation Mechanical and Voice Control Research
Abstract:In cloud computing, smart mobile devices and things, the rapid development of the Internet today, convenience become the biggest power consumer, and computer interface innovation is first and foremost, as an interactive technology, voice recognition, and certainly not faded its important role ineffect. This paper introduces the complete procedure of developing voice interface applications,controlling simulated robot arm to complete simple movements via voice commands,based on VC6.0 and Microsoft Speech SDK5.1 as the tool. It will also explore the library's loading,linear rotation algorithm, grammar library extraction, matching the exact command syntax and so on. Finally, less than that and some of the system improvement program, and computer speech for some summary and prospect interaction.
Key words:Computer interaction;Voice control;Rotation algorithm;Matching ex -actly;Outlook
目 录
1引言.......................................................... 1
1.1研究背景................................................. 1
1.2研究意义................................................. 2
1.3研究内容................................................. 2
1.4本论文组织结构........................................... 3
2 SDK及VC环境配置............................................. 4
2.1语音开发工具............................................. 4
2.2 工具使用及VC环境配置................................... 5
3 语音控制程序开发流程.......................................... 6
3.1需求分析................................................. 6
3.2 代码设计与测试.......................................... 9
3.3 重要算法实现........................................... 13
4 不足及其改进................................................. 19
5 总结与展望................................................... 19
5.1 总结................................................... 19
5.2 展望................................................... 20
致谢........................................................... 20
参考文献....................................................... 22
模拟机械运动及其语音控制的研究
1引言
随着计算机与多媒体技术的发展,在众彩纷呈的人与计算机的交互方式中,实现人与计算机通过自然语音交互,一直是人类追求的目标。这就要求开发具有语音功能的程序。而语音识别,即实现使计算机获取用户语音输入并理解识别,从而使用户使用语音和口令控制计算机工作,是具有语音功能的程序的充满魅力的一面,也是众多研究者、高校和实验室的研究热点之一,具有很高的学术价值和应用前景。
本章将介绍本论文的研究背景、研究意义、研究内容和本论文组织结构。
1.1研究背景
在计算机与多媒体技术、互联网、物联网和人们生活节奏快速发展的今天,人们的生活越来越离不开计算机与网络,而传统的人机交互方式,即通过鼠标、键盘或更原始的机械开关来操作计算机的方式,也已很不适应人们的生活节奏,并深深地影响了用户的使用体验快感。在各种需求和客观条件需求下,计算机语音技术的研究早在二十世纪五十年代就已开始,并一直处于研究和应用热点。
作为语音技术的一个重要方面,语音识别的研究工作开始于上世纪50年代的Bell实验室,到60年代末70年代初,其作为一个重要课题取得了实质进展,提出了动态规划(DP)和线性预测分析技术(LP),其中后者较好解决了语音信号产生模型的问题,极大地促进了语音识别的发展,70年代,动态时间规正技术(DTM)解决了语音特征不等长匹配问题,对特定人孤立词语音识别十分有效,在语音识别领域取得了突破,在些期间还提出了矢量量化(VQ)和隐含马尔可夫模型(HMM)理论。80年代语音识别研究工作进一步深入,HMM模型和人工神经(ANN)在语音识别中成功应用。HMM的引入和成功应用,奠定了统计方法和模型在语音识别和语音处理中的主流地位,并且,使得借助人工智能中的启发式搜索和语音模型自身的特点,高效、快捷的算法使得建立实时的连续语音搜索识别系统成为可能。90年代,语音识别的研究进一步深入,逐步发展到自然口语识别 和理解的人机对话系统。ANN也开始应用于语音识别,并在不断的研究完善的和顺应解决问题的需要中逐步与HMM模型和小波分析模型等结合。
目前,语音识别领域的研究热点包括:稳健语音识别、语音输入设备研究、声学HMM模型的细化、说话人自适应技术、大词汇量关键词识别、有效识别(搜索)算法研究、可信度评测算法研究、ANN应用、语音模型及深次的自然语音理解 。
1.2研究意义
在我们的生活中,语音识别早已成为人们消费的一部分,成为IT发展中的一大亮点,而且,在云计算与移动互联等快速发展及其促进下,语音识别技术将是人工智能不可或缺的功能模块,语音识别将是人机交互的主要界面。但是,由于语音识别技术的最终目的是要实现人与机器进行自然语言交流,那么在朝这个目标迈进的过程中,我们要解决的问题还有许多,有许多难点,例如,如何减小语音识别对环境的依赖性、如何提高语音识别在高噪声环境下的鲁棒性、如何更高效地把语言学、生理学、心理学等方面知识量化、建模从而应用于语音识别,更重要和根本的是,如何克服人类自身听觉积累、知识积累和学习机制以及大脑神经系统控制机理等知识方面的缺陷的阻碍,这些问题都是需要花很大的精力和时间去克服的。可见,对语音识别的研究仍然具有很重要的意义。
1.3研究内容
人机交互是研究如何把计算机技术和人联系起来,使计算机技术最大程度的人性化,而计算机语音交互界面的研究,是人机交互的重要组成部分,也主要涉及到语音识别、合成,是当前计算机行业竞争的焦点,它的好坏直接影响到计算机的可用性和效率,影响到人们日常生活和工作的质量和效率 。
本论文将围绕语音识别技术,利用VC 6.0和Microsoft Speech SDK5.1和Speech SDK51LangPack.exe开发工具和包开发开发一个简单孤立词语音控制应用程序,实现控制一个模拟机械臂做相应动作的功能。对语音识别感兴趣的人员可以在本程序基础上扩展,或借鉴本程序,实现更复杂的功能。
在设计本语音控制模拟机构运动的应用程序过程中,主要涉及到以下论题:
1.MFC绘图和直线旋转算法:主要是关于按钮消息映射与响应、视图中绘图设备的定义和刷新来实现直线旋转算法的内容。
2.语音控制的实现:主要是开发语音识别命令控制应用程序的步骤与注意事项,并探讨分析语法库的提取、语音判断分支的方法选择及控制响应。
3.简述应用帮助说明功能块的解决。
1.4本论文组织结构
第一章,介绍本论文的研究背景、研究意义、研究内容及组织结构;
第二章,介绍利用语音识别技术开发语音控制应用程序的开发包和工具的安装与环境配置;
第三章,以软件工程和面向对象编程开发知识为基础,介绍本软件的开发流程,其中着重讨论MFC绘图和直线旋转的实现过程,以及开发语音控制程序中各个步骤和分支判断、控制调用中的问题,并简述应用帮助说明功能块的解决。
第四章,指出程序的不足及改进方案。
如图1-1为本论文组织结构图。
图1-1本论文组织结构图
2 SDK及VC环境配置
2.1语音开发工具
语音识别控制程序一般是基于语音开发工具包来开发的,具前的语音开发工具包有很多,比较常用的开发工具包有微软的Microsoft Speech SDK及IBM的ViaVoice,而前者显然是基于Windows操作系统系列的语音开发工具的最佳选择。其含有语音应用程序接口(SAPI)、微软连续语音识别引擎(MCSR)以及串联语音合成(又称文本到语音)引擎(TTS)等。SAPI还包括对于低层控制和高度适应性的直接语音管理、训练向导、事件、语法、编译、资源、语音识别管理以及文本到语音管理 (这些在语音识别控制应用程序中都会涉及),其结构如图2-1所示。
图2-1 语音识别SAPI层次图
从用户角度从上抽象层往底层看,应用程序(Application)通过应用程序接口(API)和SAPI(SpeechAPI)交互,而SAPI则通过设备驱动接口(DDI)与语音识别引擎或语音合成引擎交互,这样,用户可以很轻松只关注于API的使用即可开发出语音识别或语音合成应用程序。
那么,对于编程语言,这里本人选择VC++作为开发语言,基于MFC,以Visual C++ 6.0作为开发平台。首先,Microsoft Speech SDK要求Visual C++ 6.0及以上作为开发平台;其次,以VC++作为开发语言,较基本地接触到底层知识但又不太复杂,可以更本质地理解语音识别程序等应用程序的运行机制,且可以更清晰地理解程序的框架、脉络,同时对于Windows消息驱动机制认识也更深刻。
2.2 工具使用及VC环境配置
1、下载Speech SDK.exe(里面有例子程序、说明文档和以及用于开发的美国英语语音引擎),运行后,安装Microsoft Speech SDK5.1.msi,选择正确的安装路径,以后在VC6.0中打开工程,选择“工程”(Project)->“设置”(Settings)->“C\C++”选项卡中选“策略”(Category)选中“预处理”(Preprocessor),再在其“额处包括目录”(Additional include director -ies)中输入上面的路径(这里建议将上述运行了Microsoft Speech SDK5.1.msi后生成的新的文件夹,如Include文件夹、Lib文件夹直接拷贝到你的工程文件夹中,这样,这里可以用相对路径,即:..\工程文件夹名\Include来加库,当拷贝整个工程文件夹到不同的机器或不同的硬盘时,不必每次修改库路径),并在“预处理定义”(Preprocessor definitions)中加上“_WIN32_DCOM”(因为我们这里用的是低级的COM接口来开发);同样,我们还要在“链接”(Link)选项卡中“策略”(Category)中选中“输入”(Input),再在“附加库路径”(Additional library)输入上面得到的Microsoft Speech SDK5.1文件夹下i386的路径(同样建议用上面的相对路径,即:..\工程文件夹名\Lib\i386),同时在“Object\library modules”中输入“sapi.lib”即可;
2、注意,如果你的语法库文件*.xml中用的简体中文语言选项,即里面有LANGID="804"(LANGID="809"是英式英语语言编号,美式英语编号为LANGID="409"),那么为支持对其的语音识别,你还需要安装Speech SDK51 LangPack.exe,安装后,找到新生成的LangPack文件,点击Microsoft Spee -ch SDK 5.1 Language Pack,运行后,再在计算机电脑上的“控制面板”中打开“语音”,选择“语音识别”选项卡中的语言(L)中的Microsoft Simp -lified Chinese Recognizer,点击“应用”和“确定”以后,就可以正常开发识别中文的语音应用程序,否则,你的程序在LoadCmdFromFile()处会出错;
3 语音控制程序开发流程
3.1需求分析
3.1.1系统分析
计算机语音交互界面设计不同于一般的软件界面设计,它需要遵循一些特殊原则,以便设计出更好的界面。一般原则如下 :
(1)用户控制:用户控制就是指让用户感受到计算机在他控制之下或允许他进行恰当的控制,这样才会使用户感到舒服;否则,会影响到用户的情绪,甚至会导致用户停止使用这种界面软件。
(2)界面的可预测性:用户界面的工作方式应该能被用户正确地预测,即用户应该知道计算机下一步应该作什么。这里就需要对用户的心理模型进行挖掘和模拟。
(3)降低记忆数量:人的暂时记忆能够在大约20秒的时间里记住5~9件事情,如果想记住更多的事,就要将信息以某种方式分块以减少记忆量,或者将信息、以语义编码或给出一定的意义。
(4)语言清晰性:控制计算机的各种语音命令之间要尽量差别分明,以便减少语音识别错误。用户在说出语音命令也要吐字清晰,以便语音识别引擎更好的识别。
(5)差错控制:语音界面与其他的界面相比有着更高的错误率,这是由其自身的特点和其处理技术的局限性决定的。这就需要我们提供差错控制机制。
(6)适应性和灵活性:适应性是指界面的设计必须要适合用户群的工作方式;而灵活性是指允许用户对界面进行调整以适应特定用途。
(7)满意度:界面的满意度是一项重要指标。当系统以高效、实用的方式工作,并且只需要很少的工作和打扰,那么用户就会感到满意。
(8)反馈及响应:界面应该及时告知用户他们所作操作的执行结果和界面所处的状态。因为反馈对于用户很重要,尤其是在用户希望和计算机进行“交谈”时。在语音界面中的一个普遍的问题是用户不知道什么时候系统准备好听他们讲,也就是说什么时候轮到他们讲话。这样当用户在系统不接收语音输入时说话就会产生错误。这可以通过为用户提供关于系统状态的反馈来解决,像“系统等待您的指示”之类的信息,而这就是一种很好的响应。
本论文是围绕语音交互界面应用程序的,该应用程序是基于语音识别技术和MFC应用程序开发技术,利用VC 6.0和Microsoft Speech SDK5.1和Speech SDK51LangPack.exe开发工具和包,开发一个简单孤立词语音控制应用程序,实现控制一个模拟机械臂做相应动作的功能。对语音识别感兴趣的人员可以在本程序基础上扩展,或借鉴本程序,实现更复杂的功能。
功能需求:
实现应用程序界面下,利用主窗口菜单栏上按钮或语音都能控制模拟机械臂竖立、倒下和左右旋转等简单动作,从而可以在此基础上进行扩展,完成更复杂的动作。
性能需求:
不管使用语音还是按钮控制,都要各自实现的功能要不产生干扰,且状态明确,尤其是语音控制,要达到只有是预建立的语法库里面的命令才能响应,其它杂音都不能使应用程序产生反应的性能。
软硬件需求:
软件方面,Windows 98/XP及以上版本操作系统,以及上述工具包;
硬件方面,需要主机耳迈、麦克风插孔要好,并且要求有好的耳迈和麦克风,保证语音输入能够清晰的捕获到。
3.1.2系统设计
要实现控制模拟机械臂完成关于旋转等简单动作,这里,在应用程序中,以直线作为模拟机械臂,完成所述竖立、倒下、左右旋转等动作,即是选取一个参考点作为圆心,利用计算机图形学的知识,完成相应图形的旋转。
那么,要看到机械臂(直线)及其相应旋转,可以在MFC所提供的三种应用程序结构中选择SDI结构,因为,这里要看到机械臂及其相应动作,正好文档视图区域可作为其“画布”背景;而作为按钮控制时,恰可充分利用主框架菜单栏,在其上添加相应按钮并设置视图类来响应按钮消息,从而实现按钮响应;对于语音控制,在上述完成SDK及VC环境配置后,要在相应头文件中添加相应头文件包括预处理命令并在相应处完成COM的初始化、语音消息的定义及消息映射机制,详见代码设计步骤。
考虑到上述语音交互界面设计原则上以及用户的情况,还需要在软件中添加使用说明文档,在本程序中巧妙而简单的解决了,具体详见代码设计阶段。
在本应用程序实现过程中,我将系统实现大致分为两步:
1、首先实现菜单命令按钮控制机械臂完成相应动作;
2、完成语音控制机械臂完成同样的功能;
系统流程如图3-1
图3-1 语音控制应用程序系统流程图
3.2 代码设计与测试
1、菜单命令按钮控制机械臂完成相应动作
在完成上述SDK的安装和上述操作后,运行Microsoft Visual C++ 6.0,按照MFC AppWizard 完成相应步骤并进入工程,按照第二章所说明的步骤完成VC环境的配置。
要使进入应用程序之后,初始界面(主要是视图类所显示的区域)应显示的是模拟机械臂的初始状态(这里假设是机械臂横放在水平面),并且,很显然,当我们有可能在某一时刻切换到另一窗口,而当我们返回时,要仍能显示我们切出该应用程序窗口之前应用程序的状态,因此,我们的绘图模块应放在系统重绘刷新之后仍被调用的函数,而视图类的OnPaint()函数正是符合上述要求的方法模块,而由MFC运行机制,视图类的OnPaint()函数实际调用OnDraw()函数,所以,实际上,我们的绘图模块应放在OnDraw()模块中。
同时,由于我们整个程序几乎是操作机械臂(直线),因此,我们应将直线的坐标及部分相应属性应作为视图类的成员,这样可以避免大量代码重复,同时方便各个函数模块对机械臂的操作。
具体步骤如下:
1) 定义直线坐标为视图类的属性:
CPoint m_LinePoint1,m_LinePoint2;//直线坐标的起点、终点
2) 为画相应机械臂,需要相应画笔设备环境,同时,可以建立一个水平线作为假设的地面,地面可采用系统默认画笔画出,由于机械臂和地面在应用程序运行始终一直出现,同样,应将其作为视图类的成员:
CPen m_Pen1;//定义画机械臂的画笔
并在视图类的构造函数中,初始化机械臂的画笔为:
m_Pen1.CreatePen(PS_SOLID,2,RGB(0,0,0));
3) 在视图OnDraw()函数中创建客户区设备描述上下文,并调用设备描述上下文画相应的机械臂和地面,从而显示应用程序初始界面;
4) 在WorkSpace中进入资源类视图ResourceView,选择Menu选项,并进入主框架界面,在菜单栏添加菜单(设以"控制命令"作为其标题属性Caption),在其上加入相应命令,比如以“竖立”作为其Caption属性,而其ID设为“ID_COM_StandUp”;
5) 按快捷键“Ctrl+W”或选择VC工程菜单栏上的“视图”(View)->“类向导”(ClassWizard),进入类向导,从“对象标识”(Object ID)选中刚才加入的命令的标识“ID_COM_StandUp”,然后从“类名”(Class Name)选中工程中的视图类名(这步以后,就确定命令按钮的消息由视图类来响应),从“消息”(Messages)中选中COMMAND,此时单击“增加函数”(Add Functions…),“确定”之后,再单击“编辑函数”(Edit code),“确定”之后即进入新创建的函数,在里面添加代码使机械臂完成相应动作。
6) 根据需要,相应重复上述步骤,可添加其它命令功能。
2、语音控制机械臂完成同样的动作功能
语音控制应用程序的开发流程比较固定,即:
1) 首先,要加入库,即上面第二章的步骤;
2) 要初始化COM接口,这个过程是:
首先要在StdAfx.h头文件中#endif之前加入:
#include<atlbase.h>
extern CComModule_Module;
#include<atlcom.h>
接着要初始化COM接口,只能是在CWinApp子类中,加入
::CoInitiallizeEx(NULL,COINIT_APARTMENTTHREADED);
3) 创建语音识别引擎;
在视图类中建立定义COM的引擎对象:
CComPtr<ISpRecognizer> m_Recognizer;
并在视图类的适当位置实例化引擎对象,在这里有点小技巧,即:应使引擎对象在应用程序显示主窗口之后、进行任何操作之前,经查,符合此要求的函数有一个CView类的OnInitialUpdate()函数,那么我们要在程序视图类中重载该函数,视图类的头文件中的Overrides下,添加:virtual void OnInitialUpdate(),并在视图类的CPP文件中添加该函数,并在该函数中添加:
HRESULT hr=S_OK;
hr=m_Recognizer.CoCreateInstance(CLSID_SpSharedRecognizer);
//Shared
一个应用程序必须从两个不同类型的语音识别引擎(ISpRecognizer)中选择一种。一种是可以与其它语音识别程序共享识别器的语音识别引擎,这在大多数识别程序中被推荐使用。为了为IspRecognizer建立一个共享的ISpRecoContext接口,一个应用程序只需要用CLSID_SpSharedRecoContext调用COM的 CoCreateInstance方法。这种方案中,SAPI将建立一个音频输入流,把它设置为SAPI默认的音频输入流。对于大型服务器程序,它可能在单独在一个系统上运行,性能是关键,一个InProc语音识别引擎更适合,而且,独立语音识别引擎InProc更适合特定人语音识别,为了为InProc ISpRecognizer建立一个IspRecoContext,程序必须首先用CLSID_SpInprocRecoInstance调用CoCreateInstance来建立属于它自己的InProc IspRecognizer。然后程序必须调用ISpRecogniz
-er::SetInput()来建立一个音频输入流 ;
4) 创建语音识别上下文(这是核心,且也是放在OnInitialUpdate函数中);
hr=m_Recognizer->CreateRecoContext(&m_RecoContext);
5) 设定语法识别通知消息(用预处理命令,可以放在Resource.h中,如:#define WM_RECOEVENT WM_USER+102)及相应识别处理方法(函数),SetNotifyWindowMessage(m_hWnd,WM_RECOEVETN,0,0),并注意在后面应用程序中要建立消息映射:ON_MESSAGE(WM_RECOEVENT,OnRecoEvent)和定义消息(在头文件中):afx_msg void OnRecoEvent(),并实现消息处理函数OnRecoEvent();
6) 设置我们感兴趣的事件,具体可参阅Speech SDK help.chm文档中查看SPEVENTENUM(这里我只设对识别的感兴趣);
CONST ULONGLONG ullinterest=SPFEI(SPEI_RECOGNITION);
hr=m_RecoContext->SetInterest(ullinterest,ullinterest);
7) 创建语法对象,语法规则也有两种类型,一种是听写型(Dictation)
,允许使用引擎中的大量短语,但识别效率低;另一种是命令和控制型(Comm -and and Control),能最大限度地识别自定义的短语,故识别效率高 。程序中,我使用的是命令和控制型:首先,设置语法对象的ID(用预处理命令#define *);其次,加载语法规则(LoadCmdFrom());
//创建命令式语法 1、创建语法对象 2、加载语法规则
hr=m_RecoContext->CreateGrammar(GIDCMDCTRL,&m_RecoGrammar);
//加载语法
WCHAR wszXMLFile[20]=L"";
MultiByteToWideChar(CP_ACP,0,(LPCSTR)"CmdStrl.xml",-1,wszXMLFile,256);//ANSI转换为UNICODE
if(SUCCEEDED(hr))
{
hr=m_RecoGrammar->LoadCmdFromFile(wszXMLFile,SPLO_DYNAMIC);
if(FAILED(hr))
MessageBox("LoadFile Error!");
}
注意,如果是开发听写式语音应用程序,则为:
hr = m_cpDictationGrammar->LoadDictation(NULL, SPLO_STATIC);//加载词典
8) 而在命令和控制型中,语法规则用xml格式,参见Speech SDK 5.1 中的 Designing Grammar Rules,那么程序中我的语法文件为CmdStrl.xml:
<?xml version="1.0" encoding="gb2312"?>
-<GRAMMAR LANGID="804">
-<DEFINE>
<IDNAME="CMD" VAL="10" />
</DEFINE>
-<RULE NAME="COMMAND" ID="CMD" TOPLEVEL="ACTIVE">
-<L>
<p>竖立</p>
<p>右旋转</p>
<p>倒下</p>
<p>左旋转</p>
</L>
</RULE>
</GRAMMAR>
9) 在开始识别时,激活语法对象;
hr=m_RecoGrammar->SetRuleState(NULL,NULL,SPRS_ACTIVE);//C&C
10) 获取识别消息并进行处理,放在OnRecoEvent()中;
11) 在语法识别消息处理之后,另一个函数中,或在整个应用程序退出前释放掉语音识别语法对象、上下文、引擎等,只需调用相应对象的Re -lease()方法即可。
注意,千万不要在识别消息处理方法的最后,即退出该方法之前释放掉相应接口,否则会出现bug,即在你每一次运行程序时,它只能识别一个语音消息,再在第二次运行该应用程序时有可能出现响应上一次运行时最后输入的语音消息响应。
3.3 重要算法实现
1、直线旋转
(一)“竖立”和“倒下”功能的实现
a. 直线旋转算法有多种,当我们选用勾股定理时,我们只须知道直线的长度和直接线的坐标即可,而直线长度易得到,因为预设“竖立”和“倒下”前初态机械臂在地面上,因此,直线的长度为初态时终点横坐标减去其起点横坐标,而且显然,直线在旋转中应长度不变,因此,我们最好将其长度也作为视图类的成员,理由同上述将直线的坐标作为视图类成员一样。
那么我们每次旋转直线时,其实只是定好参考点作为圆心,那么这里显然是以起点作为圆心,只须每次重画时,将原来的线刷新掉,再重画终点并将起点与终点连接起来即可,其实这也是直线旋转算法的思路。当我们用勾股定理来实现直线旋时,如图3-2
图3-2勾股定理画线旋转图
测试:运行发现,当直线竖立时,旋转角度太大,一两步就竖立了,显然看上去直线旋转不流畅,缺乏美感和真实感,此方法不行,那么为什么会出现这样的问题,仔细推算,原因在于,直线坐标是LONG型,而经过勾股定理的计算,先平方再开方,算得的是浮点型,再在式子中取为LONG型,会丢失许多数据。
b. 再考虑其它实现方法,由于直线的初始状态比较特殊,又只是到竖立状态,所以这里可采用相对坐标和旋转角度来求直线终点坐标,即利用直线长和角度的余弦或正弦来求,由于MFC视图中默认坐标系是原点为左上角,水平向右为横轴,竖直向下为竖轴,因此,逆时针方向角度则为负值,算法为:
m_LinePt2.x=long(m_LinePt1.x+m_LineLen*cos(-Beta/180.0*Pi));
m_LinePt2.y=long(m_LinePt1.y+m_LineLen*sin(-Beta/180.0*Pi));
(其中,直线起点终终不变,变化的只是角度Beta大小即可,当Beta角度为90度时循环终止即可)
测试:运行发现,角度Beta可以灵活设置,可以设置得较小,那么当时直线旋转时,上述a中的问题就彻底解决了,既变化角度可控,又视图流畅,而且上述算法每个终态只与其各自初态相关,算法简单,计算量小。
(二)那么当实现直线其它旋转算法时,是不是都可直接用上面的公式呢?显然,实现直线倒下,可以采用上述类似算法,但当实现直线左右旋转时,上述算法不可行,因为上述算法中因为直线初态本身是水上平的,所以用相对坐标和角度时,每次角度变化所作的变化恰好是水平坐标相对起点(水平坐标)的变化,纵坐标的变化也恰好是纵坐标相对起点纵坐标的变化,但当假设直线初始状态为某个倾斜角度时,角度的变化却不是相当于终点纵坐标的相对于起点纵坐标的变化。那么这时,只能找其它方法,根据计算机图形学知识相关知识:旋转是以某个参考点为圆心,将对象上的各个点(x,y)变为新的坐标(x′,y′)的变化。当参考点为(0,0)时,旋转公式为:
,所以上述公式可以变为:
如果参考点不是 ,而是任意一点 ,那么,绕 点的旋转由三个步骤完成
(1)将对象平移 ;
(2)按(式1)作旋转变换;
(3)平移 。
组合这三个步骤的计算公式为:
图3-3 图形旋转算法坐标图
当然,根据MFC绘图中坐标系,这里角度表示意义可能不一样。算法流程图类似图3-2,只是将算法改为图3-3演示的算法,并将终止条件稍变即可。
测试:通过上述算法,并在“左旋转”和“右旋转”时只是角度正负做对应调整即可,实现的旋转也具有真实感和美感。
我们发现,由b中算法简单,但适用范围太小,由c中算法通用,但计算量很大,复杂,总之,具上,当为“竖立”和“倒下”时采用b算法,当为“左/右旋转”时,采用算法c;
2、语音判断分支的选取
通过查资料,当我们采用CSpEvent::RecoResult()->GetText(0,-1,…)提取到要识别的所有命令时,一般的资料是采CString::CollateNoCase (_T(“…”))或CString::CompareNoCase(_T(“…”)),本程序开始也是采用此方法,即在OnRecoEvent()方法中采用如下代码时:
HRESULT hr=S_OK;
USES_CONVERSION;
CSpEvent event;
while(hr=event.GetFrom(m_RecoContext)==S_OK)
{
switch(event.eEventId)
{
case SPEI_RECOGNITION:
m_GotReco=TRUE;
static const WCHAR wszUnrecognized[]=L"<Unrecognized>";
CSpDynamicString dstrText; if(FAILED(event.RecoResult()->GetText(0,-1,TRUE,&dstrText,NULL)))
{dstrText=wszUnrecognized;
}
/* BSTR, known as basic string or binary string, is a pointer to a wide
character string used by Automation data manipulation functions.*/
BSTR SRout;
dstrText.CopyToBSTR(&SRout);//allocates a system BSTR
CString Restring;
Restring.Empty();
Restring=SRout;
if(1==!Restring.CollateNoCase(_T("竖立"))) {OnCOMStandUp();break;}
……
测试:发现程序能够识别语法文件“CmdStrl.xml”中定义的命令,但是执行多次便能够发现问题,当我们在运行程序后,使用“竖立”语音命令后,程序中机械臂正确竖立,当我们再随意用语音,比如说:“OK”"OR"、"RUN"、"RETURN"后,程序运行会出现一会儿竖立、一会儿倒下,显然与我们的期望不符。
再通过这个问题我们来查找原因,其实,当取出识别的语音后转换成CString类型,语音输入判断分支中,用CString的CollateNoCase()方法时,当比如说取得的语音与我们预定义的语法库中的字符串相比较,结果为0时,经过取反,计算机得到为1,这样也触发了识别控制命令,然后同样去调用了相应的动作执行过程(函数),产生与我们的期望的不相符的结果。
那么,为解决问题,我们需找到另一个方法,显然我们还是在CString类中找其它方法,经过查找MSDN,我们找到了CString::Compare()方法,我们将上面的if(1==!Restring.CollateNoCase(_T("…"))) 改为 if(0== Restring.Compare(_T("…)))后,再多次运行,最终解决了问题。
3、说明帮助文档的解决
由于本程序只是简单语音命令控制程序,同时第一次接触该程序的用户不一定知道如何使用,所以必须在运行程序的第一个界面就能使用户看到说明文档,那么如何解决呢?在程序中,我们可以看到,由于是采用SDI应用程序架构,且进入初始界面时,视图区域大部分是空白,显然我们可以在这个背景上显示说明文档,为此,可调用设备环境的TextOut()来装载我们已写好的说明文本资源,并且,我们应将这些显示文档放在旋转算法的循环之外,这样每次直线旋转时并不影响其视觉感观,而地面(水平线)的绘制应放在其循环中,这样直线旋转时始终有地面这个参照物,符合真实感观,其它的还有小的功能模块也可以简单实现。
当然,为了确定做完某一个动作后机械臂(直线)的状态,我们可以添加一个视图类的成员,每次执行一个动作,便将其值设为相应值,在最终显示时的OnDraw()方法中,每次判断最后一次做的动作并绘制其最终应显示的状态。
程序运行初始界面如图3-4:
图3-4 程序运行初始界面图
程序旋转过程中在某一时刻恰竖立状态如图3-5:
图3-5 程序运行时刻图
4 不足及其改进
1.程序稍微简单,机械臂只能实现简单动作,有待后续拓展与开发;
2.机械臂旋转过程中还应可以暂停,并可以更加精细地控制机械头旋转的动作,当然,正如1所述,有待在现有程序上拓展与开发;
3.刷新问题没有解决好,在机械臂旋转重绘中,本程序用的是全局刷新函数::InvalidateRect(NULL,NULL,TRUE);其最终是刷新了桌面上打开的所有窗口与图标,但尝试过,目前该程序中只有此方法才能实现所希望的旋转,这个有待查找更好的方法(函数)。
5 总结与展望
5.1 总结
本论文主要讨论了针对语音识别技术在计算机交互界面的应用研究而开发的一个程序,并着重讨论了基于MFC开发语音识别程序的主要流程、开发过程中涉及的部分算法,并诚实指出本程序的不足与改进。本论文的工作主要包括以下几点:
1.MFC绘图和直线旋转算法:主要是关于按钮消息映射与响应、视图中绘图设备的定义和刷新来实现直线旋转算法的内容。
2.语音控制的实现:主要是开发语音识别命令控制应用程序的步骤与注意事项,并探讨分析语法库的提取、语音判断分支的方法选择及控制响应。
3.简述应用帮助说明功能块的解决。
可见,语音识别和人机交互技术结合应用于计算机语音交互有很重大的学术价值和实用价值。随着信息社会的发展,尤其是语音技术在嵌入式发展的巨大实用前景,必定有更多的人员进行语音交互界面的应用研究,本论文的研究只是其中的一个试验,我也将在后续工作中继续进行完善,继续进行这方面的研究。
5.2 展望
语音技术的发展仍将充满活力,对语音识别的研究与应用将一直具有远大前景与重要意义,即:将最终实现人与机器进行自然语音交互这一目标。在这一目标下,我们将看到的是,在语音识别研究及其应用方面,困绕语音识别的上述所述问题将得到很大的解决,协同发音、噪音影响、模式匹配速度慢、特征提取准确度等问题将不再是语音识别技术应用的阻力;而与此同时,在现实中,用户体验将全然一新,人类不再受制于键盘、鼠标、显示器等图形用户接口,人将更习惯于用命令或语音来控制计算机或机器人来为自己服务,使机器成为我们的“知音”,成为我们人类的朋友,成为人类生理的一部分。
而且,在云技术及移动互联等快速发展及其促进下,语音识别技术将是人工智能必不可少数的功能模块,语音识别将是人机交互的主要界面。
致谢
终于在不断的学习与克服困惑中,将要完成自己的毕业论文,在这个过程中,逐渐明白:尽早地定位错误在开发中非常重要;碰到问题要解决问题;编程开发要持之以恒,才能有较大进步。在这个过程中,要感谢童老师,从最初定题、资料收集、论文修正与指点,每一个时刻都有童老师在背后给予关注,并且,还能宽容地给予足够时间,让我平静细心写自己的论文,当然,在这个过程中,也还有好朋友、同学给予硬件和软件的辅助或指点,在此深表感谢!
参考文献
[1]邢铭生,朱浩,王宏斌.语音识别技术综述.科协论坛[J].2010.3(下)
[2]付勇,童强老师.计算机语音交互界面应用研究.湖北师范学院2010届计算机科学与技术学院毕业论文(设计).2010.5.20:1~39.
[3]肖玮,使用SAPI实现语音识别与合成.现代计算机[J].2005.2(第二0五期).
[4]吕争,吴明慧.基于语音的人机交互界面的研究与实现[J].荆门职业技术学院学报,2007,22(6): 14~18.
[5]百度百科.API[EB/OL]. http://baike.baidu.com/view/16068.htm, 2011.4.3.
[6]童强.delphi实现电脑语音控制程序[J].微计算机信息.2006.3: 21~23.
[7]何好义,计算机语音识别技术与及其应用.大众科技[J].2005.6期(总第80期).
[8]Lorenzo Platteau,Talk to your applications[J].2003.11.7.
[9]马孜卓,Microsoft Speech SDK及语音技术研究[J].2010.3.
[10]陈一宁,朱璇等.语音识别开发工具包SRDK的研究与开发.计算机工程与应用.2003.1.
[11]邢铭生,朱浩,王宏斌.语音识别技术综述.科学文坛,2010年第三期(下):62~63.