基于 OpenCV + Python 的人脸识别上课签到系统
目录
第三步:开启摄像头实时跟踪人脸,获取人脸特征信息,然后将获取的人脸特征信息与第二步建立的特征库进行比对,将识别的信息在画面中呈现,并记录在Excel文档中。
使用本项目前请确保已经安装好了pycharm、python以及所用到的第三方库
项目用到的第三方库:opencv-python、opencv-contrib-python、pillow、tk、xlrd、xlwt、xlutils。
当今社会,科学技术呈现着井喷式的发展情况,新理论的不断提出及新技术的实时应用,给人们的生活带来了日新月异的变化。在这些新技术新应用中,物联网、人工智能、大数据等名词被人们纷纷提起,产业领域的智能化产品层出不穷,其中人脸识别就是一个典型应用。
本项目构建一个基于OpenCV + Python的人脸识别上课签到系统。人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能。人脸检测是在一张图片中把人脸定位出来,完成的是搜寻的功能。
OpenCV提供了三种人脸识别方法,分别是LBPH方法、EigenFishfaces方法、Fisherfaces方法。本项目采用LBPH方法,分四步实现。
首先建立一个新的项目文件夹:基于 OpenCV + Python 的人脸识别上课签到系统
使用pycharm打开该项目
第一步:通过调用摄像头进行人脸图像采集,建立人脸图像库。
项目目录下建立 python 文件 capture_face.py
# 第一步:通过调用摄像头进行人脸图像采集,建立人脸图像库
# 1.导入第三方库
import cv2
import os
import xlrd
# 2.初始化变量
font = cv2.FONT_HERSHEY_SIMPLEX
classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') # CascadeClassifier是级联分类器,对输入的图片分类,判断图像内是否有无人脸
if not os.path.exists('dataset'): # 如果没有子目录,则建立dataset子目录
os.mkdir('dataset')
count = 0
# 3.输入学号
student_ID = 20220811
# 4.采集图像
capture = cv2.VideoCapture(0) # 打开电脑摄像头
while capture.isOpened():
kk = cv2.waitKey(1)
_, frame = capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 彩色图像转灰色图片
faces = classifier.detectMultiScale(gray, 1.3, 5) # 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)
cv2.putText(frame, 'please "s" to save a picture ', (200, 450), font, 0.8, (0, 255, 255), 2)
if kk == ord('s'):
cv2.imwrite('dataset/shizhenxiang,'+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()
运行程序:
按 "s" 键保存人脸图像(每人采集15张人脸图像差不多,这里只采集了6张)
按 "esc" 键关闭摄像头
采集到的人脸图像如下:
第二步:使用OpenCV中LBPH(Local Binary Patterns Histograms,局部二进制编码)算法建立人脸数据模型,对人脸图像库中的人脸图像提取特征信息(LBPH),并训练成模型,存储起来形成特征库。
项目目录下建立 python 文件 train.py
# 第二步:使用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('trainer.yml')
print('模型已保存')
运行程序开始训练模型
第三步:开启摄像头实时跟踪人脸,获取人脸特征信息,然后将获取的人脸特征信息与第二步建立的特征库进行比对,将识别的信息在画面中呈现,并记录在Excel文档中。
项目目录下建立 python 文件 sign_in.py
# 第三步:开启摄像头实时跟踪人脸,获取人脸特征信息,然后将获取的人脸特征信息与第二步建立的特征库进行比对,将识别的信息在画面中呈现,并记录在Excel文档中。
# 1. 导入第三方库
import xlrd, xlwt
from xlutils.copy import copy
from datetime import datetime
import cv2, 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')
style1 = xlwt.easyxf('font:height 240,bOld on,color_index blue')
workbook = xlrd.open_workbook('考勤记录表.xls')
newbook = copy(workbook)
newsheet = newbook.get_sheet(0)
newsheet.write(idx, 4, datetime.now(), style0)
newsheet.write(idx, 3, name, style1)
newsheet.col(0).width = 256 * 6
newsheet.col(1).width = 256 * 12
newsheet.col(2).width = 256 * 10
newsheet.col(3).width = 256 * 12
newsheet.col(4).width = 256 * 15
newbook.save('考勤记录表1.xls')
# sign_name(32, '史珍香')
# 3. 导入模款,初始化变量
classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
recognizer_create = cv2.face_LBPHFaceRecognizer.create()
recognizer_create.read('trainer.yml') # 读取训练数据好的模型
start_time = time.time()
duration = 25 # 持续时间
ID = 'Unkonw'
font = cv2.FONT_HERSHEY_SIMPLEX
# 4. 导入应到学生名单
workbook = xlrd.open_workbook('考勤记录表.xls')
worksheet = workbook.sheet_by_index(0)
stu_num = worksheet.col_values(1)
stu_name = worksheet.col_values(2)
# 5.识别签到
capture = cv2.VideoCapture(0) # 调用摄像头
while capture.isOpened():
kk = cv2.waitKey(1)
_, frame = capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
faces = classifier.detectMultiScale(gray, 1.3, 5)
if len(faces) != 0:
for x, y, w, h in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)
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)]
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()
运行程序进行签到
第四步:设计GUI
项目目录下建立 python 文件 GUI.py
# 第四步:编写简单的用户界面
# 1. 导入第三方库
import os
import tkinter as tk
# 2. 创建屏幕窗口
windows = tk.Tk() # 创建windows窗口
windows.title('<人脸识别上课签到系统') # 窗口名称
windows.geometry('310x500+1000+100') # 窗口大小, 注意:x是小写字母,不能写乘号
# 3. 定义功能函数
def function1():
os.system('python capture_face.py')
def function2():
os.system('python train.py')
def function3():
os.system('python sign_in.py')
def function4():
os.startfile(os.getcwd()+'/考勤记录表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='学号:20220811 姓名:史珍香', font=('仿宋', 20, 'bold'), fg='black',
bg='white').grid(padx=20, pady=50, sticky=tk.W+tk.E)
# 5. 运行
windows.mainloop()
运行程序: