2019-12-11 | UNLOCK

人脸识别签到系统(简易版)

人脸识别签到系统(软件院拓2班专用)

课程设计者:罗泽涛 17240244

功能简述

人脸识别签到应用程序,应用程序分为学生端和教师端。学生端为主,学生端主要能够看到教室的基本信息和课程信息,功能有人脸录入和人脸识别以及查看所有人签到情况。教师端为辅,教师端主要是开启签到和签到有效时间以及教室代签功能。

功能详情

  1. 学生端

    1. 显示教室基本信息和课程名称
    2. 教师是否开启签到
    3. 如果开启签到,显示剩余签到时间(超过时间就是未签到)。
    4. 人脸录入(输入学号和姓名,在数据库上匹配查询,如果信息一致,则进行录入,然后将录入的人脸存储在本地文件夹以[学号].jpg命名。如果存在则覆盖掉)。
    5. 人脸识别(判断是否开启签到,如果开启则进入识别系统,识别成功后多识别几张,如果是同一个人则真正地识别成功。那么就进行判断是否重复签到,如果没有重复,则签到,然后将【签到信息】上传到数据库)。
    6. 查看所有人的签到状态(读取数据库,把所有签到信息遍历出来)
    7. 热键唤醒出教师端(F8)
  2. 教师端

    1. 签到开关
    2. 设置有效时间(10min),输入一个数值
    3. 教师代签(输入学生的学号和姓名,以及签到状态)

视频展示

上传样本且签到
同学正常签到
多人正常签到
没有样本的情况
如果教师没有开启签到则不能签到(样本已删了)
如果过期则不能签到
教师代签

所涉及的技术

python、mysql

主要的Python库

mysql库、face_recognition库(人脸识别)、cv2库(openCV3)、tkinter库(图形化窗口)。

核心技术

(由于书上的方法识别率极低,所以参考了网上的方法)人脸识别是使用face_recognition库,这是世界上最简单的人脸识别库了。你可以通过Python引用或者命令行的形式使用它,来管理和识别人脸。该软件包使用dlib中最先进的人脸识别深度学习算法,使得识别准确率在《Labled Faces in the world》测试基准下达到了99.38%。它同时提供了一个叫face_recognition的命令行工具,以便你可以用命令行对一个文件夹中的图片进行识别操作。

数据库设计

checkTabel表

stuInfo表

软件流程

修改week运行程序——教师F8——进入签到管理——开启签到(数据库插入该周的所有学生)——可设置过期时间——学生点击人脸签到——签到成功——数据库签到状态修改——接着其他学生可以接着签到——如果人脸是未知人脸——进入人脸录入(判断该学生是否在数据库)——录入的时候需要按空格进行录入——录入出现绿框——按ESC退出录入——再进行签到。

核心代码(人脸识别)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import face_recognition
import cv2
import ostest
import time
import sqlHelper

def qiandao(week):
video_capture = cv2.VideoCapture(0)
# 将所有人脸数据 加到数组里
face_encodingsss = []

# 人脸数据对应的名字
face_namesss = []
# 将人脸数据全部加入

last_name = ""

faces = ostest.read_images("./img")
# print(faces)
# exit()
for i in range(len(faces)):
load_img = face_recognition.load_image_file("./img/" + faces[i])
# print("./img/" + faces[i])
# print(face_recognition.face_encodings(load_img)[0])
# exit()
load_face_encoding = face_recognition.face_encodings(load_img)[0]
face_encodingsss.append(load_face_encoding)
face_namesss.append(ostest.getStuID(faces[i]))

# 初始化一些变量
face_locations = [] # 当前获取到的人脸的未知 4个点top bottom left right
face_encodings = [] # 获取当前帧的人脸数据
face_names = [] # 当前人脸的名字
process_this_frame = True # 不断的设置为true or false 一帧帧的捕获

# 开始死循环
while True:
ret, frame = video_capture.read() # 读取摄像头

small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # 重新调整大小 为原视频的1/4

if process_this_frame:
face_locations = face_recognition.face_locations(small_frame) # 获取当前的人脸的位置,以便后期框出来
face_encodings = face_recognition.face_encodings(small_frame, face_locations) # 获取当前人脸的数据

face_names = []
for face_encoding in face_encodings: # 写个循环对人脸进行比对 ,容差为0.45
match = face_recognition.compare_faces(face_encodingsss, face_encoding, tolerance=0.45)

for i in range(len(face_namesss)):
if match[i]:
name = face_namesss[i]
break
else:
name = "unknown"
face_names.append(name)

process_this_frame = not process_this_frame # 不断改成false or true

for (top, right, bottom, left), name in zip(face_locations, face_names): # 写个循环 不断的吧人脸框出来
top *= 4
right *= 4
bottom *= 4
left *= 4

if (name != "unknown"):
# print(name,last_name)
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) # 第一个方形 为上面的方形
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 255, 0), 2) # 第二个方形 为下面的方形 用于存储文字
font = cv2.FONT_HERSHEY_DUPLEX # 设置字体
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)

if (name == last_name and len(name)==8):
# print("是同一个人,不进行重复签到了")
cv2.putText(frame, name + " You've signed in!", (150, 400), font, 0.8, (0, 0, 255), 1) #
pass
else:
if(name!="unknown"):
last_name = name
cv2.putText(frame, name + " check success", (150, 400), font, 0.8, (0, 255, 0), 1) #
print("进行签到")
print(name)
sqlHelper.qiandao(name,week)
# time.sleep(3)

else:
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) # 第一个方形 为上面的方形
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), 2) # 第二个方形 为下面的方形 用于存储文字
font = cv2.FONT_HERSHEY_DUPLEX # 设置字体
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
cv2.putText(frame, "please exit(hit 'ESC') and upload the picture", (10, 400), font, 0.8, (0, 0, 255),1) #

cv2.imshow('Checking', frame) # 一帧帧的绘画出来

if cv2.waitKey(1) == 27:
break

# 销毁窗口
video_capture.release()
cv2.destroyAllWindows()

核心代码(框出人脸并存储成图像)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import face_recognition
import cv2
import ostest
from PIL import Image

def uploadImg(stuID):
video_capture = cv2.VideoCapture(0)
# cv2.CAP_DSHOW
# 初始化一些变量
face_locations = [] # 当前获取到的人脸的未知 4个点top bottom left right
process_this_frame = True # 不断的设置为true or false 一帧帧的捕获
while True:
ret, frame = video_capture.read() # 读取摄像头

rgb_small_frame = frame[:, :, ::-1]
if process_this_frame:
face_locations = face_recognition.face_locations(rgb_small_frame) # 获取当前的人脸的位置,以便后期框出来
# print(face_locations)
try:
top, right, bottom, left = face_locations[0]
top -= 80
bottom += 40
left -= 20
right += 30

face_image = rgb_small_frame[top:bottom, left:right]
pil_image = Image.fromarray(face_image)
# pil_image.show()
pil_image.save("./img/"+stuID+".jpg")
print("已经弄好了,确认后按ESC退出")
except:
print("error")

process_this_frame = not process_this_frame # 不断改成false or true

for (top, right, bottom, left) in (face_locations): # 写个循环 不断的吧人脸框出来
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) # 第一个方形 为上面的方形
font = cv2.FONT_HERSHEY_DUPLEX # 设置字体
cv2.putText(frame, "If the green box appears, please", (30, 400), font, 0.8, (0, 0, 255), 1) #
cv2.putText(frame, "confirm and press ESC for exit", (30, 450), font, 0.8, (0, 0, 255), 1) #
cv2.imshow(stuID+" Please keep pressing the space bar", frame) # 一帧帧的绘画出来

if cv2.waitKey() == 27:
break

# 销毁窗口
video_capture.release()
cv2.destroyAllWindows()

公开项目仓库地址(全部代码)

这个项目我进行开源了,如果有感兴趣的朋友可以通过我的远程仓库进行克隆下载。
地址:https://git.dev.tencent.com/ROT_conding/face_check.git

仓库目录解释

— img //文件夹,用户存储样本图片
— face_qiandao.py //人脸签到代码
— face_upload.py //人脸录入(样本采集)代码
— main.py //程序入口,主页面
— ostest.py //用于读取图片
— sqlHelper.py //用于操作数据库
— teacher.py //弃用
— win_findata.py // 显示签到情况
— win_teacherCheck.py //教师代签
— win_upload.py // 输入姓名学号,进行人脸录入

遇到问题以及解决方法

1、face_recognition库无法安装,缺少依赖,或者是报错。
解决方法:https://www.cnblogs.com/zhanghaiyan/p/9872563.html
2、tkinter图形界面调用一次摄像头后,没有释放掉摄像头(但是代码已经释放了),第二次调用的时候就会报错。
解决办法:暂无,可以通过第二次重新运行项目解决。
3、有时候获取样本数据,转成人脸数据的时候会出现list越界,暂时不知道具体原因,但是把样本图片删了,重新录入就解决了。

参考文献以及文档

face_recognition库的使用——>https://github.com/ageitgey/face_recognition

本项目可能有漏洞,或者有考虑不周到的地方,请谅解,谢谢支持!