训练流程:
照片命名格式:学号-1/学号-2+.jpg
import cv2 as cv
import os
from PIL import Image
import numpy as np# 根据jpgForTrainer文件夹中的图片进行训练,随后的训练数据保存到trainer/trainer.ymldef getImageAndLabel(url):# 储存人脸数据faces_msg = []name = []# 保存图片信息imagePaths = [os.path.join(url, f) for f in os.listdir(url)]# 加载分类器detector = cv.CascadeClassifier('../haarcascade_frontalface_alt2.xml')# 遍历图片for pict in imagePaths:fileImg = Image.open(pict).convert('L') # 打开灰度图像# 图片向量化imgNumpy = np.array(fileImg, 'uint8')face = detector.detectMultiScale(imgNumpy, 1.1, 5) # 提取图片脸部特征值# 提取图片的学号ids = int(os.path.split(pict)[1].split('-')[0])flag = Falsefor x, y, w, h in face:# 保存脸部数据flag = Truename.append(ids)faces_msg.append(imgNumpy[y:y + h, x:x + w]) # 保存脸部数据if flag:print(f'DEBUG:捕捉到学号为{ids}的人脸,')print('DEBUG')print('id', name)print('face', faces_msg)return faces_msg, nameif __name__ == '__main__':path = "../jpgForTrainer/"# 获取人脸特征和姓名faces, id = getImageAndLabel(path)# 加载识别器recognize = cv.face.LBPHFaceRecognizer_create()recognize.train(faces, np.array(id))# 保存文件recognize.write('../trainer/trainer.yml')
步骤:
# 测试人脸识别
import cv2 as cv
import os# 加载训练数据文件
data = cv.face.LBPHFaceRecognizer_create()
data.read('../trainer/trainer.yml')# 错误数目
fault = 0path = '../jpgForTest'# 根据jpgForTest里面的文件来进行识别测试# 识别模块
def discern(_img):ret = []gray = cv.cvtColor(_img, cv.COLOR_BGR2GRAY)# 加载分类器detector = cv.CascadeClassifier('../haarcascade_frontalface_alt2.xml')face_data = detector.detectMultiScale(gray, 1.1, 5)resize = _imgflag = Falsefor x, y, w, h in face_data:flag = Truecv.rectangle(_img, (x, y,), (x + w, y + h), color=(0, 0, 255), thickness=1)# 人脸识别s_id, confidence = data.predict(gray[y:y + h, x:x + w])resize = cv.resize(_img, dsize=(700, 600))if confidence > 25:cv.putText(resize, 'UnKnow', (5, 50), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)else:print('标签id:', s_id, '置信评分:', confidence)cv.putText(resize, str(s_id), (5, 50), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)ret.append(s_id)if not flag:# 没检测到人脸resize = cv.resize(_img, dsize=(700, 600))cv.putText(resize, 'Not Find Face', (5, 50), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)# 压缩图片输出cv.imshow('result', resize)while True:get = cv.waitKey(1000)if ord(' ') == get or get == -1:breakreturn ret# # 获取训练人的学号,以此来判断陌生人脸是否识别成功
# def getMessage():
# target = os.listdir('../jpgForTrainer')
# msg = []
# for Str in target:
# tmp = Str.split('-')[0]
# if tmp not in msg:
# msg.append(tmp)
# return msgif __name__ == '__main__':files = os.listdir(path) # 得到文件夹下的所有文件名称size = len(files)for file in files: # 遍历文件夹stu_id = file.split('.')[0]size += 1print(path + "/" + file + "正在识别")img = cv.imread(path + '/' + file)ret = discern(img)if len(ret) == 0:fault += 1print(f'识别错误应该学号为{stu_id},识别学号为{ret}')else:for item in ret:if str(item) not in str(stu_id):fault += 1print(f'识别错误应该学号为{stu_id},识别学号为{ret}')print(f'DEBUG:识别失败的个数{fault},测试识别总数{size}')print(f'测试成功概率{((size - fault) / size) * 100}%')cv.destroyAllWindows()
需要注意的是:这个实验使用的haarcascade_frontalface_alt2.xml文件,是OpenCV自带的人脸图像提取算法,需根据实际路径选取
代码中的置信评分越小,越可靠。
参考资料:
一天搞定人脸识别项目!
运行结果: