Python版本是Python3.7.3,OpenCV版本OpenCV3.4.1,开发环境为PyCharm
PCA方法是EigenFaces方法的核心,它找到了最大化数据总方差特征的线性组合。不可否认,EigenFaces是一种非常有效的方法,但是它的缺点在于在操作过程中会损失许多特征信息。因此,在一些情况下,如果损失的信息正好是用于分类的关键信息,必然会导致无法完成分类。
Fisherfaces采用LDA(Linear Discriminant Analysis,线性判别分析)实现人脸识别。线性判别识别最早由Fisher在1936年提出,是一种经典的线性学习方法,也被称为“Fisher判别分析法”。
线性判别分析在对特征降维的同时考虑类别信息。其思路是:在低维表示下,相同的类应该紧密地聚集在一起;不同的类别应该尽可能地分散开,并且它们之间的距离尽可能地远。简单地说,线性判别分析就是要尽力满足以下两个要求:
● 类别间的差别尽可能地大。
● 类别内的差别尽可能地小。
做线性判别分析时,首先将训练样本集投影到一条直线A上,让投影后的点满足:
● 同类间的点尽可能地靠近。
● 异类间的点尽可能地远离。
做完投影后,将待测样本投影到直线A上,根据投影点的位置判定样本的类别,就完成了识别。
例如,下图所示的是一组训练样本集。现在需要找到一条直线,让所有的训练样本满足:同类间的距离最近,异类间的距离最远。
下图的左图和右图中分别有两条不同的投影线L1和L2,将图23-13中的样本分别投影到这两条线上,可以看到样本集在L2上的投影效果要好于在L1上的投影效果。
线性判别分析就是要找到一条最优的投影线。以图23-14中右图投影为例,要满足:
● A、B组内的点之间尽可能地靠近
● C的两个端点之间的距离(类间距离)尽可能地远
找到一条这样的直线后,如果要判断某个待测样本的分组,可以直接将该样本点向投影线投影,然后根据投影点的位置来判断其所属类别。
例如,在下图中,三角形样本点U向投影线投影后,其投影点落在圆点的投影范围内,则认为待测样本点U属于圆点所在的分类。
在OpenCV中,通过函数cv2.face.FisherFaceRecognizer_create()生成Fisherfaces识别器实例模型,然后应用cv2.face_FaceRecognizer.train()函数完成训练,用cv2.face_FaceRecognizer. predict()函数完成人脸识别。
1.函数cv2.face.FisherFaceRecognizer_create()
函数cv2.face.FisherFaceRecognizer_create()的语法格式为:
retval = cv2.face.FisherFaceRecognizer_create( [, num_components[, threshold]] )
式中的两个参数都是可选参数,它们的含义为:
● num_components:使用Fisherfaces准则进行线性判别分析时保留的成分数量。可以采用默认值“0”,让函数自动设置合适的成分数量。
● threshold:进行识别时所用的阈
值。如果最近的距离比设定的阈值threshold还要大,函数会返回“-1”。
2.函数cv2.face_FaceRecognizer.train()
函数cv2.face_FaceRecognizer.train()对每个参考图像进行Fisherfaces计算,得到一个向量。每个人脸都是整个向量集中的一个点。该函数的语法格式为:
None = cv2.face_FaceRecognizer.train( src, labels )
式中各个参数的含义为:
● src:训练图像,即用来学习的人脸图像。
● labels:人脸图像所对应的标签。
该函数没有返回值。
3.函数cv2.face_FaceRecognizer.predict()
函数cv2.face_FaceRecognizer.predict()在对一个待测人脸图像进行判断时,寻找与其距离最近的人脸图像。与哪个人脸图像最接近,就将待测图像识别为其对应的标签。该函数的语法格式为:
label, confidence = cv2.face_FaceRecognizer.predict( src )
式中的参数与返回值的含义为:
● src:需要识别的人脸图像。
● label:返回的识别结果的标签。
● confidence:置信度评分。置信度评分用来衡量识别结果与原有模型之间的距离。0表示完全匹配。该值通常在0到20000之间,若低于5000,就认为是相当可靠的识别结果。需要注意,该评分值的范围与EigenFaces方法的评分值范围一致,与LBPH方法的评分值范围不一致。
本节使用OpenCV的FisherFaces模块实现一个简单的人脸识别示例。
eg1:使用FisherFaces完成一个简单的人脸识别程序。
本例中用于学习的4幅人脸图像如图23-16所示,它们的名称从左至右分别为f01.png、f02.png、f11.png、f12.png。
这4幅图像中,前两幅图像是同一个人,将其标签设定为“0”;后两幅图像是同一个人,将其标签设定为“1”。
待识别的人脸图像如图23-17所示,该图像的名称为fTest.png。
根据题目的要求,编写代码如下:
import cv2
import numpy as np
images=[]
images.append(cv2.imread("f01.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("f02.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("f11.png",cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread("f12.png",cv2.IMREAD_GRAYSCALE))
labels=[0,0,1,1]
#print(labels)
recognizer = cv2.face.FisherFaceRecognizer_create()
recognizer.train(images, np.array(labels))
predict_image=cv2.imread("fTest.png",cv2.IMREAD_GRAYSCALE)
label,confidence= recognizer.predict(predict_image)
print("label=",label)
print("confidence=",confidence)
运行上述程序,识别结果为:
label= 0
confidence= 92.5647623298737
从输出结果可以看到,fTest.png被识别为标签“0”所对应的人脸图像,即认为人脸图像fTest.png与图像f01.png、f02.png所表示的是同一个人。