照片命名格式:学号-1/学号-2+.jpg
import cv2 as cv
import os
from PIL import Image
import numpy as np
# 根据jpgForTrainer文件夹中的图片进行训练,随后的训练数据保存到trainer/trainer.yml
def 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 = False
for x, y, w, h in face:
# 保存脸部数据
flag = True
name.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, name
if __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 = 0
path = '../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 = _img
flag = False
for x, y, w, h in face_data:
flag = True
cv.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 > 80:
# cv.putText(resize, 'UnKnow', (10, 50), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
pass
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:
break
return 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 msg
if __name__ == '__main__':
files = os.listdir(path) # 得到文件夹下的所有文件名称
size = len(files)
for file in files: # 遍历文件夹
stu_id = file.split('.')[0]
print('-------\n' + path + "/" + file + "正在识别")
img = cv.imread(path + '/' + file)
ret = discern(img)
if len(ret) == 0:
fault += 1
print(f'识别错误应该学号为{stu_id},识别学号为UnKnow')
else:
for item in ret:
if str(item) not in str(stu_id):
fault += 1
print(f'识别错误应该学号为{stu_id},识别学号为{ret}')
print('\n----------\n')
print(f'DEBUG:识别失败的个数{fault},测试识别总数{size}')
print(f'测试成功概率{((size - fault) / size) * 100}%')
cv.destroyAllWindows()
需要注意的是:这个实验使用的haarcascade_frontalface_alt2.xml文件,是OpenCV自带的人脸图像提取算法,需根据实际路径选取
代码中的置信评分越小,越可靠。
参考资料:
一天搞定人脸识别项目!