基于手势识别的幻灯片控制系统的设计论文正文Word下载.docx
《基于手势识别的幻灯片控制系统的设计论文正文Word下载.docx》由会员分享,可在线阅读,更多相关《基于手势识别的幻灯片控制系统的设计论文正文Word下载.docx(53页珍藏版)》请在冰点文库上搜索。
手势识别的研究目的就是设计实现能够识别人的特定的手势,并以此来传递信息或控制设备的系统。
手势识别的研究已经有四十多年的历史。
最早的手势识别研究,是基于笔或鼠标之类的二维输入设备的书写识别。
书写也可以看作是一种手势,因为书写其实就是手在二维平面上的手势。
尤其在线书写(也称动态书写)识别和动态手势识别是同一问题,都是分析时空运动轨迹。
而研究动态手势识别就是针对人拿着激光笔在白板上书写形成的手势进行的。
严格意义的手势识别开始于基于跟踪器的手势识别,即通过在手上放置传感器,利用传感器传回的数据来进行的手势识别。
典型的装置是数据手套,这种方式能够获得手势的精确数据,对手势做准确地分析。
尽管这种基于被动感知方式的手势识别在特定应用场合也能够得到有效的使用,但是由于它的侵犯性和操作复杂性,很难在实际中被广泛使用。
所以,研究人员开始逐渐关注主动感知方式的基于视觉的手势识别。
基于视觉的手势识别,是指对视频采集设备拍摄到的包含手势的图像序列采用计算机视觉技术来处理,最终识别手势。
基于视觉的手势识别在1992年左右才出现,因为这时才有了彩色视频采集设备,可以用来实时拍摄手势图像序列。
在这之后,基于视觉的手势识别便得到了广泛地关注,研究人员对基于视觉的手势识别做了深入地研究。
由于人手变形复杂,手势具有多样性和多义性,视觉问题本身存在各种困难,这些使得研究基于视觉的手势识别极富挑战性。
研究人员一开始通过在人手上放置特定颜色的标记来简化问题,但是这种方法不方便用于在实际系统中,因此现在研究的重点是如何实现基于视觉的自由的人机交互。
一般在设计实现基于手势识别的交互系统时,首先要根据需求而定义相应的手势集合,实现的系统会根据输入的具体手势实现相应的反应或相应的控制。
一般的基于手势识别的交互系统会包含有以下几个部分:
手势检测和跟踪;
静态手势识别和动态手势识别。
手势检测和跟踪就是将手势从采集到的图像或图像序列中检测出来,这是手势识别的第一步,包括手的检测和跟踪。
静态手势识别针对从图像中检测并分割出来的手,可以识别出手的手形,而动态手势识别则是通过对图像序列中手势运动的跟踪,得到手的运动轨迹,然后根据手势在时间空间或特征状态空间的运动轨迹来区分不同的动态手势。
1.2.2现状分析
目前,基于手势识别的人机交互界面分为操作性和交互性两类:
一类是利用手势操作计算机中的虚拟对象;
另一类则把手势作为计算机和人类的交流的语言。
前者,手势操作的虚拟对象一般是计算机产生的图形,如模拟物体、控制面板设备、机器人的手臂、Windows操作系统中的窗口等。
在操纵这些虚拟对象时,会用到跟踪和识别这两项技术。
后者,手势被看成是一个直接的交流手段,如美国的手语识别系统可以把手语翻译成语音,这样对于残疾的朋友尤其有意义。
一个完整的基于手势识别的交互系统一般由以下几个部分构成。
首先,通过摄像设备获取视频数据流,接着,系统根据手势输入的交互模型检测数据流里是否有预定义的手势出现,如果有,则把该手势从视频信号中分割出来。
然后,选择手势模型进行手势分析,分析过程包括特征提取和模型参数估计。
在识别阶段,根据模型参数对手势进行分类并根据需要生成手势描述,最后,系统根据生成的描述去做相应的控制或者输出识别结果。
所以,手势识别的一般步骤可分为:
手势分割;
手势建模;
手势分析;
手势识别。
而相关的基于手势识别的交互系统,则再根据自身设计的需求进行下一步的设计即可,也就是再将识别出的结果和相应的控制系统相结合,最终达到利用手势控制设备或者其他系统的效果。
其中,对于核心的手势识别部分,从识别技术来看,以往的交互系统主要采用基于人工神经网络(ANN),隐Markov模型(HMM)和几何边缘特征等方法。
①模板匹配技术
这是一种最简单的识别技术,它将输入的原始数据与预先存储的模板进行匹配,通过测量两个模板之间的相似度来完成识别任务。
②基于神经网络的手势识别
该方法目前广泛应用于静态手势的识别。
神经网络是一种大规模并行处理网络,由许多具有非线性映射能力的神经元组成,神经元之间通过权相连,神经网络能实现复杂的非线性映射,映射关系是通过学习(或训练)得到的,神经网络具有很高的计算速度、很强的容错性和鲁棒性,特别适合用于模式识别。
神经网络是一种具有高度非线性的超大规模连续时间动力学系统,它的出现标志着人们智能信息处理能力和模拟人脑智能行为能力的一大飞跃。
③基于HMM的手势识别
对于分析区间内的手势信号,通常采取HMM方法进行模型化。
该技术在动态手势识别领域一直占有主导地位,然而由于HMM拓扑结构的一般性,导致这种模型在分析手语信号时过于复杂,使得HMM训练和识别计算量过大,尤其是在连续的HMM中,由于需要计算大量的状态概率密度,需要估计的参数个数较多,使得训练及识别的速度相对较慢,因而以往手语识别系统所采用的HMM一般为离散HMM。
④基于几何矩的手势识别
一幅图像可以被认为是一个二维密度分布,那么与空间位置有关的像素值的几何矩函数,就能够提供该图像的形状信息,例如,图像的总面积、图像矩心的坐标以及图像的方位。
这些形状特点能被进一步用于构造特征向量,而这些特征向量在图像的平移、旋转、尺度变化时保持不变。
这样就能够通过计算原始图像中的一系列几何矩和标准模板库中的几何矩的点乘距离进行判断。
手势识别技术在过去的几年的研究成果中主要使用的是KL变换、神经网络方法及几何矩,这些方法在拥有较少图像的图像库中识别率较高,但是对于较大的识别库,它的识别率就比较低,因此有待于研究新的适应性强、实用性好的识别算法。
1.3课题目标及内容
1.3.1研究目标
本课题的研究目的是对现有的手势识别算法进行综合、改进,并与现有的幻灯片控制技术结合,得到一个以手势变换来控制幻灯片的系统,同时根据得到的系统,设计一个虚拟交互环境,来实现真实世界物体与虚拟环境的互动。
本课题旨在完成的任务是在目前现有研究技术的基础上,熟悉掌握相关的手势识别知识,并结合大学日常学习生活中较为常见的一种应用软件——幻灯片的有关知识,将幻灯片控制与手势识别结合,做成一种简易的人际交互系统,以此进一步加深对人际交互活动的理解,并能够熟悉相关方面的知识。
1.3.2研究内容
本课题主要完成将现有的幻灯片控制函数在手势识别后加以调用,使之产生特定的控制效果。
系统首先利用摄像头采集用户的手势信息,然后将采集到的信息储存,加以处理,并提取其中的有用信息,与预定义的手势信息加以匹对,如果匹对成功,则调用相应的手势信息所控制的函数(用以控制幻灯片的),从而实现手势控制幻灯片。
由于手势的多义性和复杂性,本课题研究时,将特定的三个手势(静态)作为预定义的手势信息,用三种手势之间产生的六种变换实现不同的幻灯片控制功能。
同时将相应的控制函数包含在一个总对话框的按钮的定义中,实现可视化的控制。
1.4论文组织结构
论文共分为6章,组织结构如下:
第一章:
绪论。
本章介绍了课题研究背景与意义、国内外研究现状、课题的研究内容和目标。
概述了手势识别及其相关技术的发展和分类,并进行了国内外研究现状分析。
第二章:
主要应用技术。
介绍了本系统在实现过程中所涉及到的主要技术,以及这些技术的总体概况、最新研究进展情况。
阐述了诸如手势图像的处理、提取、分析(图像Hu矩的计算);
SVM技术的应用和OpenCV相关知识。
第三章:
系统总体结构及功能划分。
本章主要介绍系统的总体架构和各个模块的功能划分,对每个具体模块涉及的问题进行了介绍。
第四章:
手势识别的设计与实现。
介绍了系统的设计方式及手势识别模块的具体实现方法。
详细阐述了各主要算法的工作原理,及在本系统中的实现方式、注意细节。
第五章:
接口模块的设计与实现。
本章主要是做一个接口,将手势识别模块与幻灯片控制模块联系在一起,使系统能够通过手势达到控制幻灯片的目标。
本章还介绍了MFC窗口的部分知识及其OpenCV窗口的前端显示问题和解决办法。
第六章:
系统测试。
本章主要对系统的功能及性能进行测试。
2背景技术
本章主要介绍了在实现手势识别中手势图像采集及处理分析所用到的主要技术,主要包括C++编程技术、MFC(微软基础类)相关知识、OpenCV所涉及的相关知识和支持向量机(SVM)的相关知识等。
另外,本章还分别介绍了这些技术的研究背景、现状及以后的发展方向。
2.1C++编程技术
C++是一种使用非常广泛的计算机编程语言。
它是一种静态数据类型检查的,支持多重编程范式的通用程序设计语言。
它支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等等泛型程序设计等多种程序设计风格。
2.1.1C++的编程原则
由于C++本身使用的广泛性和代表性,熟悉继而掌握这门编程语言是十分重要的。
C++语言在设计时有一定的原则,可以帮助我们很好的理解和掌握它的编程技术,也同时培养了我们的良好的编程习惯。
这些原则主要有:
•C++设计成静态类型、和C同样高效且可移植的多用途程序设计语言。
•C++设计成直接的和广泛的支援多种程序设计风格(程序化程序设计、资料抽象化、面向对象程序设计、泛型程序设计)。
•C++设计成给程序设计者更多的选择,即使可能导致程序设计者选择错误。
•C++设计成尽可能与C兼容,籍此提供一个从C到C++的平滑过渡。
•C++避免平台限定或没有普遍用途的特性。
•C++不使用会带来额外开销的特性。
•C++设计成无需复杂的程序设计环境。
出于保证语言的简洁和运行高效等方面的考虑,C++的很多特性都是以库(如STL)或其他的形式提供的,而没有直接添加到语言本身里。
2.1.2C++的编程技巧和应用
C++在编程中有诸多的设计技巧,可以方便使用者熟悉和掌握。
这些技巧都有:
使用new和delete进行动态内存分配和释放
运算符new和delete是C++新增的运算符,提供了存储的动态分配和释放功能。
它的作用相当于C语言的函数malloc()和free(),但是性能更为优越。
使用new较之使用malloc()有以下的几个优点:
(1)new自动计算要分配类型的大小,不使用sizeof运算符,比较省事,可以避免错误。
(2)自动地返回正确的指针类型,不用进行强制指针类型转换。
(3)可以用new对分配的对象进行初始化。
举例如下:
(1)int*p;
p=newint[10];
//分配一个含有10个整数的整形数组
delete[]p;
//删除这个数组
(2)int*p;
p=newint(100);
//动态分配一个整数并初始化
使用inline内联函数替代宏调用
对于频繁使用的函数,C语言建议使用宏调用代替函数调用以加快代码执行,减少调用开销。
但是宏调用有许多的弊端,可能引起不期望的副作用。
例如宏:
#defineabs(a)(a)<
0?
(-a):
(a)),当使用abs(i++)时,这个宏就会出错。
所以在C++中应该使用inline内联函数替代宏调用,这样既可达到宏调用的目的,又避免了宏调用的弊端。
使用内联函数只须把inline关键字放在函数返回类型的前面。
例如:
inlineintAdd(inta,intb);
//声明Add()为内联函数
这样编译器在遇到Add()函数时,就不再进行函数调用,而是直接嵌入函数代码以加快程序的执行。
使用函数重载
在C语言中,两个函数的名称不能相同,否则会导致编译错误。
而在C++中,函数名相同而参数数据类型不同的两个函数被解释为重载。
voidPutHz(char*str);
//在当前位置输出汉字
voidPutHz(intx,inty,char*str);
//在x,y处输入数字
使用函数重载可以帮助程序员处理更多的复杂问题,避免了使用诸如intabs()、fabs()、dabs()等繁杂的函数名称;
同时在大型程序中,使函数名易于管理和使用,而不必绞尽脑汁地去处理函数名。
同时必须注意,参数数据类型相同,但是函数返回类型不同的两个函数不能重载。
用引用(reference)代替指针进行参数传递
在C语言中,如果一个函数需要修改用作参数的变量值的时候,参数应该声明为指针类型。
voidAdd(int*a)
{
(*a)++;
}
调用时则使用
Add(&
x);
//其中x为int或可以转化为int的类型,如unsignedint,但这时候编译器通常会给出warning
对于复杂的程序,使用指针容易出错,程序也难以读懂。
在C++中,对于上述情况可以使用引用来代替指针,使程序更加清晰易懂。
引用就是对变量取的一个别名,对引用进行操作,这就相当于对原有变量进行操作。
例如使用引用的函数定义为:
voidAdd(int&
a)
a++;
//a为一个整数的引用
调用时使用
Add(x);
//其中x为int
这个函数与使用指针的上一个函数的功能是一样的,然而代码却更为简洁和清晰易懂。
使用缺省参数
在C++中函数可以使用缺省参数,例如:
voidPutHzxy(char*str,intx=-1,inty=-1)
if(x==-1)
x=wherex();
if(y==-1)
moveto(x,y);
PutHx(str);
可以有三种方式调用函数PutHzxy(),例如:
PutHzxy("
C++语言"
);
//使用缺省参数,在当前位置输出
10,10);
//没有使用缺省参数
10);
//对y使用缺省参数,指定x的位置
通常的情况下,一个函数应该具有尽可能大的灵活性。
使用缺省参数为程序员处理更大的复杂性和灵活性问题提供了有效的方法,所以在C++的代码中都大量地使用了缺省参数。
需要说明的是,所有的缺省参数必须出现在不缺省参数的右边。
亦即,一旦开始定义缺省参数,就不可再说明非缺省的参数。
否则当你省略其中一个参数的时候,编译器无法知道你是自定义了这个参数还是利用了缺省参数而定义了非缺省的参数。
例如:
voidPutHzxy(char*str,intx=-1,inty=-1)//正确
voidPutHzxy(intx=-1,inty=-1,char*str)//错误
使用STL
STL(StandardTemplateLibrary,标准模板库),STL的代码从广义上讲分为三类:
algorithm(算法)、container(容器)和iterator(迭代器),并包括一些工具类如auto_ptr。
几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
#include<
vector>
//包含相关的头文件/
typedefstd:
:
vector<
int>
intvector;
//使用typedef使代码看起来更简洁
intmain()
intvectorvi;
for(inti=0;
i<
10,i++)
vi.push_back(i);
//使用push_back添加元素
vi.size();
i++)
std:
cout<
<
vi[i]<
"
"
;
//[]操作符被重载,使得我们可以像访问数组一样访问vector中的元素
}
2.2MFC简介
2.2.1MFC简述
MFC是一个编程框架。
MFC(MicrosoftFoundationClassLibrary)中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。
因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。
MicrosoftVisualC++提供了相应的工具来完成这个工作:
AppWizard可以用来生成初步的框架文件(代码和资源等);
资源编辑器用于帮助直观地设计用户接口;
ClassWizard用来协助添加代码到框架文件;
最后,编译,则通过类库实现了应用程序特定的逻辑。
MFC实现了对应用程序概念的封装,把类、类的继承、动态约束、类的关系和相互作用等封装起来。
这样封装的结果对程序员来说,是一套开发模板(或者说模式)。
针对不同的应用和目的,程序员采用不同的模板。
例如,SDI应用程序的模板,MDI应用程序的模板,规则DLL应用程序的模板,扩展DLL应用程序的模板,OLE/ACTIVEX应用程序的模板,等等。
这些模板都采用了以文档-视为中心的思想,每一个模板都包含一组特定的类。
为了支持对应用程序概念的封装,MFC内部必须作大量的工作。
例如,为了实现消息映射机制,MFC编程框架必须要保证首先得到消息,然后按既定的方法进行处理。
总之,MFC封装了Win32API,OLEAPI,ODBCAPI等底层函数的功能,并提供更高一层的接口,简化了Windows编程。
同时,MFC支持对底层API的直接调用。
MFC提供了一个Windows应用程序开发模式,对程序的控制主要是由MFC框架完成的,而且MFC也完成了大部分的功能,预定义或实现了许多事件和消息处理,等等。
框架或者由其本身处理事件,不依赖程序员的代码;
或者调用程序员的代码来处理应用程序特定的事件。
MFC是C++类库,程序员就是通过使用、继承和扩展适当的类来实现特定的目的。
例如,继承时,应用程序特定的事件由程序员的派生类来处理,不感兴趣的由基类处理。
实现这种功能的基础是C++对继承的支持,对虚拟函数的支持,以及MFC实现的消息映射机制。
MFC类库提供了一组通用的可重用的类库供开发人员使用。
大部分类均从CObject直接或间接派生,只有少部分类例外。
MFC应用程序的总体结构通常由开发人员从MFC类派生的几个类和一个CWinApp类对象(应用程序对象)组成。
MFC提供了MFCAppWizard自动生成框架。
Windows应用程序中,MFC的主包含文件为"
afxwin.h"
。
此外MFC的部分类为MFC/ATL通用,可以在Win32应用程序中单独包含并使用这些类。
2.2.2重要的MFC
有一些重要的MFC应用如下:
CWnd窗口,它是大多数“看得见的东西”的父类(Windows里几乎所有看得见的东西都是一个窗口,大窗口里有许多小窗口),比如视图CView、框架窗口CFrameWnd、工具条CToolBar、对话框CDialog、按钮CButton,等等;
一个例外是菜单(CMenu)不是从窗口派生的。
CDocument文档,负责内存数据与磁盘的交互。
最重要的是OnOpenDocument(读入),OnSaveDocument(写盘),Serialize(读写)。
CView视图,负责内存数据与用户的交互。
包括数据的显示、用户操作的响应(如菜单的选取、鼠标的响应)。
最重要的是OnDraw(重画窗口),通常用CWnd:
Invalidate()来启动它。
另外,它通过消息映射表处理菜单、工具条、快捷键和其他用户消息。
CDC设备文本。
无论是显示器还是打印机,都是画图给用户看。
这图就抽象为CDC。
CDC与其他GDI(图形设备接口)一起,完成文字和图形、图像的显示工作。
把CDC想象成一张纸,每个窗口都有一个CDC相联系,负责画窗口。
CDC有个常用子类CClientDC(窗口客户区),画图通常通过CClientDC完成。
CDialog对话框。
CWinApp应用程序类。
似于C中的main函数,是程序执行的入口和管理者,负责程序建立、消灭,主窗口和文档模板的建立。
最常用函数InitInstance():
初始化。
CGdiObject及子类,用于向设备文本画图。
它们都需要在使用前选进DC。
CPen笔,画线。
CBrush刷子,填充。
C