【优秀毕设】基于OpenCV的人脸识别打卡/签到/考勤管理系统(最简基本库开发、可基于树莓派)
该系统利用Harr级联检测和LPBH进行人脸检测和训练、识别
利用Tkinter完成界面搭建
利用Flask+HTML完成网络实时图像推流及控制
利用captcha.image 完成验证码功能
利用xlsxwriter将数据保存为Excel文档
利用email库发送邮件
功能如下图所示 所有功能均可实现
cv2版本: 推荐4.4.0.46 安装opencv-python和opencv-contrib-python
部分资源:
download.csdn.net/download/weixin_53403301/85545163
基础完整资源:
download.csdn.net/download/weixin_53403301/85744946
视频:
www.bilibili.com/video/BV1Ls4y1d78U/
【优秀毕设开源】基于OpenCV的人脸识别打卡/签到/考勤管理系统(最简基本库开发、可基于树莓派)
部分代码:
"""
Created on Mon May 31 23:39:19 2021
@author: ZHOU
"""
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
import tkinter.messagebox
from PIL import Image, ImageTk, ImageDraw, ImageFont
import cv2
import threading
import time
import os
import re
import numpy as np
from captcha.image import ImageCaptcha
import random
import string
import xlsxwriter
import smtplib
import email.mime.multipart
import email.mime.text
from email.mime.application import MIMEApplication
from flask import Flask,render_template, request, Response
import socket
global network_flag
network_flag = 0
local_post = 1212
local_ip = None
for i in range(12):
try:
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.connect(("8.8.8.8",80))
local_ip = str(s.getsockname()[0])
s.close()
print("Network Enable")
network_flag = 1
break
except:
print("Network Error...")
network_flag = 0
time.sleep(5)
app = Flask(__name__)
star_pic_path = "./star.png"
pic_path = "./dataset"
train_path = "./trainer"
data_path = "./data"
train_nb_path = "/train_nb.txt"
train_time_path = "/train_time.txt"
name_id_path = "/name_id.txt"
email_set_path = "/email_set.txt"
admin_path = "/admin.txt"
yml_path = "/trainer.yml"
temp_path = "./temp"
save_path = "./save"
date_path = "/date.txt"
sign_in_mode_path = "/sign_in_mode.txt"
company_path = "/company.txt"
department_path = "/department.txt"
class_id_path = "/class_id.txt"
global today_temp_path
now_today = time.time()
today_temp_path = "/today_"+str(time.localtime(now_today).tm_year)+"_"+str(time.localtime(now_today).tm_mon)+"_"+str(time.localtime(now_today).tm_mday)+".txt"
cascadePath = "./cascade/haarcascade_frontalface_alt2.xml"
faceCascade = cv2.CascadeClassifier(cascadePath)
font = cv2.FONT_HERSHEY_SIMPLEX
recognizer = cv2.face.LBPHFaceRecognizer_create()
try:
recognizer.read(train_path+yml_path)
except:
print("缺失训练数据文件,请先训练数据")
cam_flag = 0
global img2
img2 = None
global img_flag
img_flag = 0
global login_flag
login_flag = 0
global doing_change_record_date_flag
doing_change_record_date_flag = 0
global auto_send_flag
auto_send_flag = 0
"""
Created on Mon Apr 25 23:25:45 2022
@author: 16016
"""
import xlsxwriter
import time
def txt_excel(filename):
fp = open(filename,encoding="utf-8")
x = 0
y = 0
lines = fp.readlines()
today_list = (lines[0].split("\n")[0]).split("-")
xls = xlsxwriter.Workbook('record_' + today_list[0]+"_"+today_list[1]+"_"+today_list[2] + '.xlsx')
sheet = xls.add_worksheet('record_' + today_list[0]+"_"+today_list[1]+"_"+today_list[2])
sheet.write(0,0,"姓名")
for j in lines:
for i in range(1,len(j.split('|'))):
item = j.split('|')[i].strip(' ')
sheet.write(x,y,item)
y += 1
x += 1
y = 0
fp.close()
xls.close()
filename = './temp/today_2022_4_25.txt'
xlsname = './save/学生签到表'
txt_excel(filename)
<html>
<meta http-equiv="refresh" content="60">
<head>
<title>人脸识别签到管理系统</title>
</head>
<body>
<h1>人脸识别签到管理系统</h1>
<form action="/" method="post">
<p><input type="submit" style="font-size:50px" name="send" value="发送数据">
<input type="submit" style="font-size:50px" name="maul" value="刷新网页"></p>
<p>
<table>
{% for k,v in data_dict.items() %}
<tr>
<td>{{k}}</td>
<td>{{v[0]}}</td>
<td>{{v[1]}}</td>
<td>{{v[2]}}</td>
<td>{{v[3]}}</td>
<td>{{v[4]}}</td>
</tr>
{% endfor %}
</table>
</p>
<p><input type="submit" style="font-size:50px" name="update" value="更新记录日期">
<input type="submit" style="font-size:50px" name="back" value="回退记录日期"></p>
</form>
<img src="{{ url_for('video_feed') }}" height="520" style="float:left">
</body>
</html>
"""
Created on Tue Apr 26 15:16:42 2022
@author: 16016
"""
import smtplib
import email.mime.multipart
import email.mime.text
from email.mime.application import MIMEApplication
def send_email(file_path,smtp_host, smtp_port, sendAddr, password, recipientAddrs, subject='', content=''):
'''
:param smtp_host: 域名
:param smtp_port: 端口
:param sendAddr: 发送邮箱
:param password: 邮箱密码
:param recipientAddrs: 发送地址
:param subject: 标题
:param content: 内容
:return: 无
'''
msg = email.mime.multipart.MIMEMultipart()
msg['from'] = sendAddr
msg['to'] = recipientAddrs
msg['subject'] = subject
content = content
txt = email.mime.text.MIMEText(content, 'plain', 'utf-8')
msg.attach(txt)
if file_path != '':
part = MIMEApplication(open(file_path, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename="name_id.xlsx")
msg.attach(part)
try:
smtpSSLClient = smtplib.SMTP_SSL(smtp_host, smtp_port)
loginRes = smtpSSLClient.login(sendAddr, password)
print(f"登录结果:loginRes = {loginRes}")
if loginRes and loginRes[0] == 235:
print(f"登录成功,code = {loginRes[0]}")
smtpSSLClient.sendmail(sendAddr, recipientAddrs, str(msg))
print(f"mail has been send successfully. message:{str(msg)}")
smtpSSLClient.quit()
else:
print(f"登陆失败,code = {loginRes[0]}")
except Exception as e:
print(f"发送失败,Exception: e={e}")
try:
subject = 'Python 测试邮件'
content = '这是一封来自 Python 编写的测试邮件。'
send_email('','smtp.qq.com', 465, '', '', '', subject, content)
except Exception as err:
print(err)
主页面
验证码:
识别效果
管理页面:
数据保存除了用户信息和签到信息外 还可以判断是否迟到、早退并计算工作时长
人脸信息采集
管理:
实时数据更新:
签到结果:
邮件发送:
网络前端效果:
实时图像推流:
(在识别时(IN/OUT功能)会推流到网络中 管理员通过IP地址可以实现监控效果)
py打包
Pyinstaller打包exe(包括打包资源文件 绝不出错版)
依赖包及其对应的版本号
PyQt5 5.10.1
PyQt5-Qt5 5.15.2
PyQt5-sip 12.9.0
pyinstaller 4.5.1
pyinstaller-hooks-contrib 2021.3
Pyinstaller -F setup.py 打包exe
Pyinstaller -F -w setup.py 不带控制台的打包
Pyinstaller -F -i xx.ico setup.py 打包指定exe图标打包
打包exe参数说明:
-F:打包后只生成单个exe格式文件;
-D:默认选项,创建一个目录,包含exe文件以及大量依赖文件;
-c:默认选项,使用控制台(就是类似cmd的黑框);
-w:不使用控制台;
-p:添加搜索路径,让其找到对应的库;
-i:改变生成程序的icon图标。
如果要打包资源文件
则需要对代码中的路径进行转换处理
另外要注意的是 如果要打包资源文件 则py程序里面的路径要从./xxx/yy换成xxx/yy 并且进行路径转换
但如果不打包资源文件的话 最好路径还是用作./xxx/yy 并且不进行路径转换
def get_resource_path(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
而后再spec文件中的datas部分加入目录
如:
a = Analysis(['cxk.py'],
pathex=['D:\\Python Test\\cxk'],
binaries=[],
datas=[('root','root')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
而后直接Pyinstaller -F setup.spec即可
如果打包的文件过大则更改spec文件中的excludes 把不需要的库写进去(但是已经在环境中安装了的)就行
这些不要了的库在上一次编译时的shell里面输出
比如:
然后用pyinstaller --clean -F 某某.spec
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)