用opencv 矩阵特征值获得人脸特征值怎么做

【从零学习openCV】IOS7下的人脸检測 - 推酷
【从零学习openCV】IOS7下的人脸检測
人脸检測与识别一直是计算机视觉领域一大热门研究方向,并且也从安全监控等工业级的应用扩展到了手机移动端的app,总之随着人脸识别技术获得突破,其应用前景和市场价值都是不可估量的,眼下在学习openCV,自然不能放过这个领域,于是略微了解了下openCV下人脸检測的一些原理,为之后的人脸识别等研究做个小小的铺垫。
人脸检測属于目标检測
(object detection) &
的一部分,主要涉及两个方面
先对要检測的目标对象进行概率统计,从而知道待检測对象的一些特征,建立起目标检測模型。
用得到的模型来匹配输入的图像,假设有匹配则输出匹配的区域
好吧,这样说有点抽象,接下来我们来看看openCV经常使用的haar人脸检測是怎么回事吧
首先,什么是Haar呢?说白了,haar就是一种基于“块”的特征, 它最早是由 Papageorigiou 等人用于人脸描写叙述。眼下经常使用的 Haar-like 特征能够分为三类:线性特征、边缘特征、点特征(中心特征)、对角线特征。例如以下图所看到的:
显然,边缘特征有 4 种: x 方向, y 方向, x 倾斜方向, y 倾斜方向;线特征有 8 种,点特征有 2 种,对角线特征有 1 种。每一种特征的计算都是由黑色填充区域的像素值之和与白色填充区域的像素值之和的差值。而计算出来的这个差值就是所谓的 Haar-like 特征的特征值。
Haar特征是基于&块&的特征,可以减少计算成本。可是对于一张24*24的图片可以提取的haar特征量很巨大,大概有16万之多。怎样从这么多的特征中提取出对人脸识别真正实用的特征是一个很重要的问题,于是就要使用到 Adaboosting算法。
Adaboosting算法
AdaBoost算法是一种迭代的算法,对于一组训练集,通过改变当中每个样本的分布概率,而得到不同的训练集Si,对于每个Si进行训练从而得到一个弱分类器Hi,再将这些若分类器依据不同的权值组合起来,就得到了强分类器。
第一次的时候,每一个样本都是均匀分布,通过训练得到分类器H 0, 在该训练集中,分类正确的,就减少其分布概率;分类错误的,就提高其分布概率,这样得到的新的训练集S1就主要是针对不太好分类的样本了。再使用S1进行训练,得到分类器H1,依次迭代下去……,设迭代此外为T,则得到T个分类器。
对于每一个分类器的权值,其分类准确性越高,权值越高。
前面说到,一张24*24的图片,能提取到16W多的haar特征,一个弱分类器,实际上就是在这16W多的特征中选取一个特征,用这个特征可以区分出人脸or非人脸,且错误率最低。
比方如今有人脸样本2000张,非人脸样本4000张,这些样本都经过了归一化,大小都是24X24的图像。那么,对于16W中的任一特征f i, 我们计算该特征在这2000人脸样本、4000非人脸样本上的值,这样就得到6000个特征值。将这些特征值排序,然后选取一个最佳的特征值,在该特征值下,对于特征f i 来说,样本的加权错误率最低。选择全部特征中,错误率最低的特征,用来推断人脸,这就是一个弱分类器,同一时候用此分类器对样本进行分类,并更新样本的权重。
详细实施步骤例如以下,内容均摘自DylanTsou的博客
窗体扫描检測
得到了分类器后就行对图像进行人脸检測了,因为输入的图像往往与分类器训练的图像大小不一致(一般更大),于是我们须要一个可以滑动的窗体在输入图像上不断移动进行扫描,假设我们训练的图像就是24*24的,滑动窗体就是 一个24*24 window,使用这个window扫描一张大图上全部位置,在每一个位置上都使用训练好的分类器回答是不是人脸的问题。扫描结束之后须要一些重叠的窗体合并(在同一张人脸附近可能有非常多个临近窗体都被推断为包括人脸)。
为了可以提高扫描速度可以使用了逐级删选的方案,就是先開始使用计算成本低的分类器海选(这种分类器包括较少的特征),海选过程中标准较低,尽可能将全部的人脸都删选进来,低标准导致非常多非人脸也被选进来。然后逐渐提高分类器的标准(也就是说使用包括很多其它特征的分类器,同一时候添加了计算成本)这种逐级删选可以减少计算成本。 最后另一个问题: 在一张照片中人脸的大小各有区别不一定就和训练图片大小同样。解决问题的方法是使用不同大小的窗体来检測人脸, 这时候若分类器中的阈值须要随着窗体面积做等比例的变化。
使用openCV进行人脸检測
了,经过前面的介绍,对人脸检測的原理应该有了大体的了解,其有用openCV实现人脸检測十分简单。
首先OpenCV 自带了人脸的 Haar 特征分类器。 OpenCV 安装文件夹中的 \data\ haarcascades 文件夹下的
haarcascade_frontalface_alt.xml与 haarcascade_frontalface_alt2.xml 都是用来检測人脸的 Haar 分类器。这个 haarcascades 文件夹下还有人的全身,眼睛,嘴唇的 Haar 分类器 。
使用人脸的Haar特征分类器很之简单,直接使用 cvHaarDetectObjects 。以下来看看这个函数的介绍:
函数功能: 检測图像中的文件夹
函数原型:
CVAPI ( CvSeq *)& cvHaarDetectObjects (
& const & CvArr *& image ,
& CvHaarClassifierCascade *& cascade ,
& CvMemStorage *& storage ,
& double & scale_factor & CV_DEFAULT (1.1),
& int & min_neighbors & CV_DEFAULT (3),
& int & flags & CV_DEFAULT (0),
& CvSize & min_size & CV_DEFAULT ( cvSize (0,0)),
& CvSize & max_size & CV_DEFAULT ( cvSize (0,0))
參数说明:
CvArr *& image
: 表示输入图像,使用灰度图能够去除一些噪声,而且加快检測速度。
CvHaarClassifierCascade
cascade : 表示Haar特征分类器,能够用 cvLoad ()函数来从磁盘中载入xml文件作为Haar特征分类器。
CvMemStorage
storage : 表示内存存储器,用来统一管理各种动态对象的内存。
& scale_factor
: 表示在前后两次相继的扫描中,搜索窗体的比例系数。默觉得1.1即每次搜索窗体依次扩大10%
min_neighbors
: 表示构成检測目标的相邻矩形的最小个数(默觉得3个)。假设组成检測目标的小矩形的个数和小于&min_neighbors - 1&都会被排除。假设min_neighbors&为&0,&则函数不做不论什么操作就返回全部的被检候选矩形框,这样的设定值一般用在用户自己定义对检測结果的组合程序上。
: 要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,假设设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检測来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。
min_size 、 max_size :
表示检測窗体的最小值和最大值,一般设置为默认就可以。
函数返回值:
函数将返回 CvSeq 对象,该对象包括 一系列CvRect表示检測到的人脸矩形。
案例实战——IOS7人脸检測应用
最终进入正题了,这次的案例是在上篇的基础上稍加改动的,关于怎样在Xcode下配置openCV以及UIImage与cv:Mat和IplImage之间的转化我就不赘述了,详细请參看
首先我们先将 haarcascade_frontalface_alt2.xml导入project文件夹
将main.storyboard下的布局改成例如以下形式:
好了,废话不多说,直接上代码:
- (void) opencvFaceDetect
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
UIImage* img = [image copy];
[self.view bringSubviewToFront:self.indicator];
[self.indicator startAnimating];
//因为人脸检測比較耗时,于是使用载入指示器
cvSetErrMode(CV_ErrModeParent);
IplImage *image = [self CreateIplImageFromUIImage:img];
IplImage *grayImg = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); //先转为灰度图
cvCvtColor(image, grayImg, CV_BGR2GRAY);
//将输入图像缩小4倍以加快处理速度
int scale = 4;
IplImage *small_image = cvCreateImage(cvSize(image-&width/scale,image-&height/scale), IPL_DEPTH_8U, 1);
cvResize(grayImg, small_image);
//载入分类器
NSString *path = [[NSBundle mainBundle] pathForResource:@&haarcascade_frontalface_alt2& ofType:@&xml&];
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad([path cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL, NULL);
CvMemStorage* storage = cvCreateMemStorage(0);
cvClearMemStorage(storage);
//关键部分,使用cvHaarDetectObjects进行检測,得到一系列方框
CvSeq* faces = cvHaarDetectObjects(small_image, cascade, storage ,1.1, currentvalue, CV_HAAR_DO_CANNY_PRUNING, cvSize(0,0), cvSize(0, 0));
NSLog(@&faces:%d&,faces-&total);
cvReleaseImage(&small_image);
cvReleaseImage(I);
cvReleaseImage(&grayImg);
//创建画布将人脸部分标记出
CGImageRef imageRef = img.CGI
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef contextRef = CGBitmapContextCreate(NULL, img.size.width, img.size.height,8, img.size.width * 4,colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
CGContextDrawImage(contextRef, CGRectMake(0, 0, img.size.width, img.size.height), imageRef);
CGContextSetLineWidth(contextRef, 4);
CGContextSetRGBStrokeColor(contextRef, 1.0, 0.0, 0.0, 1);
//对人脸进行标记,假设isDoge为Yes则在人脸上贴图
for(int i = 0; i & faces-& i++) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Calc the rect of faces
CvRect cvrect = *(CvRect*)cvGetSeqElem(faces, i);
CGRect face_rect = CGContextConvertRectToDeviceSpace(contextRef, CGRectMake(cvrect.x*scale, cvrect.y*scale , cvrect.width*scale, cvrect.height*scale));
if(isDoge) {
CGContextDrawImage(contextRef, face_rect, [UIImage imageNamed:@&doge.png&].CGImage);
CGContextStrokeRect(contextRef, face_rect);
[pool release];
self.imageView.image = [UIImage imageWithCGImage:CGBitmapContextCreateImage(contextRef)];
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
cvReleaseMemStorage(&storage);
cvReleaseHaarClassifierCascade(&cascade);
[pool release];
[self.indicator stopAnimating];
上面这个函数就是整个人脸检測的核心了,思路非常easy,先将原图像转为灰度图,而且缩小4倍,这样处理的速度可以大大加快,然后就是载入haar分类器,调用 cvHaarDetectObjects 函数进行检測得到一系列的人脸框(cvRect),最后就是在原图像上把cvRect的地方画出来。
因为整个检測过程相对照较耗时,尤其是图像像素特别大的时候,甚至须要好几秒的时间,所以应该单开线程来调用 opencvFaceDetect 方法,而且最后用指示器来表示图像正在处理中。
- (IBAction)FaceDetectClicked:(id)sender {
[self.view bringSubviewToFront:self.indicator];
[self.indicator startAnimating];
[NSThread detachNewThreadSelector:@selector(opencvFaceDetect) toTarget:self withObject:nil];
终于效果例如以下:
近期迷上了doge啊,女神不要怪我。。
老规矩,整个案例的project代码附上:
(转载请注明作者和出处:
&未经同意请勿用于商业用途)
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致下次自动登录
现在的位置:
& 综合 & 正文
使用OpenCV进行人脸识别的三种算法(官方网翻译)
怎样使用进行人脸识别
本文大部分来自官网上的这节内容),小弟我尝试翻译一些重要内容。这部分内容是Philipp Wagner写的,他的:,他的网站,应该是个德国人。下面应该是他的照片。
友情提示,要看懂前,你得先知道的安装和配置,会用,用过一些函数。基本的图像处理和矩阵知识也是需要的。我是箫鸣的注释由于我仅仅是翻译,对于六级才过的我,肯定有一些翻译错的或者不当的地方,所以请大家纠错。
从开始,加入了新的类,我们可以使用它便捷地进行人脸识别实验。本文既介绍代码使用,又介绍原理。他写的,我们可以在的opencv\modules\contrib\doc\facerec\src下找到,当然也可以在他的中找到,如果你想研究源码,自然可以去看看,不复杂
目前支持的算法有
Eigenfaces特征脸
Fisherfaces
Local Binary Patterns Histograms局部二值直方图
下面所有的例子中的代码在安装目录下的下面都能找到,所有的代码商用或者学习都是免费的。
对人类来说,人脸识别很容易。文献告诉我们,仅仅是才三天的婴儿已经可以区分周围熟悉的人脸了。那么对于计算机来说,到底有多难?其实,迄今为止,我们对于人类自己为何可以区分不同的人所知甚少。是人脸内部特征眼睛、鼻子、嘴巴还是外部特征头型、发际线对于人类识别更有效我们怎么分析一张图像,大脑是如何对它编码的?和向我们展示,我们的大脑针对不同的场景,如线、边、角或者运动这些局部特征有专门的神经细胞作出反应。显然我们没有把世界看成零散的块块,我们的视觉皮层必须以某种方式把不同的信息来源转化成有用的模式。自动人脸识别就是如何从一幅图像中提取有意义的特征,把它们放入一种有用的表示方式,然后对他们进行一些分类。基于几何特征的人脸的人脸识别可能是最直观的方法来识别人脸。第一个自动人脸识别系统在中又描述:标记点眼睛、耳朵、鼻子等的位置用来构造一个特征向量点与点之间的距离、角度等。通过计算测试和训练图像的特征向量的欧氏距离来进行识别。这样的方法对于光照变化很稳健,但也有巨大的缺点:标记点的确定是很复杂的,即使是使用最先进的算法。一些几何特征人脸识别近期工作在文献中有描述。一个维的特征向量被用在一个大数据库上,单靠几何特征不能提供足够的信息用于人脸识别。
特征脸方法在文献中有描述,他描述了一个全面的方法来识别人脸:面部图像是一个点,这个点是从高维图像空间找到它在低维空间的表示,这样分类变得很简单。低维子空间低维是使用主元分析找到的,它可以找拥有最大方差的那个轴。虽然这样的转换是从最佳重建角度考虑的,但是他没有把标签问题考虑进去。读懂这段需要一些机器学习知识。想象一个情况,如果变化是基于外部来源,比如光照。轴的最大方差不一定包含任何有鉴别性的信息,因此此时的分类是不可能的。因此,一个使用线性鉴别的特定类投影方法被提出来解决人脸识别问题。其中一个基本的想法就是,使类内方差最小的同时,使类外方差最大。
近年来,各种局部特征提取方法出现。为了避免输入的图像的高维数据,仅仅使用的局部特征描述图像的方法被提出,提取的特征很有希望的对于局部遮挡、光照变化、小样本等情况更强健。有关局部特征提取的方法有盖伯小波() ,离散傅立叶变换(Discrete Cosinus Transform,DCT)() ,局部二值模式(Local Binary Patterns,LBP)()。使用什么方法来提取时域空间的局部特征依旧是一个开放性的研究问题,因为空间信息是潜在有用的信息。
我们先获取一些数据来进行实验吧。我不想在这里做一个幼稚的例子。我们在研究人脸识别,所以我们需要一个真的人脸图像!你可以自己创建自己的数据集,也可以从这里)下载一个。
又称人脸数据库,个人,每人张照片。照片在不同时间、不同光照、不同表情睁眼闭眼、笑或者不笑、不同人脸细节戴眼镜或者不戴眼镜下采集。所有的图像都在一个黑暗均匀的背景下采集的,正面竖直人脸有些有有轻微旋转。
ORL数据库对于初始化测试比较适合,但它是一个简单的数据库,特征脸已经可以达到97%的识别率,所以你使用其他方法很难得到更好的提升。Yale人脸数据库是一个对于初始实验更好的数据库,因为识别问题更复杂。这个数据库包括15个人(14个男人,1个女人),每一个都有11个灰度图像,大小是320*243像素。数据库中有光照变化(中心光照、左侧光照、右侧光照)、表情变化(开心、正常、悲伤、瞌睡、惊讶、眨眼)、眼镜(戴眼镜或者没戴)。
坏消息是它不可以公开下载,可能因为原来的服务器坏了。但我们可以找到一些镜像(比如)但我不能保证它的完整性。如果你需要自己剪裁和校准图像,可以阅读我的笔记()。
此数据库包含个人的张图片,并且是剪裁好的。这个数据库重点是测试特征提取是否对光照变化强健,因为图像的表情、遮挡等都没变化。我认为这个数据库太大,不适合这篇的实验,我建议使用数据库。
我们从网上下了数据,下了我们需要在中读取它,我决定使用文件读取它。一个文件包含文件名,紧跟一个标签。
/path/to/image.0
假设是图像,就像你在下的。最后我们给它一个标签。这个标签类似代表这个人的名字,所以同一个人的照片的标签都一样。我们对下载的数据库进行标识,可以获取到如下结果:
./at/s1/1.0
./at/s1/2.0
./at/s2/1.1
./at/s2/2.1
./at/s40/1.39
./at/s40/2.39
想象我已经把图像解压缩在下面,而文件在。下面你根据自己的情况修改替换即可。一旦你成功建立文件,就可以像这样运行示例程序:
facerec_demo.exe D:/data/at.txt
<span style="color:#0.2 Creating the CSV File
你不需要手工来创建一个文件,我已经写了一个程序来做这事。
[gm:说一个我实现的方法
如果你会命令,或者称命令,那么你打开命令控制台。假设我们的图片放在下的文件夹下,可以输入如下语句:
J:\Faces\ORL&dir /b/s *.bmp & at.txt
然后你打开文件可能看到如下内容后面的,标签是自己加的:
J:\Faces\ORL\s1\1.0
J:\Faces\ORL\s1\10.0
J:\Faces\ORL\s1\2.0
J:\Faces\ORL\s1\3.0
J:\Faces\ORL\s1\4.0
J:\Faces\ORL\s1\5.0
J:\Faces\ORL\s1\6.0
J:\Faces\ORL\s1\7.0
J:\Faces\ORL\s1\8.0
J:\Faces\ORL\s1\9.0
J:\Faces\ORL\s10\1.1
J:\Faces\ORL\s10\10.1
J:\Faces\ORL\s10\2.1
J:\Faces\ORL\s10\3.1
J:\Faces\ORL\s10\4.1
J:\Faces\ORL\s10\5.1
J:\Faces\ORL\s10\6.1
自然还有编程等方法可以做得更好,看这篇文章反响,如果很多人需要,我就把这部分的代码写出来。遍历多个文件夹,标上标签
Eigenfaces
我们讲过,图像表示的问题是他的高维问题。二维灰度图像大小,是一个维的向量空间,所以一个像素大小的图像就是,维的图像空间。问题是,是不是所有的维数空间对我们来说都有用?我们可以做一个决定,如果数据有任何差异,我们可以通过寻找主元来知道主要信息。主成分分析是 (1901)独立发表的,而
(1933)把一些可能相关的变量转换成一个更小的不相关的子集。想法是,一个高维数据集经常被相关变量表示,因此只有一些的维上数据才是有意义的,包含最多的信息。PCA方法寻找数据中拥有最大方差的方向,被称为主成分。
表示一个随机特征,其中 .
<span style="color:#. 计算均值向量
<span style="color:#. 计算协方差矩阵 S
<span style="color:#. 计算的特征值
和对应的特征向量
<span style="color:#. 对特征值进行递减排序,特征向量和它顺序一致. K个主成分也就是k个最大的特征值对应的特征向量。
x的K个主成份:
其中 (11).
PCA基的重构:
然后特征脸通过下面的方式进行人脸识别:
A. 把所有的训练数据投影到子空间
B. 把待识别图像投影到子空间
C. 找到训练数据投影后的向量和待识别图像投影后的向量最近的那个。
还有一个问题有待解决。比如我们有张图片,每张像素大小,那么需要解决协方差矩阵的求解,而的大小是,那么我们会得到大小的矩阵,这需要大概的内存。解决这个问题不容易,所以我们需要另一个计策。就是转置一下再求,特征向量不变化。文献 中有描述。
[gm:这个还是自己搜着看吧,这里的讲的不清楚,不适合初学者看
OpenCV中使用特征脸
给出示例程序源代码
#include "opencv2/core/core.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"
#include &iostream&
#include &fstream&
#include &sstream&
using namespace cv;
using namespace std;
static Mat norm_0_255(InputArray _src) {
Mat src = _src.getMat();
// 创建和返回一个归一化后的图像矩阵:
switch(src.channels()) {
case <span style="color:#:
cv::normalize(_src, dst, <span style="color:#, <span style="color:#5, NORM_MINMAX, CV_8UC1);
case <span style="color:#:
cv::normalize(_src, dst, <span style="color:#, <span style="color:#5, NORM_MINMAX, CV_8UC3);
src.copyTo(dst);
return dst;
//使用CSV文件去读图像和标签,主要使用stringstream和getline方法
static void read_csv(const string& filename, vector&Mat&& images, vector&int&& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
if (!file) {
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if(!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, <span style="color:#));
labels.push_back(atoi(classlabel.c_str()));
int main(int argc, const char *argv[]) {
// 检测合法的命令,显示用法
// 如果没有参数输入则退出!.
if (argc & <span style="color:#) {
cout && "usage: " && argv[<span style="color:#] && " &csv.ext& &output_folder& " && endl;
exit(<span style="color:#);
string output_folder;
if (argc == <span style="color:#) {
output_folder = string(argv[<span style="color:#]);
//读取你的CSV文件路径.
string fn_csv = string(argv[<span style="color:#]);
// <span style="color:#个容器来存放图像数据和对应的标签
vector&Mat& images;
vector&int& labels;
// 读取数据. 如果文件不合法就会出错
// 输入的文件名已经有了.
read_csv(fn_csv, images, labels);
} catch (cv::Exception& e) {
cerr && "Error opening file \"" && fn_csv && "\". Reason: " && e.msg && endl;
// 文件有问题,我们啥也做不了了,退出了
exit(<span style="color:#);
// 如果没有读取到足够图片,我们也得退出.
if(images.size() &= <span style="color:#) {
string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
CV_Error(CV_StsError, error_message);
// 得到第一张照片的高度. 在下面对图像
// 变形到他们原始大小时需要
int height = images[<span style="color:#].rows;
// 下面的几行代码仅仅是从你的数据集中移除最后一张图片
//[gm:自然这里需要根据自己的需要修改,他这里简化了很多问题
Mat testSample = images[images.size() - <span style="color:#];
int testLabel = labels[labels.size() - <span style="color:#];
images.pop_back();
labels.pop_back();
// 下面几行创建了一个特征脸模型用于人脸识别,
// 通过文件读取的图像和标签训练它。
// T这里是一个完整的变换
//如果你只想保留个主成分,使用如下代码
cv::createEigenFaceRecognizer(10);
// 如果你还希望使用置信度阈值来初始化,使用以下语句:
cv::createEigenFaceRecognizer(10, 123.0);
// 如果你使用所有特征并且使用一个阈值,使用以下语句:
cv::createEigenFaceRecognizer(0, 123.0);
Ptr&FaceRecognizer& model = createEigenFaceRecognizer();
model-&train(images, labels);
// 下面对测试图像进行预测,是预
&&&&推荐文章:
【上篇】【下篇】实验报告: 人脸识别方法回溯与实验分析 【OpenCV测试方法源码】 - C++当前位置:& &&&实验报告: 人脸识别方法回溯与实验分析 【OpenCV测实验报告: 人脸识别方法回溯与实验分析 【OpenCV测试方法源码】&&网友分享于:&&浏览:0次实验报告: 人脸识别方法回顾与实验分析 【OpenCV测试方法源码】&
趁着还未工作,先把过去做的东西整理下出来~&&
Github源码:
(涉及个人隐私,源码不包含测试样本,请谅解~)
对实验结果更感兴趣的朋友请直接看
【摘要】这是一篇关于人脸识别方法的实验报告。报告首先回顾了人脸识别研究的发展历程及基本分类;随后对人脸识别技术方法发展过程中一些经典的流行的方法进行了详细的阐述;最后作者通过设计实验对比了三种方法的识别效果并总结了人脸识别所面临的困难与挑战。一些能反映方法性能的实验数据同样会在报告中展现,以便于更直观的了解其特点。&
【关键词】人脸识别;局部二值模式(LBP);线性判别(LDA);主成分分析(PCA)
注: 该报告所使用的方法描述来源于现有文献,这里仅以论文格式进行呈现。
&&&&&&& 简单来说,人脸识别就是利用计算机分析人脸视频或者图像,并从中提取出有效的识别信息,最终判别人脸对象的身份。它是基于生物识别技术的最要身份识别方法之一,涉及到计算机图形学、计算机视觉、模式识别、人工智能、计算智能等技术。对于人脸识别问题的研究已有几十年的时间,在理论研究和实际开发方面都取得了一定的成果,并在不断的发展与完善。另外,基于人脸图像的计算机视觉和模式识别问题也成为近些年研究的热点问题。其中包括人脸检测,人脸识别,人脸表情识别等各类识别问题。
&&&&&&& 人脸与人体的其他生物特征(指纹、虹膜等)一样与生俱来,其生物特征内在的稳定性和唯一性使其成为了作为身份识别的理想依据。与其他生物识别系统相比,人脸识别系统具有直接、友好、方便等特点,容易被使用者接受。因此,其在信息安全、刑事侦破、出入口控制等领域都有着广泛的应用前景。
1.1 人脸识别发展历程
&&&&&&& 关于人脸识别的研究最早始于心理学家们在20世纪50年代的工作,而真正从工程应用的角度来研究它则开始于20世纪60年代。最早的研究者是Bledsoe,他建立了一个半自动的人脸识别系统,主要是以人脸特征点的间距、比率等参数为特征。早期的人脸识别方法有两大特点:
&&&&&&& 1)大多数识别方法是基于部件的,它们利用人脸的几何特征进行识别,提取的信息是人脸主要器官特征信息及其之间的几何关系。这类方法比较简单,但是很容易丢失人脸的有用信息,从而在视角、表情等变化的情况下识别能力差。鉴于这种情况,后来出现了性能较优的模板匹配方法,即根据图像库中的人脸模板与待识别人脸模板在灰度上的相似程度来实现人脸识别,这类方法在一定时期内占据主流。
&&&&&&& 2)人脸识别研究主要是在较强约束条件下的人脸图像识别。假设图像背景单一或无背景,人脸位置已知或很容易获得,因此对现实场景产生的图像处理效果不佳。&
&&&&&&& 90年代中期以来,人脸识别方法向着整体识别和部件分析相结合的趋势发展。研究人员开始逐渐认识到人脸识别算法必须能够充分地利用人脸的各种特征信息,融合人脸的形状拓扑结构特征、局部灰度特征和全局灰度分布特征等多种特征。因此,出现了很多新的算法,这些算法是将原先单一的算法结合起来,共同完成人脸的识别。灰度和形状分离的可变形模型方法就是其中之一。90年代后期,一些商业性的人脸识别系统开始逐渐进入市场,人脸识别技术成为当今国际安全防范最重要的手段之一。但是,这些技术和系统离实用化还有一定的距离,性能和准确率有待提高。1991年Turk和Pentland [1]、[2] 首次提出著名的&特征脸&(Eigenface)方法,利用主成分分析(Principal Component Analysis,PCA)取得了不错的识别效果;Belhumer [3] 在他的论文中,成功地将Fisher判别准则应用到了人脸分类当中,提出了Fisherface方法;从此基于子空间和统计特征的人脸识别技术成了一种主流的技术,这种基于线性子空间的技术主要包括主成分分析、线形判别分析(Linear Discriminant Analysis,LDA)等方法。总体来说,这一阶段的基于机器学习方法的人脸识别技术得到了迅速的发展,在一些识别系统里面获得了不错的识别效果。最近几年,人脸识别的研究有了新的发展,基于机器学习的理论,研究者提出了许多新颖的方法,其中包括遗传算法(Genetic Algorithm,GA)、AdaBoost、贝叶斯分类器、支持向量机(Support Vector Machine,SVM)等方法。&
&&&&&&& 2000年以后,人脸识别方法的性能虽然有了一定的提高,但仍与人们的要求还有一定的差距,现有方法对光照、年龄、表情、姿态、距离等条件的变化比较敏感,当某些条件发生变化时,识别效果很不理想。目前,人脸识别技术仍只能用于某些对识别准确率要求不高的场合。
1.2 人脸识别方法分类
&&&&&&& 人脸识别从不同的角度有不同的分类方法,报告基于人脸识别的发展过程将其分为基于几何特征、基于代数特征和基于机器学习三类人脸识别方法。
1.2.1 基于几何特征的人脸识别方法
&&&&&&& 基于几何特征的方法是将人脸用一个几何特征矢量的表示,根据模式识别中层次聚类的思想设计分类器达到识别目的。通常采用的几何特征有人脸的五官如眼睛、鼻子、嘴巴等的局部形状特征。脸型特征以及五官在脸上分布的几何特征。提取特征时往往要用到人脸结构的一些先验知识。识别所采用的几何特征是以人脸器官的形状和几何关系为基础的特征矢量,本质上是特征矢量之间的匹配,其分量通常包括人脸指定两点间的欧式距离、曲率、角度等[9] 。
&&&&&&& 基于几何特征的识别方法比较简单、容易理解,但所使用的能量函数中各种代价的加权系数的选择是经验性的,没有形成统一的特征提取标准;从图像中抽取稳定的特征较困难,特别是特征受到遮挡时;对较大的表情变化或姿态变化的鲁棒性较差。
1.2.2 基于代数特征的方法
&&&&&&& 基于代数特性的方法通常是将空间图像的像素点变换投影空间[10] ,用一定数量的基本图像对人脸图像进行线性编码。
&&&&&&& 1)主成分分析(PCA)。PCA方法最早由Sirovitch和Kirby[5]、[6] 引人人脸识别领。主成分分析是多元统计分析中用来分析数据的一种方法,它是一种用较少数量的特征对样本进行描述以达到降低特征空间维度的方法,其基础是KL展开式。Turk等人[1]、[2] 首先提出了基于KL展开式的人脸识别方法,即特征脸(Eigenface)法。
&&&&&&& 2)独立分量分析(ICA)。独立分量分析是一种对多变量数据进行非正交线性坐标变换的方法,坐标轴方向由可以观察到的混合数据的二阶和高阶统计信息确定,变换的目的是使变换后的变量间相互独立[4] 。与PCA方法不同的是ICA方法要求特征空间的各个分量间统计独立。
1.2.3 基于机器学习的方法
&&&&&&& 在基于几何特征的方法中,人脸的特征是预先定义好的;而在基于机器学习的方法中,人脸的特征和类别利用统计分析和机器学习的技术从样本中学习来的。学习所得的人脸特征和类别存在于由各种算法所保证的分布规律、模型和判别函数中,并被用于人脸的检测和识别。
&&&&&&& 基于学习的分类器是现今比较流行的技术,有很多研究者在从事该研究,主要包括人工神经网络,支持向量机,隐马尔可夫模型(Hidden Markow Model,HMM)[7],贝叶斯决策和AdaBoost算法等技术。
2. 特征脸方法
&&&&&&& 特征提取是人脸识别系统中最为重要的一个组成部分。主成分分析方法(PCA)是应用最广泛的一种特征提取方法之一,它是一种统计学方法,在信号处理、模式识别、数字图像处理等领域已经得到了广泛的应用。特征脸方法是从主成分分析导出的一种人脸识别和描述技术。它将包含人脸的图像区域看作一随机向量,采用K-L变换得到正交K-L基,对应其中较大特征值的基具有与人脸相似的形状,因此又被称为特征脸。利用这些基的线性组合可以描述、表达和逼近人脸图像,所以可进行人脸识别与合成。识别过程就是将人脸图像映射到由特征脸组成的子空间上,并比较其在特征脸空间中的位置。
2.1 人脸空间的建立
& & 假设一幅人脸图像包含N个像素点,它可以用一个N维向量&G表示。这样,训练样本库就可以用&Gi(i=1,...,M)表示。协方差矩阵C的正交特征向量就是组成人脸空间的基向量,即特征脸。
& & 将特征值由大到小排列:&1&&2&...&&r ,其对应的特征向量为&k。这样每一幅人脸图像都可以投影到由u1, u2, ..., ur组成的子空间中。因此,每一幅人脸图像对应于子空间中的一点。同样,子空间的任意一点也对应于一幅图像。
2.2 特征向量的选取
& & & & 虽然协方差矩阵&O最多有对应于非零特征值的k(k远小于M)个特征向量,但是通常情况下,k仍然很大,而事实上,根据应用的要求,并非所有的特征向量都有需要保留,而特征空间投影的计算速度是直接与创建子空间所用的特征向量的数目相关,若考虑到计算时间的因素,可以适当的减去一些信息量少的特征向量,而且去掉这些特征向量之后不一定不利于分类结果,有的情况下反而能够提高识别性能。
2.3 预测识别
&&&&&&& 有了这样一个由&特征脸&组成的降维子空间,任何一幅人脸图像都可以向其投影得到一组坐标系数,这组系数表明了该图像在子空间中的位置,从而可以作为人脸识别的依据。换句话说,任何一幅人脸图像都可以表示为这组&特征脸&的线性组合,其加权系数即是K-L变换的展开系数,也可以称为该图像的代数特征。因此,在获得特征脸之后,就可以对每一类别的典型样本进行投影,由此得到每个人脸的投影特征从而构成人脸特征向量,作为下一步识别匹配的搜索空间。
&&&&&&& 输入图像及其在人脸空间上的投影(重构图像),人脸图像在人脸空间中的投影变化不明显而非人脸图像的投影变化明显。因此,检测一幅图像中是否存在人脸的基本思想是,计算该图像中任意位置处的局部图像与人脸空间之间的距离&。其中,&是局部图像是否为人脸的度量。因此,只要计算给定图像任意一点上的&,就可以得到映射图&(x,y) 。
3 线性判别分析
&&&&&&& 线性判别分析(linear/fisher discrimination analysis,LDA)思想是将多维空间上的样本投影到一条直线上,形成一维特征空间。在该直线上样本的投影具有最佳可分性,即同类模式尽可能的密集,不同类模式尽可能分开。
&&&&&&& LDA实质上就是多维模式空间到一维特征空间的映射,利用类的成员信息形成一组特征向量,特征向量体现了不同的人脸变化,称此特征空间为Fisherface。该方法以训练样本的类内散布矩阵与类间散布矩阵为基础构造最优投影空间。与PCA相比,LDA更好地反映了不同人脸之间的差异性,即增加了类间差异,但却忽略了同一个体由于光照、姿态等因素的不同而产生的类内差异。与基于K -L变换的人脸识别方法相比,基于Fisher的人脸识别方法能够抑制图像之间的与识别信息无关的差异,同时能够提取出异类之间有益于识别的特征,因此具有更加优越的识别性能。
&&&&&&& Fisherfaces方法被Belhumeu等人提出,它是由Fisher线性判别式(Fisher&s lineardiscriminant,FLD)思想派生而来,同时考虑类间离散度和类内离散度,使这两者的比率达到最大。Belhumeur的实验证明,Fisherfaces的性能优于Eigen-faces。但即便如此,Fisherfaces还是存在两个明显的问题,即小样本问题(样本数目小于样本维数),以及多数实际问题属于非线性可分,传统的Fisher线性分析在这些问题上不能取得良好的结果[9]。因此,一系列Fisherfaces的改进方法也被提出。
&&&&&&& 在数学上,Fisher鉴别准则最终转化为求取散布矩阵特征值的问题。但是对人脸识别的应用来说,由于通常没有足够的训练样本来保证类内离散度矩阵Sw为满秩,无法直接求解,因此需要加入一定的条件或策略才行,这里就不作具体介绍了。
4 局部二值模式
&&&&&&& LBP算子是执行纹理描述的最好的方法之一,它已经广泛用于各种应用软件,并且被证明有很高的判别能力、计算效率及不变形单调灰度水平变化的优势,能适用与各种复杂的图像分析任务。使用LBP作为人脸表示的想法是由于脸部能被看做由微模块组成,这种组成能很好的用LPB运算表述出来。
4.1 基本的LBP算子
&&&&&&& 局部二值模式是一种灰度范围内的纹理描述方法,最初LBP算子定义为在3&3的窗户,以窗口的中心像素为阈值,将周围8个像素的灰度值与其比较,大于中心像素则标记为1,否则为0。这样3&3周围的8个点可以得到一个8位无符号的二进制数,这个二进制数转换为一个十进制整数,即该窗口的LBP值,用这个值来反映该区域的纹理信息。基本的LBP计算见图1。
图1 基本的LBP算子
&&&&&&& LBP可以用不同尺寸的邻域来表示,采用圆形领域结合双线性插值,邻域的半径R和像素数目P可以任意选取,用符号(P,R)表示像素的领域关系。我们可以用式子LBP 表示LBP运算(上标u2表示使用统一模式)[8]、[11]。圆形邻域的实例参见图2。
图2 (8,1)、(16,2)、(8,2)邻域
4.2 LBP人脸描述
&&&&&&& LBP方法进行人脸描述,这一过程包括使用纹理描述符对人脸局部进行描述,在将其组合起来成一个整体。人脸图像被划分为几个局部区域,纹理描述符从这些单独的区域提取出来,这些描述符串联起来组成了人脸的整体描述。
&&&&&&& 把脸部区域分成确定的m份,每个区域单独做直方图计算,m个直方图的计算结果组合到一起形成空间增强直方图,空间增强直方图的大小为m&n,其中n为单个直方图的大小。在空间增强直方图中,我们能有效的有效的对脸部进行三个不同层次的描述,这三个层次是:直方图的LBP标志包含的信息组成一个像素级;一个小的区域上的标志集合起来组成一个地域级;这些区域的直方图连接在一起构成完整的人脸。
5 实验对比
&&&&&&& 为了更好的了解各种人脸识别算法的性能与效果,这里通过openCV对PCA、Fisher线性判别、LBP三种算法进行了测试。实验使用的人脸图片共560张,由28位同学提供,其中每人20张(10张用于训练,10张用于测试)。图3与图4分别展示了前6位同学的训练样本与测试样本实例。
图3 训练样本(部分)
图4 测试样本(部分)
&&&&&&& 图5显示了28位同学提供的样本分别在三种识别算法下的识别情况。
图5 三种方法的匹配效果对比
&&&&&&& 其中24号样本在PCA、Fisher算法下的正确匹配数量少于一半。27号样本(参见图6)由于拍照环境过于复杂,在有限的训练样本中无法正确匹配。
图6 27号的训练样本(上)与测试样本(下)
表1 三种算法的识别率比较
表2 三种算法的性能对比
&&&&&&& 表1给出了三种算法对于每组样本的识别比例,经过统计可以得出,在上述的样本空间里主成分分析方法的识别率为91.0714%;Fisher线性判别方法的识别率为89.6429%;局部二值模式下的识别率为90.3571%。此外,表2还结合了样本训练的时间与预测所有测试样本的时间,给出了三种算法在性能上的对比。从中,我们发现PCA方法的总体表现较为出色。
6 总结与展望
&&&&&& 综合比较目前常用的几种人脸识别方法,通过分析可以看出,每种方法都有各自优缺点,应根据具体的识别任务和条件选择合适的识别方法。由于人脸识别的复杂性,仅单独使用任何一种现有的方法一般都不会取得很好的识别效果,将各种人脸识别方法组合是今后研究的一种趋势。而如何有效地与基于其它生物特征识别方法结合来提高识别效率也是一个重要的研究方向。
&&&&&&& 目前,人脸识别技术已经从理论走向了实用,在特殊场合已经得到了广泛应用,但是限制其应用的最主要难题是:人脸姿态、光照变化、表情变化所导致的识别效果不理想。对于姿态的变化,采用通用3D模型和形变模型的方法是目前较好的选择;对于光照变化,熵图像是处理光照变化的一个有效方法,结合图像变形技术可以更好地处理光照和姿态的变化;对于表情变化,采用同一个体和不同个体的图像进行弹性变形的概率模型方法获得了较好的识别效果,也可以采用3D模型和形变模型进行识别。而随着真三维获取技术的发展,人脸识别技术有望取得突破性的进展并得到广泛的应用。
&&&&&&& 课程的学习让我对图像处理的知识体系有了比较全面的认识,为今后相关问题的解决提供了广阔的思路。此外,各位同学的报告与展示也让我收获良多。在此,我向提供人脸图片样本的同学们表示感谢。(涉及个人隐私,源码不包含样本)
[1] Turk M, Pentland A. Eigenfaces for recognition[J]. Journal of cognitive neuroscience, ): 71-86.
[2] Turk M A, Pentland A P. Face recognition using eigenfaces[C]//Computer Vision and Pattern Recognition, 1991. Proceedings CVPR'91., IEEE Computer Society Conference on. IEEE, 1.
[3] Belhumeur P N, Hespanha J P, Kriegman D. Eigenfaces vs. fisherfaces: Recognition using class specific linear projection[J]. Pattern Analysis and Machine Intelligence, IEEE Transactions on, ): 711-720.
[4] Bartlett M, Lades H, Sejnowski T. Independent component representations for face recognition. Proceeding of the SPIE Symposium on Electronic Imaging: Human Vision and Electronic Imaging[M]. SPIE Press, .
[5] Sirovich L, Kirby M. Low-dimensional procedure for the characterization of human face[ J]. Journal of the Optical Society of America, ): 519-524.
[6] Kirby M, Sirovich L. Application of the Karhunen-Loeve procedure for the characterization of human faces[J]. IEEE Transactions on Pattern Analysis and Machine Intelligence,):103-108.
[7] Samaria F, Young S. HMM based architecture for face identification[J]. Image and ComputerV ision, ): 537-543.
[8] T. Ahonen, A. Hadid, M. Pietikainen. Face description with local binary patterns: Application to face recognition[J]. IEEE Trans. Pattern Anal. ): .
[9] 吴巾一,周德龙. 人脸识别方法综述[J]. 计算机应用研究, ): .
[10] 段锦著. 人脸自动机器识别[M]. 北京: 科学出版社, 2009.
[11] 黄非非. 基于LBP的人脸识别研究[D]. 天津: 天津大学, 2009.
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 1234567891011 Copyright & &&版权所有}

我要回帖

更多关于 基于opencv的人脸识别 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信