基于OpenCV-Python的人脸签到系统

一、流程:
人脸数据采集→模型训练→建立一个maxmember.csv表格用来存放人员的ID、打卡的名称,识别时显示的名称→启动人脸检测打卡→自动生成CSV表格用来存放打卡人的名称与时间。
基于OpenCV-Python的人脸签到系统_第1张图片

二代码:

import cv2
import os
import numpy as np
from PIL import Image
import datetime
import csv
# 调用笔记本内置摄像头,所以参数为0,如果有其他的摄像头可以调整参数为1,2
Path = r"G:/haarcascade_frontalface_default.xml"
face_detector = cv2.CascadeClassifier(Path)
names = []
zh_name = []
############################################################
# 建立一个maxmember.csv表格
# 用来存放人员的ID、姓名
#UTF-8:是实现Unicode的方法
#把8位以内能表示的Unicode编码用一个字节表示
############################################################
with open("maxmember.csv","r",encoding='UTF-8') as csv_file:
    reader = csv.reader(csv_file)
    for item in reader:
        # print(item)
        names.append(item[2])            #边框显示的名称
        zh_name.append(item[1])          #打卡人员名称
    # print (zh_name)
def data_collection():
    cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
    #cv2.CAP_DSHOW是作为open调用的一部分传递标志,还有许多其它的参数,而这个CAP_DSHOW是微软特有的。
    face_id = input('\n 请输入你的ID:')

    print('\n 数据初始化中,请直视摄像机录入数据....')

    count = 0

    while True:

        # 从摄像头读取图片

        sucess, img = cap.read()

        # 转为灰度图片

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        fi=img/255
        gamma=0.5
        o=np.power(fi,gamma)
        # 检测人脸

        faces = face_detector.detectMultiScale(gray, 1.3, 5)

        for (x, y, w, h) in faces:
            cv2.rectangle(o, (x, y), (x + w, y + w), (255, 0, 0))
            count += 1
            # 保存图像
            cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
            cv2.imshow('data collection', o)

        # 保持画面的持续。

        k = cv2.waitKey(1)
        if k == 27:  # 通过esc键退出摄像
            break
        elif count >= 20:  # 得到n个样本后退出摄像
            break
    cap.release()
    cv2.destroyAllWindows()
def face_training():
    # 人脸数据路径
    path = './dataset'

    recognizer = cv2.face.LBPHFaceRecognizer_create()

    def getImagesAndLabels(path):
        imagePaths = [os.path.join(path, f) for f in os.listdir(path)]  # join函数将多个路径组合后返回
        faceSamples = []
        ids = []
        for imagePath in imagePaths:
            PIL_img = Image.open(imagePath).convert('L')  # convert it to grayscale
            img_numpy = np.array(PIL_img, 'uint8')
            id = int(os.path.split(imagePath)[-1].split(".")[1])
            faces = face_detector.detectMultiScale(img_numpy)
            for (x, y, w, h) in faces:
                faceSamples.append(img_numpy[y:y + h, x: x + w])
                ids.append(id)
        return faceSamples, ids

    print('数据训练中')
    faces, ids = getImagesAndLabels(path)
    recognizer.train(faces, np.array(ids))

    recognizer.write(r'trainer\trainer.yml')
    # print("{0} faces trained. Exiting Program".format(len(np.unique(ids))))
    print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))

###############
#采用LBPH算法
###############

def face_ientification():
    cap = cv2.VideoCapture(0)
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.read('trainer/trainer.yml')
    faceCascade = cv2.CascadeClassifier(Path)
    font = cv2.FONT_HERSHEY_SIMPLEX

    idnum = 0
    global namess
    cam = cv2.VideoCapture(0)
    #设置大小
    minW = 0.1 * cam.get(3)
    minH = 0.1 * cam.get(4)

    while True:
        ret, img = cam.read()
        #图像灰度处理
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        #----------------------
        #采用伽玛变换,提高图像清晰度
        #----------------------
        fi=img/255
        gamma=0.5
        o=np.power(fi,gamma)
        # 将人脸用vector保存各个人脸的坐标、大小(用矩形表示)
        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.2,#表示在前后两次相继的扫描中,搜索窗口的比例系数
            minNeighbors=5,#表示构成检测目标的相邻矩形的最小个数(默认为3个)
            minSize=(int(minW), int(minH))#minSize和maxSize用来限制得到的目标区域的范围
        )

        for (x, y, w, h) in faces:
            cv2.rectangle(o, (x, y), (x + w, y + h), (11, 255, 255), 2)
            idnum, confidence = recognizer.predict(gray[y:y + h, x:x + w])

            if ((confidence < 100)):
                namess = names[idnum]
                confidence = "{0}%".format(round(100 - confidence))
            else:
                namess = "unknown"
                confidence = "{0}%".format(round(100 - confidence))

            cv2.putText(o, str(namess), (x + 5, y - 5), font, 1, (255, 255, 255), 1)
            cv2.putText(o, str(confidence), (x + 5, y + h - 5), font, 1, (255, 255, 0), 1)#输出置信度

        cv2.imshow(u'Identification punch', o)
        k = cv2.waitKey(1)
        if k == 13:              #回车键的ASCLL(13)
            theTime = datetime.datetime.now()

            # print(zh_name[idnum])
            strings = [str(zh_name[idnum]),str(theTime)]
            print(strings)
            with open("log.csv", "a",newline="") as csvFile:  #将获取到的打卡时间重新做一个表格
                writer = csv.writer(csvFile)
                writer.writerow([str(zh_name[idnum]),str(theTime)])
        elif k==27:             #ESC  END
            cap.release()
            cv2.destroyAllWindows()
            break
while True:

    a = int(input("输入1,进行人脸收集;输入2,进行人脸模型训练;输入3,进行识别打卡;输入4,退出系统:"))
    if a==1:
        data_collection()
    if a==2:
        face_training()
    if a==3:
        face_ientification()
    if a==4:

        cv2.destroyAllWindows()
        break

三效果展示:
在这里插入图片描述ID:4
基于OpenCV-Python的人脸签到系统_第2张图片
采集到人脸时,边框显示我的名字
打卡时也会显示打卡人的名称以及打卡的时间maxmember.csv表格:

基于OpenCV-Python的人脸签到系统_第3张图片第一列为采集人脸数据的ID好,比如我采集自己的人脸时我的ID为4,第二列为打卡时显示打卡人的名称,第三列为人脸识别后对人人的名称。

生成的csv用来保存打卡人员的名称与时间:
在这里插入图片描述

你可能感兴趣的:(OpenCV学习)