Python-中北大学人工智能OpenCV人脸识别(根据图片训练数据,根据训练好的数据识别人脸)

1. 根据训练照片训练数据模型

在这里插入图片描述
训练流程:

  1. 读取文件夹下的所有文件,使用PIL 库中的Image方法打开图片,并将其转化为灰度图片。
  2. 加载人脸数据分类器,这里直接使用OpenCV库自带的(cv.CascadeClassifier(…))
  3. 使用numpy.array方法,让照片向量化。使用分类器detectMultiScale方法,提取图片脸部特征值。
  4. 将一个人的信息和脸部特征值写入到文件中,达到训练的目的

照片命名格式:学号-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')

2. 根据训练的数据文件,进行人脸识别

步骤:

  1. 将要识别的图片使用os模块,读取进来
  2. 使用cv2库(检测cv)cv.imread函数打开图片,调用人脸识别函数(自定义)进行识别,函数返回从训练数据里面查找的复合条件的学号,根据图片名称来判断识别是否准确
  3. 人脸识别函数中,使用data = cv.face.LBPHFaceRecognizer_create(),data.read(‘…/trainer/trainer.yml’)来加载训练好的数据。
  4. 使用data.predict函数来预测准确性,准确性在25以内的就可以认为识别成功,将学号写到图片上调用cv.imshow函数进行输出。可以使用cv.resize函数对图片进行缩放后再将识别信息写到图片上。
  5. 最后统计识别学号和照片名称学号对应的比例来计算识别成功率即可。
# 测试人脸识别
# 测试人脸识别
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自带的人脸图像提取算法,需根据实际路径选取

代码中的置信评分越小,越可靠。

参考资料
一天搞定人脸识别项目!

运行结果:
在这里插入图片描述
这个是我用训练集做的,准确度很高,经过测试。实际准确度在40%左右,比较低

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值