本文将分别讲述基于SVM和PCA的人脸识别
SVM人脸识别理论
在之前的文章中,我们讲过SVM的原理:利用超平面进行二分类。我们来看看它是怎么作用到人脸识别上来的。
人脸作为一张h*w的二维图像(去掉颜色通道的灰度图),可以看做一个h*w维的(含有h*w个坐标值)的数据。在SVM里,寻找到一个h*w-1维的超平面可以对这样的人脸进行二分类。假设我们有两个人的多张人脸数据,就可以训练出一个模型(找到这样一个超平面),能够最好地区分两种人脸。
在实际操作中,我们不会只满足于二分类的人脸识别。事实上SVM通过组合可以构建多分类的分类器,通常的实现方法是:1)对其中一种脸和其它的脸构建二分类模型,轮流构建多个即可。2)对任何两种脸构建二分类模型,遍历所有组合即可。
本文中使用了sklearn中的SVM的api,就是有多分类功能的。
PCA人脸识别理论
PCA原来在之前的文章也有讲述:通过在数据们的信息量最大的方向上进行降维投影,获得数据的在新空间的表示。
谈到人脸识别或者任何形式的图片相似度匹配,假设我们不知道PCA或SVM这种成熟的算法原理,而需要这个问题。容易想到:把h*w大小的图片看做一个h*w维数据,这样在h*w维空间里,一张图片只是一个点。考察两张图片(两个点)在h*w维空间的距离,距离越近则相似度越高。
事实上PCA最终的解决方案跟上述方法是一致的!只是PCA的精髓在于,提供了一种降维变换。在降维变换到新的空间之后,用简化的方式表示原来的图片。然后再考虑在新空间中两张图片的距离来确定相似度。
具体到PCA在人脸识别的应用,就是:先找到训练人脸数据的投影空间(特征脸空间),然后将训练的人脸们投影到该空间。在识别时,将待识别的脸也投影到该空间,然后逐一比较它与训练的人脸的距离。距离最近则为识别出的对象。
再具体一点,在PCA人脸识别的工程实践中,我们使用的方法叫做Eigenfaces,即特征脸方法。它不是直接将训练人脸投影到特征脸空间,而是先进行中心化,即求所有训练数据的平均值(称作“平均脸”),求得所有训练人脸到该平均值的差值作为真正的训练数据,再进行投影。在识别时,也会先将待识别的人脸减去上述平均脸,再投影,再计算距离。
下面是特征脸。每一张脸其实就是一个特征向量,他们作为该空间的一组基存在。
实现原理和代码
完整代码见此
在代码上,SVM和PCA没有什么区别,因为只是OpenCV的接口不同。除此之外的部分是一致的。
在代码实现上,首先通过传参来决定:人脸采集 or 人脸识别。 人脸采集通过OpenCV调用计算机的摄像头进行图像拍照,然后抠出人脸进行保存。人脸识别上,同样通过OpenCV调用计算机摄像头进行拍照,此外还可以通过输入图像文件进行识别。值得一提的是,通过循环拍照识别,可以将识别过程动态化为视频识别。
下面代码,我们按照功能而非按照工作流程进行讲解
图片读取
1 | import cv2 |
人脸提取
OpenCV自带了人脸提取的Haar特征分类器,其参数以xml格式保存,只要调出相应文件即可使用1
2
3
4
5
6
7
8
9
10
11
12# 通过CascadeClassifier级联分类器读取模型参数,获得模型对象
face_cascade = cv2.CascadeClassifier('<PATH>/haarcascade_frontalface_alt2.xml')
# 通过detectMultiScale提取gray_img里的每个人脸的方形坐标
# 输出faces为numpy.ndarray格式的x,y,w,h数据,比如[[238 109 217 217],[121 19 215 215]],代表两个人脸
# 第一个人脸框左上顶点为(238,109),宽和高分别为217和217;第二个人脸框左上顶点为(121,19),宽和高分别为215和215
faces = face_cascade.detectMultiScale(gray_img, 1.1, 5)
# 打印看看
for x,y,w,h in faces:
cv2.imshow('image', gray_img[y:y+h,x:x+w])
cv2.waitKey(0)
经过实际测试,OpenCV自带的模型精度并不高,当图片中的人脸有倾斜或者侧转的时候,很容易提取不出人脸。
为了更高的精度,我们使用著名的经过caffe训练好的人脸提取器。OpenCV的dnn库有相关的接口可以直接读取caffe模型文件:
1 | # 实例化一个caffe模型 |
训练
假设我们已经获取了很多张人脸图片(灰度图)及其label,将这些图片和label读取到numpy.ndarray变量train_X, train_Y中。 其中train_X的shape为(N,300,300),train_Y的shape为(N,)
同时我们待预测的原始图片为image,其灰度图为gray_img,其人脸所在框的两个顶点为(startX, startY), (endX, endY)
SVM
1 | from sklearn.svm import SVC |
PCA
1 | # 实例化特征脸识别器对象 |
效果展示
参考
https://docs.opencv.org/master/db/d7c/group__face.html
https://www.pyimagesearch.com/2018/09/24/opencv-face-recognition/