[译]人脸检测与人脸识别简介
From: http://www.shervinemami.co.cc/faceRecognition.html
Translated by 11
“人脸识别”是一个在计算机视觉和生物特征识别领域十分活跃的话题。这个主题已经被给力地研究了25年,并且最终在安全、机器人学、人机交互、数码摄像机、游戏和娱乐领域得到了广泛应用。
“人脸识别”大致可分为两个阶段:
1.人脸检测 搜索一幅图像,寻找一切人脸区域(此处以绿色矩形显示),然后进行图像处理,清理脸部图像以便于更好地识别。
2.人脸识别 把上一阶段检测处理得到的人脸图像与数据库中的已知人脸进行比对,判定人脸对应的人是谁(此处以红色文本显示)。
2002年后,人脸检测已经可以相当可靠地运作。比如OpenCV的Face Detector,对于一个人直视摄像头得到的较清晰图片,大约有90-95%的准确度。通常来说,当人以侧面对准摄像头或与摄像头成一定角度时,较难检测到人脸,有时需要3D Head Pose Estimation。假如图片亮度不是很好,也较难检测到人脸。脸部的部分区域比另一部分区域明亮,带有阴影,模糊,或者戴眼镜,也会影响检测效果。
然而,人脸识别却比人脸检测不可靠得多,一般只有30-70%的准确度。20世纪90年代以来,人脸识别一直是一个很重要的研究领域,但仍然十分不可靠,并且每一年都有更多的识别技术被创造,如文章底部所列出的(Alternatives to Eigenfaces such as 3D face recognition or recognition from video.)
我将向你展示如何使用“特征脸”(Eigenfaces),也称为主元分析法(Principal Component Analysis or PCA)。相对于普通的神经网络方法(Neural Networks)和Fisher Faces方法来说,这是一个简单和流行的对图片进行的二维人脸识别的方法。
要学习特征脸方法的理论,你需要阅读Face Recognition With Eigenface from Servo Magazine (April 2007),可能还需要一些数学算法。
首先我将向你解释,怎样实现特征脸的命令行离线训练(offline training from the command-line),基于Servo Magazine tutorial and source-code (May 2007)。
之后,我将说明如何将此扩展成为从网络摄像头进行实时的在线训练:-)
使用OpenCV的Face Detector检测人脸
如上所述,人脸识别的第一个阶段是人脸检测。OpenCV库使得使用它的Haar Cascade Face Detector(也称为Viola-Jones方法)检测正面人脸变得相当简单。
OpenCV里的“cvHaarDetectObjects”函数执行人脸检测,但是这个函数直接用没有意义,所以最好用这个包装好的函数:
这是把一幅RGB格式的图像或灰度图像转变为灰度图像的基本代码。它还把图像调整成了固定的维度,然后应用直方图均衡化来实现固定的亮度和对比度。
在上面这些示例图片中你可以看到平均人脸和第一个以及最后一个特征脸。它们是从一个四人的每人30幅图片的训练集中生成的。注意到,平均人脸显示的是一个普通人的平滑脸部结构,排在最前的一些特征脸显示了一些主要的脸部特征,而最后的特征脸(比如Eigenface 119)主要是图像噪声。你可以在下面看到前32张特征脸。
使用主元分析法进行人脸识别
简单地说,特征脸方法(Principal Component Analysis)计算出了训练集中图片的主要区别,并且用这些“区别”的组合来代表每幅训练图片。
比如,一张训练图片可能是如下的组成:
(averageFace) + (13.5% of eigenface0) – (34.3% of eigenface1) + (4.7% of eigenface2) + … + (0.0% of eigenface199).
一旦计算出来,就可以认为这张训练图片是这200个比率(ratio):
{13.5, -34.3, 4.7, …, 0.0}.
用特征脸图片分别乘以这些比率,并加上平均人脸图片 (average face),从这200个比率还原这张训练图片是完全可以做到的。但是既然很多排在后面的特征脸是图像噪声或者不会对图片有太大作用,这个比率表可以被降低到只剩下最主要的,比如前30个,不会对图像质量有很大影响。所以现在可以用30个特征脸,平均人脸图片,和一个含有30个比率的表,来代表全部的200张训练图片。
有趣的是,这意味着,我们已经找到了一种方法把200张图片压缩成31张图片再加上一点点数据,而不丢失很多的图像质量。但是这个教程是关于人脸识别的,而不是图像压缩的,所以我们将会忽略它:-)
在另一幅图片中识别一个人,可以应用相同的PCA计算,使用相同的200个特征脸来寻找200个代表输入图片的比率。并且仍然可以只保留前30个比率而忽略其余的比率,因为它们是次要的。然后通过搜索这些比率的表,寻找在数据库中已知的20个人,来看谁的前30个比率与输入图片的前30个比率最接近。这就是寻找与输入图片最相似的训练图片的基本方法,总共提供了200张训练图片。
离线命令行训练的实现
为了实现离线训练,也就是通过命令行(command-line)使用文件作为输入输出,我使用了与Servo Magazine里Face Recognition with Eigenface相同的实现,所以你可以先阅读这篇文章,但是我做了一些小的改动。
基本上,从训练图片创建一个人脸识别数据库,就是创建一个列出图片文件和每个文件代表的人的文本文件。
比如,你可以把这些输入一个名为”4_images_of_2_people.txt”的文本文件:
CvCapture* camera = 0;// The camera device.while ( cvWaitKey(10) != 27 ) {// Quit on "Escape" key.IplImage *frame = getCameraFrame(camera);...}// Free the camera.cvReleaseCapture( &camera );请注意,假如你是为windows操作系统开发,你可以使用 Theo Watson 的 videoInput Library v0.1995 达到两倍于这些代码的速度。它使用了DirectShow硬件加速,然而OpenCV使用VFW已经15年不变了!
把我已经解释的这些部分放到一起,人脸识别系统运行步骤如下:1. 从摄像头抓取一帧图片。
2. 转换彩色图片帧为灰度图片帧。
3. 检测灰度图片帧的人脸。
4. 处理图片以显示人脸区域(使用 cvSetImageROI() 和 cvCopyImage())。
5. 预处理脸部图片。
6. 识别图片中的人。
摄像头实时训练的实现
现在你已经有了一个用摄像头实时识别人脸的方法,但是要学习新人脸,你不得不关闭这个程序,把摄像头的图片保存成图片文件,更新图片列表,使用离线命令行训练的方法,然后以实时摄像头识别的模式再次运行这个程序。所以实际上,你完全可以用程序来执行实时的摄像头训练!
这里就是用摄像头视频流把一个新的人加入人脸识别数据库而不关闭程序的一个最简单的方法:
1. 从摄像头收集一些图片(预处理后的脸部图片),也可以同时执行人脸识别。
2. 用“cvSaveImage()”函数保存这些脸部图片作为图片文件存入磁盘。
3. 加入每张脸部图片的文件名到训练图片列表(用于离线命令行训练的文本文件)的底部。
4. 一旦你准备实时训练,你将从所有图片文件形成的数据库重新训练。这个文本文件列出了新加入的训练图片文件,并且这些图片被电脑存为了图片文件,所以实时训练工作起来跟离线训练一样。
5. 但是在重新训练之前,释放任何正在使用的资源和重新初始化也很必要。应该像你重新启动了这个程序一样。比如,在图片被存储成文件并且加入训练列表的文本文件后,你应该再执行相同的离线训练(包括从训练列表文件载入图片,用PCA方法找出新训练集的特征脸和比率)之前释放特征脸数组。 这个实时训练的方法相当低效,因为假如在训练集中有50个人,而你多加了一个人,它将为51个人重新训练,这是非常不好的,因为训练的时间随着用户或图片数量的增加呈指数级增长。但是假如你只是处理百来张图片,它不需要多少秒就可以完成。
文件下载请转到原文。
The article source is http://www.shervinemami.co.cc/faceRecognition.html