基于视觉的静态手势识别方法 【技术领域】
本发明涉及一种控制方法,特别是一种应用于计算机辅助哑语教学、电视节目双语播放、虚拟人的研究、电影制作中的特技处理、动画的制作、医疗研究、游戏娱乐等诸多方面,同时也有助于改善和提高聋哑人的生活学习和工作条件,为他们供更好的服务的基于视觉的静态手势识别方法。
背景技术
1991年富士通实验室完成了对46个手语符号的识别工作
2003年12月,美国密歇根州的Cybernet系统公司开发出一套名为手势风暴的系统,是公司针对天气预报节目开发的,主持人可以通过简单的手势来控制预报的进程。
2008年,日本东芝公司设在英国剑桥大学的一个研究实验室的科学家发明了“手势交互技术”(gesture interface technology),它可以使看电视的人通过简单的手势来控制电视。
现有技术中存在以下的技术困难:
(1)手势目标检测的困难
目标的实时检测是指在人以复杂的背景条件下从图像流中检测出目标来,这是机器视觉主要研究的课题之一。
(2)手势目标识别的困难
手势识别是根据人手的姿态以及变化过程来解释其高层次的含义,由于手势具有以下特点:
a)是弹性物体,故同一种手势之间差别很大;
b)手有大量冗余信息,由于人识别手势关键是识别手指特征,故手掌特征是冗余信息;
c)位置是在三维空间,因此难以定位,并且计算机获取的图像是三维向二维的投影,因此投影方向很关键;
d)手的表面是非光滑的,因此易产生阴影。
【发明内容】
本发明为了克服上述现有技术的不足,本发明提供一种识别效果好的基于视觉的静态手势识别方法。
本发明解决其技术问题所采用的技术方案是:提供一种基于视觉的静态手势识别方法,其包括以下步骤:S1手势图像预处理,根据人体的肤色特征从环境中分割出手区域,然后通过图滤波及图像形态学操作得到手势轮廓;S2手势特征参数提取,提取了Hu不变矩特征,手势区域特征以及傅立叶描述子参数,组成特征向量;S3手势识别,使用多层感知器分类器,该分类器具有自组织和自学习能力,能有效的抗噪声和处理不完整模式以及具有模式推广能力。
本发明解决进一步技术问题的方案是:所述的步骤S1包括S11二值化手势图像,S12平滑滤波去噪以及S13轮廓提取。
本发明解决进一步技术问题的方案是:所述的S11二值化手势图像是根据人体的肤色信息对原始的手势图像进行二值化处理,得到人手区域。
本发明解决进一步技术问题的方案是:所述的S12平滑滤波去噪使用中值滤波和线性平滑滤波对手区域二值图进行去噪,得到清晰地手势区域。
本发明解决进一步技术问题的方案是:所述的S13轮廓提取采用拉普拉斯边缘提取算法。
本发明解决进一步技术问题的方案是:所述的手势区域特征包括手势区域面积与手势区域矩形面积的比值,手势区域的长宽比,手势二值图的重心将手势外接矩形分割的上下两段的比例,手区域面积以及手势轮廓的周长。
相较于现有技术,本发明的基于视觉的静态手势识别方法在对原始的手势图像进行特征参数提取之前,先进行预处理,根据人体的肤色特征将原始的手势图像二值化,并对手势图像地二值图通过图像增强的方法去噪,得到没有噪声的二值图,然后对二值图进行边缘提取,得到手势的轮廓,提取的手势特征参数有三组,分别为Hu不变矩特征,手势区域特征以及傅立叶描述子,共同组成特征向量,该组特征具有更好的识别率,使得识别效果好,识别率高。
【附图说明】
图1是本发明的基于视觉的静态手势识别方法的原理模块示意图。
【具体实施方式】
如图1所示,本发明提供一种基于视觉的静态手势识别方法,其包括以下步骤:S1手势图像预处理,根据人体的肤色特征从环境中分割出手区域,然后通过图滤波及图像形态学操作得到手势轮廓;S2手势特征参数提取,提取了Hu不变矩特征,手势区域特征以及傅立叶描述子参数,组成特征向量;S3手势识别部分,使用多层感知器分类器,该分类器具有自组织和自学习能力,能有效的抗噪声和处理不完整模式以及具有模式推广能力。
所述的步骤S1包括S11二值化手势图像,S12平滑滤波去噪以及S13轮廓提取。
S11二值化手势图像:根据人体的肤色信息对原始的手势图像进行二值化处理,得到人手区域,算法如下:
对于原始图像的每一个像素
{
由RGB值计算出该像素的Hue和Satisfaction值;
判断该像素的Hue和Satisfaction值是否均在该人的肤色区间内;
如果在则将该像素变为黑色;
否则将该像素变为白色;
}
经过二值化处理,可以得到手势区域的二值图。
S12平滑滤波去噪:由于二值化后的二值图主要存在椒盐噪声的影响,本系统使用中值滤波和线性平滑滤波对手区域二值图进行去噪,得到清晰地手势区域。
S13轮廓提取:采用拉普拉斯边缘提取算法,拉普拉斯算子是一种对二维函数进行运算的二阶导数标量算子,因此对图像中的噪声相当敏感,而且在进行处理时会在边缘处产生一个陡峭的零交叉,因此如果对于无噪声且具有陡峭边缘的图像,可以通过拉普拉斯算子检测出来。
S2手势特征参数提取:对预处理过后得到的手势模型,即手势区域二值图和手势轮廓,进行手势模型特征参数提取,本发明所要提取的手势特征参数有三组,分别为Hu不变矩特征,手势区域特征以及傅立叶描述子,共同组成特征向量:
<1>手势区域特征:
struct REGION_FEATURE
{
double area_ratio; //手势区域面积与手势区域矩形面积的比值
double aspect_ratio; //手势区域的长宽比
double bary_ratio;//手势二值图的重心将手势外接矩形手势区域矩
形分割的上下两段的比例
double hand_area; //手区域面积,用像素个数表示
double hand_perimeter;//手势轮廓的周长
};
<2>Hu不变矩特征
struct CvHuMoments
{
double hu1,hu2,hu3,hu4,hu5,hu6,hu7
};
<3>傅立叶描述子
struct FOURIER_FEATURE
{
vector<double> feature_data;
};
手势区域矩形的计算
int cvFindContours(
CvArr*image,
CvMemStorage*storage,
CvSeq**first_contour,
int header_size=sizeof(CvContour),
int mode=CV_RETR_LIST,
int method=CV_CHAIN_APPROX_SIMPLE,
CvPoint offset=cvPoint(0,0));
主要参数说明:
image:8-比特,单通道图像.非零元素被当成1,0象素值保留为0
storage:得到的轮廓的存储容器
first_contour:输出参数:包含第一个输出轮廓的指针
函数cvFindContours从二值图像中提取轮廓,并且返回提取轮廓的数目。指针first_contour的内容由函数填写。它包含第一个最外层轮廓的指针,如果指针为NULL,则没有检测到轮廓(比如图像是全黑的)。其它轮廓可以从first_contour利用h_next和v_next链接访问到。
然后通过CvRect手势区域矩形=((CvContour*)contour)->rect,就可以得到手势区域矩形。
关于hand_area特征的计算方法:
手势区域矩形计算出来以后,以下所有的特征的计算都是在图像的手势区域矩形区域内进行。手势的面积hand_area即为手区域包含的像素总数,通过扫描二值图中手势区域矩形区域,计算黑色点的个数即可得出。
area=∑∑f(x,y) (4-1)
其中
我们可以调用OpenCV的库函数cvContourArea来计算hand_area,函数原型如下:
double cvContourArea(
const CvArr*contour,
CvSlice slice=CV_WHOLE_SEQ);
参数contour为图像轮廓,slice则是兴趣轮廓部分的起始点,缺省是计算整个轮廓的面积。函数的返回值是整个轮廓的面积。
关于area_ratio特征的计算方法:
area_ratio=hand_area/(手势区域矩形.width*手势区域矩形.height)
关于aspect_ratio特征的计算方法:
aspect_ratio=(float)手势区域矩形.widht/(float)手势区域矩形.height
关于hand_perimeter特征的计算方法:
手势轮廓的周长hand_perimeter即为手势轮廓图像在手势区域矩形区域内包含的像素总数,通过扫描手势轮廓图中手势区域矩形区域,计算黑色点的个数即可得出:
hand_perimeter=∑∑f(x,y)
其中
我们可以调用OpenCV的库函数cvArcLength来计算hand_perimeter,函数原型如下:
double cvArcLength(
const void*curve,
CvSlice slice=CV_WHOLE_SEQ,
int is_closed=-1);
参数curve为曲线点集序列或数组,slice则是曲线的起始点,缺省是计算整个曲线的长度,参数is_closed表示曲线是否闭合。函数的返回值是计算轮廓周长或曲线长度。
Hu不变矩特征的计算方法:
1962年,M.K.Hu首先提出了不变矩,他给出了连续函数矩的定义和关于矩的基本性质,证明了有关矩的平移不变性、旋转不变性以及比例不变性等性质,具体给出了具有平移不变性、旋转不变性和比例不变性的七个不变矩的表达式,具体表达式如公式
φ1=μ20+μ02
φ2=(μ20-μ02)2+(2μ11)2
φ3=(μ30-3μ12)2+(3μ21-μ03)2
φ4=(μ30+μ12)2+(μ21+μ03)2
φ5=(μ30-3μ12)(μ30+μ12)[(μ30+μ12)2-3(μ21+μ03)2]+(3μ21-μ03)(μ21+μ03)[3(μ30+μ12)2-(μ21+μ03)
φ6=(μ20-μ02)[(μ30+μ12)2-(μ21+μ03)2]+4μ11(μ30+μ12)(μ21+μ03)
φ7=(3μ21-μ03)(μ30+μ12)[(μ30+μ12)2-3(μ21+μ03)2]-(μ30-3μ12)(μ21+μ03)[3(μ30+μ12)2-(μ21+μ03)
规格化的中心矩ηpq定义为:
ηpq=μpqμ00r]]>
其中r=p+q+22,]]>p+q=2,3,.....
计算图像Hu矩的主要代码
void CFeature::CalcHuMoments(const IplImage *img,CvHuMoments
&humoments)
{
CvMoments moments;
cvMoments(img,&moments,0);
cvGetHuMoments(&moments,&humoments);
}
傅立叶描述子的计算方法
傅立叶变换是线型变换的一种,它提供了一种解决线型系统问题的解决办法。傅立叶变换在很多学科的理论中起着重要作用,尽管可以象对待其他变换一样,把傅立叶变换看做纯数学的函数,但在许多领域,傅立叶变换也同样产生它们的函数一样的明确的物理意义。
用N个互相间隔Δx单位采样函数f(x),使其成为系列
{f(x0),f(x0+Δx),f(x0+2Δx,....f(x0+[N-1]Δx)}
规定f(x)=f(x0+Δx),这时x为离散值x=0,1,2,...,N一1,一上述序列表示为
{f(0),f(1),f(2),...,f(N-1)}
这时傅立叶变换对为
F(u)=1NΣx=0N-1f(x)exp[-j2πux/N]]]>
f(x)=Σu=0N-1F(u)exp[j2πux/N]]]>
式中F(u)=F(uΔu)u=0,1,2,...N-1,且Δu=1NΔx,]]>相应于0,Δu,2Δu,....(N-1)Δu
傅立叶变换对f(x)⇔F(u)]]>
离散傅立叶变换满足正交条件
1NΣx=0N-1exp[j2πu1x/N]exp[-j2πu2x/N]=1if(u1=u2)0elsewhere]]>
实际上,常令N=2m。
傅立叶描述子(Fourier DescriPtors)是物体形状边界曲线的傅立叶变换系数,它是物体边界曲线信号的频域分析的结果,是一种描述不受原点的移动及旋转影响的曲线的方法。
傅立叶描述子的基本思想是假定物体的形状是一条封闭的曲线沿边界曲线上所有点的序列为:{x(l),y(l):l=0,1,...,n-1},用复数的形式表示为:
P(l)=x(l)+jy(l) (l=0,1,....,n-1,j=-1]]>)
这样,边界就可以在一维空间上表示。
一维序列的离散傅立叶系数定义为:
z(k)=1nΣl=0n-1p(l)exp(-j2πlkn)]]>(k=0,1,....n-1)
Z是p的傅立叶变换,是点序列在频域中的表示。其傅立叶逆变换为
P(l)=p(l)=Σk=0n-1z(k)exp(j2πlkn)]]>(l=0,1,....n-1)
利用傅立叶系数的性质z(k)=z*(n-k)(z*是Z的共轭复数),在系数Z中,消去从K+l(0≤K<n2-1)]]>到n-K-1范围内的高频成分。再进行傅立叶逆变换,将得到和原曲线近似的曲线,但原曲线中突变的部分将变得平滑,这个近似的曲线称为原曲线的第K近似曲线。这个意义下的傅立叶系数子集{z(k):k≤K}称为傅立叶描述子(Fourier Descriptor)。由于傅立叶系数有能量向低频集中的特性,故用较少的系数就可以达到区分不同形状边界的目的。
傅立叶描述子与形状的尺度、方向和曲线的起始点位置有关。为了识别具有旋转、平移和尺度不变性的形状,需要对傅立叶描述子进行归一化。根据傅立叶变换性质,将物体形状边界起始点位置平移a长度,物体放大r倍,旋转角度职和平移位移(x0,y0)后,新的形状的傅立叶变换系数z‘(k):
其中k=0,1,....n-1, x′(l)+iy′(l)=x(l+a)+iy(l+a)
由上式可以看出,用傅立叶系数描述形状时,系数幅值□Z(k)□,k=0,1,....n-1,具有旋转不变性和平移不变性(Z(0)不具有平移不变性),并且与曲线起点的选择无关。当物体平移时,仅仅改变其Z(0)分量F(x0+iy0)的值。把每一个系数(Z(0)除外)的幅值□Z(k)□除以□Z(l)□,则是不随尺度变换而变化的,所以k=1,2,.....,n-1,□·□表示取模同时具有旋转,平移和尺度不变性,并且与曲线起点位置的选择无关,我们把它作为傅立叶描述子,故归一化的傅立叶描述子d(k)定义为:
k=1,2,...n-1,□·□表示取模
本系统取除z(0)外的前12个系数,得到一个12维的特征向量,该特征句量具有旋转、平移和尺度不变性,平且与曲线的起点位置的选择无关,具体算法如下:
CFeature::CalcFourierFeature(const IplImage*img,FOURIER_FEATURE
&fourier_feature)
{
assert(img!=NULL);
int MAX_POINT_NUMBER=1024; //假设轮廓点的数量最多为
1024
IplImage *clone_img=cvCloneImage(img);
CvMemStorage*storage=cvCreateMemStorage(0);
CvSeq *contour;
int contour_count=cvFindContours(
clone_img,
storage,
&contour,
sizeof(CvContour),
CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_NONE,
cvPoint(0,0));
double img_area=img->width*img->height;
for(;contour;contour=contour->h_next)
{
double contour_area=fabs(cvContourArea(contour,
CV_WHOLE_SEQ));
if(contour_area/img_area>=0.05)
break;
}
int point_count=contour->total;//轮廓点的数量
//assert(point_count<MAX_POINT_NUMBER);
MAX_POINT_NUMBER=point_count;
if(point_count>MAX_POINT_NUMBER)
{
fourier_feature.feature_data.clear();
return false;
}
CvPoint*pt=new CvPoint[point_count];
cvCvtSeqToArray(contour,pt,CV_WHOLE_SEQ);
CvMat *real_input=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64F);
CvMat *imag_input=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64F);
CvMat *comp_input=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64FC2);
cvZero(real_input);
cvZero(imag_input);
cvZero(comp_input);
for(int i=0;i<point_count;i++)
{
cvSetReal2D(real_input,0,i,pt[i].x);//将x设置为实部
cvSetReal2D(imag_input,0,i,pt[i].y);//将y设置为虚部
}
cvMerge(real_input,imag_input,NULL,NULL,comp_input);
cvDFT(comp_input, comp_input,
CV_DXT_FORWARD|CV_DXT_SCALE,comp_input->heigbt);//傅立叶变
换
CvMat *real_output=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64F);
CvMat *imag_output=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64F);
CvMat*spectrum=cvCreateMat(1,MAX_POINT_NUMBER,
CV_64F);//频谱
cvSplit(comp_input,real_output,imag_output,NULL,NULL);
cvPow(real_output,real_output,2.0);
cvPow(imag_output,imag_output,2.0);
cvAdd(real_output,imag_output,spectrum,NULL);
cvPow(spectrum,spectrum,0.5);
double factor=1.0/(cvGetReal2D(spectrum,0,0));
cvScale(spectrum,spectrum,factor,0);
for(int i=1;i<11;i++)
{
double d=cvGetReal2D(spectrum,0,i);
fourier feature.featuredata.push back(d);
}
cvReleaseMat(&real_input);
cvReleaseMat(&imag_input);
cvReleaseMat(&comp_input);
cvReleaseMat(&real_output);
cvReleaseMat(&imag_output);
cvReleaseMat(&spectrum);
cvReleaseImage(&clone_img);
cvReleaseMemStorage(&storage);
delete[]pt;
return true;
}
本发明的基于视觉的静态手势识别方法在对原始的手势图像进行特征参数提取之前,先进行预处理,根据人体的肤色特征将原始的手势图像二值化,并对手势图像的二值图通过图像增强的方法去噪,得到没有噪声的二值图,然后对二值图进行边缘提取,得到手势的轮廓,提取的手势特征参数有三组,分别为Hu不变矩特征,手势区域特征以及傅立叶描述子,共同组成特征向量,该组特征具有更好的识别率,使得识别效果好,识别率高。