前文提到了OpenCV自带人脸分类器,虽然准确性一般,但含泪也要完成工作,巧合的是,OpenCV还提供了三种人脸识别算法(Eigenfaces、Fisherfaces、LBPH),这些算法各有特点,识别率一般。
OpenCV人脸识别算法有三种:
Eigenfaces 他是通过PCA来处理的。PCA它是计算机视觉中使用的一个更多的数学概念。其本质是识别训练集中的主要成分,计算人脸相对于数据库的发散程度,并输出值。值越小,人脸数据库与检测到的人脸之间的差异越小,0表示完全匹配。低于4000-5000的值相对可靠
Fisherfaces 它是从PCA衍生发展起来,逻辑更复杂,计算更密集,但比Eigenfaces更容易得到准确的效果。
LBPH(Local Binary Pattern Histogram) 在一个非常好的层次上,检测到的人脸被分成小单元,并与模型中的相应单元进行比较,并为每个区域的匹配值生成一个直方图。由于该方法的灵活性,它是唯一一种不同形状和大小的人脸识别算法。50分以内的置信分相对可靠
model = cv2.face.EigenFaceRecognizer_create()
创建识别模型并使用它EigenFace算法识别,Confidence4000分以下可靠
model = cv2.face.LBPHFaceRecognizer_create()
创建识别模型并使用它LBPHFace算法识别,Confidence50分以下是可靠的
model = cv2.face.FisherFaceRecognizer_create()
创建识别模型并使用它FisherFace算法识别,Confidence4000分以下可靠
从训练图片中随机选择两种新的预测文件夹,从网上找到刘德华的照片,试试识别效果。
获得训练集的函数与前面一致
训练过程和预测过程添加到主函数中。
import cv2 import numpy as np import os import shutil # OpenCV有三种人脸识别的算法: # Eigenfaces 他是通过PCA来处理的。PCA在计算机视觉中使用的数学概念较多。其本质是识别训练集中的主要成分,计算检测到的人脸相对于数据库的发散程度,并输出值越小,表明人脸数据库与检测到的人脸之间的差异越小,0表示完全匹配。低于4000-5000的值相对可靠 # Fisherfaces 它是从PCA衍生发展起来,逻辑更复杂,计算更密集,但比Eigenfaces更容易获得准确的效果。 # LBPH(Local Binary Pattern Histogram) 在一个非常好的层次上,检测到的人脸被分成小单元,并与模型中的相应单元进行比较,并为每个区域的匹配值生成一个直方图。由于该方法的灵活性,它是唯一一种不同形状和大小的人脸识别算法。50分以内的置信分相对可靠 # model = cv2.face.EigenFaceRecognizer_create() # 创建识别模型并使用它EigenFace算法识别,Confidence4000分以下可靠 # model = cv2.face.LBPHFaceRecognizer_create() # 创建识别模型并使用它LBPHFace算法识别,Confidence50分以下是可靠的 # model = cv2.face.FisherFaceRecognizer_create() # 创建识别模型并使用它FisherFace算法识别,Confidence4000分以下可靠 # OpenCV 通过函数 cv2.face.EigenFaceRecognizer_create()生成特征脸识别器实例模型, # 然后应用 cv2.face_FaceRecognizer.train()函数完成训练, # 最后用cv2.face_FaceRecognizer.predict()函数完成人脸识别。 # 1. 函数cv2.face.EigenFaceRecognizer_create() # retval = cv2.face.EigenFaceRecognizer_create( [, num_components[, threshold]] ) # 其中: # num_components:在 PCA 要保留的重量数。(一般来说, 80 一个重量就够了。(一般来说, 80 一个重量就够了。 # threshold:人脸识别使用的阈值。 # 2. 函数cv2.face_FaceRecognizer.train() # 函数 cv2.face_FaceRecognizer.train()每个参考图像 EigenFaces 计算,得到一个向量。每张脸都是整个向量集中的一个点。 # 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 到 20 000 之间, 只要低于 5000, 都被认为是相当可靠的识别结果。 # 注意,这个范围与 LBPH 信心评分的范围不同。 # 下载官方的ORL人脸数据库 # 加载图像,读取ORL人脸数据库,准备训练数据 def loadimageface(data): # 加载图片数据进行训练 # params:data:目录中的训练数据,要求图片尺寸相同 #ret: # images:[m,height,width] m为样本数,height为高,width为宽 # names:名字的集合 # labels:标签 images = [] names = [] labels = [] face_casecade = cv2.CascadeClassifier('C:\\Python\\Python37\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_default.xml') # haarcascade_frontalface_alt_tree 21 # [ 3 9 13 13 13 13 15 17 24 31 33 34 34 34 35 35 36 37 37 37 37] # haarcascade_frontalface_alt 222 # [ 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 # 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 6 6 6 6 6 7 7 7 7 # 8 8 9 9 9 9 9 9 9 9 9 9 10 10 10 12 12 12 12 12 12 12 12 12 # 13 13 13 13 13 13 13 13 13 13 14 15 15 15 15 15 15 16 16 16 16 16 17 17 # 17 17 18 18 18 18 18 18 19 20 20 21 21 21 21 21 21 21 21 22 22 22 22 22 # 22 23 23 23 23 23 23 23 23 24 24 24 24 24 25 25 26 26 26 26 26 26 26 26 # 29 29 29 29 29 30 30 30 30 30 31 31 31 31 31 31 31 31 31 31 32 32 32 33 # 33 33 33 33 34 34 34 34 34 34 34 35 35 35 35 35 36 36 36 36 36 36 36 36 # 36 37 37 37 37 37 37 37 37 37 37 38 38 38 38 38 38 38 38 38 39 39 39 39 # 39 39 39 39 39] # haarcascade_frontalface_alt2 231 # [ 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 # 3 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 6 6 7 7 7 7 7 # 7 8 8 9 9 9 9 9 9 9 9 9 9 10 10 10 12 12 12 12 12 12 12 12 # 12 13 13 13 13 13 13 13 13 13 13 15 15 15 15 15 15 15 15 15 16 16 16 16 # 16 16 16 16 17 17 17 17 17 18 18 18 18 18 19 19 19 20 20 21 21 21 21 21 # 21 21 21 22 22 22 22 22 22 22 23 23 23 23 23 23 23 23 23 24 24 24 24 24 # 25 25 26 26 26 26 26 28 29 29 29 29 29 30 30 30 30 31 31 31 31 31 31 31
# 31 31 31 32 32 32 32 32 32 33 33 33 33 33 34 34 34 34 34 34 34 35 35 35
# 35 35 36 36 36 36 36 36 36 36 36 37 37 37 37 37 37 37 37 37 37 38 38 38
# 38 38 38 38 38 39 39 39 39 39 39 39 39 39]
# haarcascade_frontalface_default 264
# [ 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3
# 3 3 3 3 3 3 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6
# 6 6 6 6 6 7 7 7 7 7 7 7 8 8 9 9 9 9 9 9 9 9 9 9
# 10 10 10 10 10 12 12 12 12 12 12 12 12 12 12 13 13 13 13 13 13 13 13 13
# 13 14 14 14 14 14 14 14 15 15 15 15 15 15 16 16 16 16 16 16 16 16 16 17
# 17 17 17 17 18 18 18 18 18 19 19 19 19 19 19 19 19 19 19 20 20 20 20 20
# 20 21 21 21 21 21 21 22 22 22 22 23 23 23 23 23 23 23 24 24 24 24 24 25
# 25 25 25 26 26 26 26 26 26 26 26 26 29 29 29 29 29 29 29 30 30 30 30 30
# 30 30 31 31 31 31 31 31 31 31 31 32 32 32 32 33 33 33 33 33 33 33 33 34
# 34 34 34 34 34 34 35 35 35 35 35 36 36 36 36 36 36 36 36 36 37 37 37 37
# 37 37 37 37 37 37 38 38 38 38 38 38 38 38 38 39 39 39 39 39 39 39 39]
label = 0
# 遍历当前文件夹
for subdir in os.listdir(data):
print('processing ',subdir)
# 构造路径全链路
subpath = os.path.join(data, subdir)
# 如果是否文件夹
if os.path.isdir(subpath):
# 每个文件夹代表一个人,也就是构造人的姓名
names.append(subdir)
# 遍历文件夹中的图片文件
for filename in os.listdir(subpath):
imgpath = os.path.join(subpath, filename)
# 读取图片,并转换为灰度图片
# 灰度图片用于进行训练
# 构造图片和标签关系
img = cv2.imread(imgpath, cv2.IMREAD_COLOR)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_casecade.detectMultiScale(gray_img, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
if (len(faces) > 0):
(x, y, w, h) = faces[0]
# 只返回图像的正面部分
images.append(gray_img[y:y + w, x:x + h])
labels.append(label)
cv2.imshow('img', img)
label += 1
# 将图片转换为易于操作的ndarray形式
images = np.asarray(images)
# 将标签转为numpy格式
labels = np.asarray(labels)
return images, labels, names
dif __name__ == '__main__':
trainimage = 'C:\\Python\\Pycharm\\docxprocess\\picture\\ORL\\'
predictdata='C:\\Python\\Pycharm\\docxprocess\\picture\\predict\\'
face_cascade = cv2.CascadeClassifier('C:\\Python\\Python37\\Lib\\site-packages\\cv2\\data\\haarcascade_frontalface_alt2.xml')
X, y, names = loadimageface(trainimage)
model = cv2.face.LBPHFaceRecognizer_create()
model.train(X, y)
for filename in os.listdir(predictdata):
imgpath = os.path.join(predictdata, filename)
if os.path.isfile(imgpath):pass
img = cv2.imread(imgpath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
roi_gray = gray[y:y + h, x:x + w]
roi_color = img[y:y + h, x:x + w]
roi_gray = cv2.resize(roi_gray, (92, 112), interpolation=cv2.INTER_LINEAR)
params = model.predict(roi_gray)
print('Label:%s,confidence:%.2f' % (params[0], params[1]))
print('人员姓名:',names[params[0]])
cv2.putText(img, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
识别结果如下,前两张随机挑选的照片置信度在65-69之间,识别输出是准确无误的,但刘德华这张照片就有点无厘头了。
# Label:3,confidence:65.66
# 识别照片: s12
# Label:23,confidence:68.60
# 识别照片: s30
# Label:26,confidence:114.96
# 识别照片: s33
最后,谢谢关注,谢谢支持!