这里打算实现一个人脸考勤机,本篇主要实现一个label和人脸的对应。
主要采取的方法为hog人脸框选+cv2.face.LBPHFaceRecognizer_create()分类器进行训练。
(采用传统的机器学习的方法,这种方法弊端其实还是很明显的,精度不够理想,后面会有结果的展示,后续会更新深度学习的实现)
整个步骤如下:
# 步骤 # 1、图片数据预处理 # 2、加载模型 # 3、训练模型 # 4、预测图片 # 5、评估测试数据集 # 6、保存模型 # 7、调用加载模型
首先进行图像的预处理,因为hog检测只能对传入的灰度图进行检测,所以要对图像进行预处理,然后提取和图像对应的标签,这里我直接定义了一个函数。
这里说明一下,因为笔者用的数据集为gif格式,所以读取的操作采用的cv2.VideoCapture的视频读取方法。
具体操作如下:
from sklearn.metrics import accuracy_score #准确率的一个判断
# 获取融合矩阵
from sklearn.metrics import confusion_matrix
import cv2
import glob
import numpy as np
import dlib
#构造hog人脸检测器
hog_face_detetor = dlib.get_frontal_face_detector()
def getFaceImgLabel(fileName):
#图像预处理
cap = cv2.VideoCapture(fileName)
ret,img = cap.read()
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#检测人脸
detections = hog_face_detetor( img, 1 )
if len( detections ) > 0:
x = detections[0].left()
y = detections[0].top()
r = detections[0].right()
b = detections[0].bottom()
# 截取人脸
img_crop = img[y:b, x:r]
# 缩放解决冲突
img_crop = cv2.resize( img_crop, (120, 120) )
# 获取人脸labelid,int 用于取消0
#split分割,以前面为分割单元
label_id = int( fileName.split( '/' )[-1].split( '.' )[0].split( 'subject' )[-1] )
# 返回值
return img_crop, label_id
else:
return None, -1
定义完图像的预处理和标签的提取函数以后,下面就要读取数据提取对应标签。
具体代码如下:
file_list = glob.glob( './yalefaces/train/*' )
# 构造两个空列表
img_list = []
label_list = []
for train_file in file_list:
# 获取每一张图片的对应信息
img, label = getFaceImgLabel( train_file )
# 过滤数据
if label != -1:
img_list.append( img )
label_list.append( label )
下面就要用数据进行分类器的训练:
分类器的用法是:先声明,然后训练/调用。
首先构造分类器:
#构造分类器
face_cls = cv2.face.LBPHFaceRecognizer_create()
训练:
# 训练
face_cls.train(img_list,np.array(label_list))
下面要进行模型的评估:
主要使用了klearn.metrics里面的accuracy函数。
file_list =glob.glob('./yalefaces/test/*')
true_list = []
predict_list = []
for test_file in file_list:
# 获取每一张图片的对应信息
img,label = getFaceImgLabel(test_file)
#过滤数据
if label != -1:
predict_id,distance = face_cls.predict(img)
predict_list.append(predict_id)
true_list.append(label)
print('准确率为:',accuracy_score(true_list,predict_list))
#获取融合矩阵
cm = confusion_matrix(true_list,predict_list)
print(cm)
下面有相关的模型的保存和调用,主要是靠model.save和model.read实现的,具体如下:
face_cls.save('./LBPH.yml')
#调用
new_cls = cv2.face.LBPHFaceRecognizer_create()
new_cls.read('./LBPH.yml')
这里是分类器cv2的一个保存方式,其他的训练好的model可以用下面这种方法。
from joblib import dump,load
dump(cls,'./models/poly.')
cls = load('./models/svc.joblib')
predictLabels = cls.predict(x_test)
最后展示一下最终的识别的结果,可以看到精度是70%多,作为人脸识别的话这个精度是远远不够的,这与我数据集不够多有关,但是也体现传统机器学习在精度上面的一些弊端。