基于 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)修改姓名学号

b1b703bcd5554781bb662f627e7c9edc.png

(2)运行capture_face.py 

7e27703126b44a5c98b9e695b9697b0e.png

(3)采集人脸图像

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

f0796c27cfbc49baaa295e4b40de90b0.png

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

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

6330592996e44bb48b2ce6d5ef43a3f0.png

 

第二步:训练模型

使用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 就是训练好的人脸模型

0a1c059b15234ed5a5eae76b6e15af37.png

 

第三步:识别签到

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

(1)建立签到表

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

9bcac73100284a0ca31b61d305568032.png

 注意:

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

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

e7fcebcf2eba44d884912586906ba40b.png

07eadff197cd47ad9b57aa0e917e3599.png

0c5529f58b7945178cf69ac04ebbc681.png

 (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)]  # 得到预测学号在excel表格中所在的行数(注:index的值是从0开始的,index=3表示在excel表格中的第4行)
                # 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)  # 添加字幕

    cv2.putText(frame, 'please "esc" to quit ', (10, 20), font, 0.8, (0, 255, 255), 2)  # 在窗口上添加文字,参数依次表示:图像、要添加的文字、文字的位置、字体、字体大小、颜色、粗细
    cv2.imshow("picture from a cammre", frame)  # 打开窗口的名称
    if flag > 5:
        sign_name(index[0], name)
        print('签到成功')
        break
    if time.time()-start_time > duration:  # 如果超时,则签到失败
        print('签到失败!')
        break
    if kk == 27:  # 如果退出
        print('程序被终止,请重新签到!')
        break

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

82f1d64ce2134ee880788190de60d2ba.png

(3)查看签到结果

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

f9aef81e1d044d98b920558254338e7e.png

 

第四步:设计GUI

 

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

# 第四步:设计GUI

# 1. 导入第三方库
import os
import tkinter as tk

# 2. 创建屏幕窗口
windows = tk.Tk()  # 创建windows的窗口
windows.title('<计算机视觉>课程案例')  # 窗口名称
windows.geometry('310x500+1000+100')  # 窗口大小(注:x是小写字母x,不能写乘号)

# 3. 定义功能函数
def function1():
    os.system('python capture_face.py')  # 执行python capture_face.py命令
def function2():
    os.system('python train.py')  # 执行python train.py命令
def function3():
    os.system('python sign_in.py')  # 执行python sign_in.py命令
def function4():
    os.startfile(os.getcwd()+'/签到表1.xls')  # 打开'签到表1.xls'文件
def function5():
    os.startfile(os.getcwd()+'/基于OpenCV的人脸识别说明文档.docx')  # 打开说明文档
def function6():
    windows.destroy()

# 4. 创建标签及按钮
tk.Label(windows, text='人脸识别上课签到系统', font=('黑体', 20, 'bold'), fg='white',
         bg='maroon', height=2).grid(padx=7, pady=5)
tk.Button(windows,text='采 集 人 脸 图 像', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function1).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='训 练 模 型', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function2).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='识 别 签 到', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function3).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='查 看 签 到 表', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function4).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='查看项目说明文档', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function5).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='  退      出  ', font=('黑体', 20, 'bold'), fg='white',
         bg='#0D47A1', command=function6).grid(padx=7, pady=5, sticky=tk.W+tk.E)
tk.Button(windows,text='学号:2021520542   姓名:蔡徐坤', font=('仿宋', 20, 'bold'), fg='black',
         bg='white').grid(padx=20, pady=50, sticky=tk.W+tk.E)

# 5. 运行
windows.mainloop()

4a8a8174d7ad4a188fe53f81bf3f92c3.png

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年11月9日
下一篇 2023年11月9日

相关推荐