基于 OpenCV + Python 的人脸识别上课签到系统

目录

前言

安装第三方库

第一步:采集人脸图像

(1)修改姓名学号

(2)运行capture_face.py

(3)采集人脸图像

(4)查看采集到的人脸图像

第二步:训练模型

第三步:识别签到

(1)建立签到表

(2)运行sign_in.py,进行签到

(3)查看签到结果

第四步:设计GUI

完整项目的百度网盘链接:https://pan.baidu.com/s/1P1UzTyNdcHxfJyFxl-MV-Q?pwd=ni7A,提取码:ni7A

前言

当今社会,科学技术呈现着井喷式的发展情况,新理论的不断提出及新技术的实时应用,给人们的生活带来了日新月异的变化。在这些新技术新应用中,物联网、人工智能、大数据等名词被人们纷纷提起,产业领域的智能化产品层出不穷,其中人脸识别就是一个典型应用。

本项目构建一个基于OpenCV + Python的人脸识别上课签到系统。人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能。人脸检测是在一张图片中把人脸定位出来,完成的是搜寻的功能。

OpenCV提供了三种人脸识别方法,分别是LBPH方法、EigenFishfaces方法、Fisherfaces方法。本项目采用LBPH方法,分四步实现。

安装第三方库

首先安装项目用到的第三方库:opencv-python、opencv-contrib-python、pillow、tk、xlrd、xlwt、xlutils

安装方式:在当前python解释器下,pycharm终端运行:

pip install 库名称

第一步:采集人脸图像

capture_face.py

通过调用摄像头进行人脸图像采集,建立人脸图像库

第一步:采集人脸图像

1.导入第三方库
import cv2
import os
import xlrd

2.初始化变量
font = cv2.FONT_HERSHEY_SIMPLEX    # 定义字体,使用opencv中的FONT_HERSHEY_SIMPLEX字体
classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')  # 导入人脸检测级联文件。CascadeClassifier是opencv中做人脸检测时的一个级联分类器,对输入的图片进行分类,判断图像内是否有无人脸
if not os.path.exists('dataset'):  # 判断项目目录中是否存在dataset文件(dataset中存放采集到的人脸图像)
    os.mkdir('dataset')  # 如果没有就新建立dataset文件夹
count = 0  # 人脸图像的初始数量

3.输入学号
student_ID = 2021520542

4.采集图像
capture = cv2.VideoCapture(0)  # 打开电脑的内置摄像头

while capture.isOpened():  # 当摄像头打开的时候
    kk = cv2.waitKey(1)    # 等待键盘的输入,1:表示延时1ms切换到下一帧图像
    _, frame = capture.read()   # 读取摄像头内容,返回两个参数
    gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)  # 将读取到的RGB图像转换为灰度图像
    faces = classifier.detectMultiScale(gray, 1.3, 5)  # 让classifier判断人脸,detectMultiScale函数可以检测出图像中的人脸,其中gray为要检测的灰度图像,1.3为每次图像尺寸减小的比例,5为minNeighbors
    if len(faces) != 0:  # 如果找到人脸
        # 框选人脸
        for x, y, w, h in faces:
            cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 255, 0), 2)  # 用矩形框框出人脸,xy为左上角的坐标,w为宽,h为高
            cv2.putText(frame, 'please "s" to save a picture ', (200, 450), font, 0.8, (0, 255, 255), 2)  # 在人脸图像上添加文字,参数依次表示:图像、要添加的文字、文字的位置、字体、字体大小、颜色、粗细
            if kk == ord('s'):  # ord(' ')将字符转化为对应的整数(ASCII码)
               cv2.imwrite('dataset/caixukun.'+str(student_ID)+'.'+str(count)+'.jpg', gray[y:y+h, x:x+w])  # 保存图像
               count += 1  # 成功框选人脸后,则样本数增加
               print('共采集了'+str(count)+'张图片')

    cv2.putText(frame, 'please "esc" to quit ', (10, 20), font, 0.8, (0, 255, 255), 2)  # 在窗口上添加文字,参数依次表示:图像、要添加的文字、文字的位置、字体、字体大小、颜色、粗细

    cv2.imshow("picture from a cammre", frame)  # 打开窗口的名称
    if kk == 27:
        print('共采集了' + str(student_ID) + '同学' + str(count) + '张图片')
        break

5.退出程序
capture.release()  # 释放变量
cv2.destroyAllWindows()  # 检查有无打开窗口,有的话关掉

(1)修改姓名学号

基于 OpenCV + Python 的人脸识别上课签到系统

(2)运行capture_face.py

基于 OpenCV + Python 的人脸识别上课签到系统

(3)采集人脸图像

按住 “s” 键保存人脸图像,按 “esc” 键关闭摄像头,结束人脸采集

基于 OpenCV + Python 的人脸识别上课签到系统

(4)查看采集到的人脸图像

采集到的人脸图像会自动保存在dataset文件夹中

基于 OpenCV + Python 的人脸识别上课签到系统

第二步:训练模型

使用OpenCV中LBPH(Local Binary Patterns Histograms,局部二进制编码)算法建立人脸数据模型,对人脸图像库中的人脸图像提取特征信息(LBPH),并训练成模型,存储起来形成特征库。

第二步:训练模型

1. 导入第三方库
import cv2
import os
from PIL import Image
import numpy as np

2. 加载特征提取模型
recognizer_create = cv2.face_LBPHFaceRecognizer.create()

3. 数据处理
def data_translate(path):
    face_data = []
    id_data = []
    file_list = [os.path.join(path, f) for f in os.listdir(path)]
    # print(file_list)
    for file in file_list:
        PIL_image = Image.open(file).convert("L")
        np_image = np.array(PIL_image, 'uint8')
        image_id = int(file.split('.')[1])
        # print(image_id)
        face_data.append(np_image)
        id_data.append(image_id)
    return face_data, id_data

4. 训练模型
Face, ID = data_translate('dataset')
recognizer_create.train(Face, np.array(ID))
print('训练完成')

5. 保存模型
recognizer_create.save('face_model.yml')
print('模型已保存')

运行train.py,开始训练模型,训练完成后会生成face_model.yml 文件,face_model.yml 就是训练好的人脸模型

基于 OpenCV + Python 的人脸识别上课签到系统

第三步:识别签到

开启摄像头实时跟踪人脸,获取人脸特征信息,然后将获取的人脸特征信息与第二步建立的特征库进行比对,将识别的信息在画面中呈现,并记录在Excel文档中。

(1)建立签到表

打开excel,新建文件,按如下的格式新建一个签到表

基于 OpenCV + Python 的人脸识别上课签到系统

注意:

  1. 建立签到表的时候,一定要将 单元格格式设置成文本,这就是为什么大家老是签到不成功的原因

  2. 保存签到表时,保存位置为 当前项目的目录文件夹,文件命名为 ” 签到表” 保存类型一定要选择 .xls格式

基于 OpenCV + Python 的人脸识别上课签到系统

基于 OpenCV + Python 的人脸识别上课签到系统

基于 OpenCV + Python 的人脸识别上课签到系统

(2)运行sign_in.py,进行签到

第三步:识别签到

1. 导入第三方库
import xlrd, xlwt
from xlutils.copy import copy
from datetime import datetime
import cv2
import time

2. 在考勤表签字
def sign_name(idx, name):
    style0 = xlwt.easyxf('font:height 240,bOld on,color_index red', num_format_str='DD:MM HH:MM')  # 样式0
    style1 = xlwt.easyxf('font:height 240,bOld on,color_index blue')  # 样式1
    workbook = xlrd.open_workbook('签到表.xls')  # 读取excel文件
    newbook = copy(workbook)  # 复制文件
    newsheet = newbook.get_sheet(0)  # 在源文件上追加
    newsheet.write(idx, 4, datetime.now(), style0)  # 第idx行,第4列,写入签到时间,样式为style0(注:代码中的行列是从0开始的)
    newsheet.write(idx, 3, name, style1)   # 第idx行,第3列,写入签到学生的名字,样式为style1((注:代码中的行列是从0开始的))

    # 设置列宽
    newsheet.col(0).width = 256 * 6  # 第0列的列宽为 256 * 6 (256为衡量单位,6表示6个字符宽度)
    newsheet.col(1).width = 256 * 12  # 第1列的列宽为 256 * 12 (256为衡量单位,12表示12个字符宽度)
    newsheet.col(2).width = 256 * 10  # 第2列的列宽为 256 * 10 (256为衡量单位,10表示10个字符宽度)
    newsheet.col(3).width = 256 * 12  # 第3列的列宽为 256 * 12 (256为衡量单位,12表示12个字符宽度)
    newsheet.col(4).width = 256 * 15  # 第4列的列宽为 256 * 15 (256为衡量单位,15表示15个字符宽度)
    newbook.save('签到表1.xls')

3. 导入模块,初始化变量
classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
recognizer_create = cv2.face.LBPHFaceRecognizer.create()
recognizer_create.read('face_model.yml')  # 读取训练好的模型
flag = 0  # 标记次数
start_time = time.time()  # 系统时间提取
duration = 25  # 持续时间
ID = 'Unkonw'
font = cv2.FONT_HERSHEY_SIMPLEX  # 定义字体,使用opencv中的FONT_HERSHEY_SIMPLEX字体

4. 导入应到学生名单
workbook = xlrd.open_workbook('签到表.xls')  # 导入考勤记录表
worksheet = workbook.sheet_by_index(0)  # 打开工作表
stu_num = worksheet.col_values(1)  # 提取工作表第1列,第1列为学生学号
stu_name = worksheet.col_values(2)  # 提取工作表第2列,第2列为学生名字

5.识别签到
capture = cv2.VideoCapture(0)  # 打开摄像头

while capture.isOpened():  # 当打开摄像头的时候
    kk = cv2.waitKey(1)  # 等待键盘的输入
    _, frame = capture.read()  # 读取摄像头内容
    gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)  # 将读取到的RGB图像转换为灰度图像
    faces = classifier.detectMultiScale(gray, 1.3, 5)  # 让classifier判断人脸,detectMultiScale函数可以检测出图像中的人脸
    if len(faces) != 0:  # 如果能找到人脸
        # 框选人脸
        for x, y, w, h in faces:
            cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)  # 用矩形框框出人脸,xy为左上角的坐标,w为宽,h为高
            roi_face = gray[y:y + h, x:x + w]
            label, conf = recognizer_create.predict(roi_face)  # 预测出的学号和可信度
            # print(label,conf)

            if conf < 60:
                index = [list for list, i in enumerate(stu_num) if i == str(label)]  # &#x5F97;&#x5230;&#x9884;&#x6D4B;&#x5B66;&#x53F7;&#x5728;excel&#x8868;&#x683C;&#x4E2D;&#x6240;&#x5728;&#x7684;&#x884C;&#x6570;&#xFF08;&#x6CE8;&#xFF1A;index&#x7684;&#x503C;&#x662F;&#x4ECE;0&#x5F00;&#x59CB;&#x7684;&#xFF0C;index=3&#x8868;&#x793A;&#x5728;excel&#x8868;&#x683C;&#x4E2D;&#x7684;&#x7B2C;4&#x884C;&#xFF09;
                # print(index)
                if index != []:
                    name = stu_name[index[0]]
                    ID = stu_name[index[0]]
                    flag += 1
                else:
                    ID = 'unknow'
        cv2.putText(frame, str(ID), (x, y-10), font, 0.8, (0, 0, 255), 2)  # &#x6DFB;&#x52A0;&#x5B57;&#x5E55;

    cv2.putText(frame, 'please "esc" to quit ', (10, 20), font, 0.8, (0, 255, 255), 2)  # &#x5728;&#x7A97;&#x53E3;&#x4E0A;&#x6DFB;&#x52A0;&#x6587;&#x5B57;&#xFF0C;&#x53C2;&#x6570;&#x4F9D;&#x6B21;&#x8868;&#x793A;&#xFF1A;&#x56FE;&#x50CF;&#x3001;&#x8981;&#x6DFB;&#x52A0;&#x7684;&#x6587;&#x5B57;&#x3001;&#x6587;&#x5B57;&#x7684;&#x4F4D;&#x7F6E;&#x3001;&#x5B57;&#x4F53;&#x3001;&#x5B57;&#x4F53;&#x5927;&#x5C0F;&#x3001;&#x989C;&#x8272;&#x3001;&#x7C97;&#x7EC6;
    cv2.imshow("picture from a cammre", frame)  # &#x6253;&#x5F00;&#x7A97;&#x53E3;&#x7684;&#x540D;&#x79F0;
    if flag > 5:
        sign_name(index[0], name)
        print('&#x7B7E;&#x5230;&#x6210;&#x529F;')
        break
    if time.time()-start_time > duration:  # &#x5982;&#x679C;&#x8D85;&#x65F6;&#xFF0C;&#x5219;&#x7B7E;&#x5230;&#x5931;&#x8D25;
        print('&#x7B7E;&#x5230;&#x5931;&#x8D25;&#xFF01;')
        break
    if kk == 27:  # &#x5982;&#x679C;&#x9000;&#x51FA;
        print('&#x7A0B;&#x5E8F;&#x88AB;&#x7EC8;&#x6B62;&#xFF0C;&#x8BF7;&#x91CD;&#x65B0;&#x7B7E;&#x5230;&#xFF01;')
        break

6.&#x9000;&#x51FA;&#x7A0B;&#x5E8F;
capture.release()  # &#x91CA;&#x653E;&#x53D8;&#x91CF;
cv2.destroyAllWindows()  # &#x68C0;&#x67E5;&#x6709;&#x65E0;&#x6253;&#x5F00;&#x7A97;&#x53E3;&#xFF0C;&#x6709;&#x7684;&#x8BDD;&#x5173;&#x6389;

基于 OpenCV + Python 的人脸识别上课签到系统

(3)查看签到结果

签到成功后项目目录生成 “签到表1.xls” 文件,双击打开即可查看签到结果

基于 OpenCV + Python 的人脸识别上课签到系统

第四步:设计GUI

运行GUI.py,查看用户界面

&#x7B2C;&#x56DB;&#x6B65;&#xFF1A;&#x8BBE;&#x8BA1;GUI

1. &#x5BFC;&#x5165;&#x7B2C;&#x4E09;&#x65B9;&#x5E93;
import os
import tkinter as tk

2. &#x521B;&#x5EFA;&#x5C4F;&#x5E55;&#x7A97;&#x53E3;
windows = tk.Tk()  # &#x521B;&#x5EFA;windows&#x7684;&#x7A97;&#x53E3;
windows.title('<计算机视觉>&#x8BFE;&#x7A0B;&#x6848;&#x4F8B;')  # &#x7A97;&#x53E3;&#x540D;&#x79F0;
windows.geometry('310x500+1000+100')  # &#x7A97;&#x53E3;&#x5927;&#x5C0F;&#xFF08;&#x6CE8;&#xFF1A;x&#x662F;&#x5C0F;&#x5199;&#x5B57;&#x6BCD;x&#xFF0C;&#x4E0D;&#x80FD;&#x5199;&#x4E58;&#x53F7;&#xFF09;

3. &#x5B9A;&#x4E49;&#x529F;&#x80FD;&#x51FD;&#x6570;
def function1():
    os.system('python capture_face.py')  # &#x6267;&#x884C;python capture_face.py&#x547D;&#x4EE4;
def function2():
    os.system('python train.py')  # &#x6267;&#x884C;python train.py&#x547D;&#x4EE4;
def function3():
    os.system('python sign_in.py')  # &#x6267;&#x884C;python sign_in.py&#x547D;&#x4EE4;
def function4():
    os.startfile(os.getcwd()+'/&#x7B7E;&#x5230;&#x8868;1.xls')  # &#x6253;&#x5F00;'&#x7B7E;&#x5230;&#x8868;1.xls'&#x6587;&#x4EF6;
def function5():
    os.startfile(os.getcwd()+'/&#x57FA;&#x4E8E;OpenCV&#x7684;&#x4EBA;&#x8138;&#x8BC6;&#x522B;&#x8BF4;&#x660E;&#x6587;&#x6863;.docx')  # &#x6253;&#x5F00;&#x8BF4;&#x660E;&#x6587;&#x6863;
def function6():
    windows.destroy()

4. &#x521B;&#x5EFA;&#x6807;&#x7B7E;&#x53CA;&#x6309;&#x94AE;
tk.Label(windows, text='&#x4EBA;&#x8138;&#x8BC6;&#x522B;&#x4E0A;&#x8BFE;&#x7B7E;&#x5230;&#x7CFB;&#x7EDF;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='maroon', height=2).grid(padx=7, pady=5)
tk.Button(windows,text='&#x91C7; &#x96C6; &#x4EBA; &#x8138; &#x56FE; &#x50CF;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function1).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='&#x8BAD; &#x7EC3; &#x6A21; &#x578B;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function2).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='&#x8BC6; &#x522B; &#x7B7E; &#x5230;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function3).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='&#x67E5; &#x770B; &#x7B7E; &#x5230; &#x8868;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function4).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='&#x67E5;&#x770B;&#x9879;&#x76EE;&#x8BF4;&#x660E;&#x6587;&#x6863;', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function5).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='  &#x9000;      &#x51FA;  ', font=('&#x9ED1;&#x4F53;', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function6).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='&#x5B66;&#x53F7;&#xFF1A;2021520542   &#x59D3;&#x540D;&#xFF1A;&#x8521;&#x5F90;&#x5764;', font=('&#x4EFF;&#x5B8B;', 20, 'bold'), fg='black',
         bg='white').grid(padx=20, pady=50, sticky=tk.W+tk.E)

5. &#x8FD0;&#x884C;
windows.mainloop()
</计算机视觉>

基于 OpenCV + Python 的人脸识别上课签到系统

Original: https://blog.csdn.net/qq_61290020/article/details/126130381
Author: wuxuhong0542
Title: 基于 OpenCV + Python 的人脸识别上课签到系统

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/637018/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球