Python OpenCV开发MR智能人脸识别打卡系统(四服务模块设计)
Posted showswoller
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python OpenCV开发MR智能人脸识别打卡系统(四服务模块设计)相关的知识,希望对你有一定的参考价值。
需要源码请点赞关注收藏后评论区留言私信~~~
整体系统讲解如下
Python OpenCV开发MR智能人脸识别打卡系统(一、需求分析与系统设计)
Python OpenCV开发MR智能人脸识别打卡系统(二、文件系统、数据实体模块设计)
Python OpenCV开发MR智能人脸识别打卡系统(三、工具模块设计)
Python OpenCV开发MR智能人脸识别打卡系统(五、程序入口设计与测试)
本系统的服务模块包含两个文件:hr_service.py和rocognize_service.py,前者提供所有人事管理的相关功能,例如增减员工,查询员工数据,后者提供人脸识别服务
一、人事服务模块
该模块包含以下功能:
添加新员工
删除某员工
为指定员工添加打卡记录
多种获取员工新的方法
生成考勤日报
生成考勤月报
1:导入模块
人事服务需要管理员工类列表,记录打卡时间,还要计算,对比负责的日期和时间数值,所以要导入数据实体模块,公共工具模块,时间模块和日历模块
from entity import organizations as o
from util import public_tools as tool
from util import io_tools as io
import datetime
import calendar
2:加载所有数据
程序启动时运行此方法就可以一次性载入所有保存在文件中的数据,该方法依次进行文件自检,载入管理员账号密码,打卡记录,员工信息和员工照片
def load_emp_data():
io.checking_data_files() # 文件自检
io.load_users() # 载入管理员账号
io.load_lock_record() # 载入打卡记录
io.load_employee_info() # 载入员工信息
io.load_employee_pic() # 载入员工照片
3:添加新员工
def add_new_employee(name):
code = tool.randomCode() # 生成随机特征码
newEmp = o.Employee(o.get_new_id(), name, code) # 创建员工对象
o.add(newEmp) # 组织结构中添加新员工
io.save_employee_all() # 保存最新的员工信息
return code # 新员工的特征码
4:删除员工
# 删除某个员工
def remove_employee(id):
io.remove_pics(id) # 删除该员工所有图片
o.remove(id) # 从组织结构中删除
io.save_employee_all() # 保存最新的员工信息
io.save_lock_record() # 保存最新的打卡记录
5:添加打卡记录
def add_lock_record(name):
record = o.LOCK_RECORD # 所有打卡记录
now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 当前时间
if name in record.keys(): # 如果这个人有打卡记录
r_list = record[name] # 去除他的记录
if len(r_list) == 0: # 如果记录为空
r_list = list() # 创建新列表
r_list.append(now_time) # 记录当前时间
else: # 如果这个人从未打过卡
r_list = list() # 创建新列表
r_list.append(now_time) # 记录当前时间
record[name] = r_list # 将记录保存在字典中
io.save_lock_record() # 保存所有打卡记录
打卡时间规则如下
6:获取员工数据
人事服务提供了多种获取员工数据的方法,可以满足多种业务场景
def get_employee_report():
# report = list() # 员工信息列表
report = "###########################################\\n"
report += "员工名单如下:\\n"
i = 0 # 换行计数器
for emp in o.EMPLOYEES: # 遍历所有员工
report += "(" + str(emp.id) + ")" + emp.name + "\\t"
i += 1 # 计数器自增
if i == 4: # 每四个员工换一行
report += "\\n"
i = 0 # 计数器归零
report = report.strip() # 清除报表结尾可能出现的换行符
report += "\\n###########################################"
return report
7:验证管理员账号和密码
只有管理员账号密码都正确的情况下,才可以正确登录
def valid_user(username, password):
if username in o.USERS.keys(): # 如果有这个账号
if o.USERS.get(username) == password: # 如果账号和密码匹配
return True # 验证成功
return False # 验证失败
8:保存上下班时间
第一个参数为上班时间,第二个参数为下班时间
def save_work_time(work_time, close_time):
o.WORK_TIME = work_time
o.CLOSING_TIME = close_time
io.save_work_time_config() # 上下班时间保存到文件中
9:打印考勤日报
方法中分别创建了迟到 早退和缺席名单三个列表,只要某员工出现不正常打卡记录,就会将该员工姓名放到对应不正常打卡状态的名单里,最后打印报表,给出各名单人数和明细
# 打印指定日期的打卡日报
def get_day_report(date):
io.load_work_time_config() # 读取上下班时间
earliest_time = datetime.datetime.strptime(date + " 00:00:00", "%Y-%m-%d %H:%M:%S") # 今天0点
noon_time = datetime.datetime.strptime(date + " 12:00:00", "%Y-%m-%d %H:%M:%S") # 今天中午12点
latest_time = datetime.datetime.strptime(date + " 23:59:59", "%Y-%m-%d %H:%M:%S") # 今晚0点之前
work_time = datetime.datetime.strptime(date + " " + o.WORK_TIME, "%Y-%m-%d %H:%M:%S") # 上班时间
closing_time = datetime.datetime.strptime(date + " " + o.CLOSING_TIME, "%Y-%m-%d %H:%M:%S") # 下班时间
late_list = [] # 迟到名单
left_early = [] # 早退名单
absent_list = [] # 缺席名单
for emp in o.EMPLOYEES: # 遍历所有员工
if emp.name in o.LOCK_RECORD.keys(): # 如果该员工有打卡记录
emp_lock_list = o.LOCK_RECORD.get(emp.name) # 获取该员工所有的打卡记录
is_absent = True # 缺席状态
for lock_time_str in emp_lock_list: # 遍历所有打卡记录
lock_time = datetime.datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S") # 打卡记录转为日期格式
if earliest_time < lock_time < latest_time: # 如果当天有打卡记录
is_absent = False # 不缺席
if work_time < lock_time <= noon_time: # 上班时间后、中午之前打卡
late_list.append(emp.name) # 加入迟到名单
if noon_time < lock_time < closing_time: # 中午之后、下班之前打卡
left_early.append(emp.name) # 加入早退名单
if is_absent: # 如果仍然是缺席状态
absent_list.append(emp.name) # 加入缺席名单
else: # 该员工没有打卡记录
absent_list.append(emp.name) # 加入缺席名单
emp_count = len(o.EMPLOYEES) # 员工总人数
print("--------" + date + "--------")
print("应到人数:" + str(emp_count))
print("缺席人数:" + str(len(absent_list)))
absent_name = "" # 缺席名单
if len(absent_list) == 0: # 如果没有缺席的
absent_name = "(空)"
else: # 有缺席的
for name in absent_list: # 遍历缺席列表
absent_name += name + " " # 拼接名字
print("缺席名单:" + absent_name)
print("迟到人数:" + str(len(late_list)))
late_name = "" # 迟到名单
if len(late_list) == 0: # 如果没有迟到的
late_name = "(空)"
else: # 有迟到的
for name in late_list: # 遍历迟到列表
late_name += name + " " # 拼接名字
print("迟到名单:" + str(late_name))
print("早退人数:" + str(len(left_early)))
early_name = "" # 早退名单
if len(left_early) == 0: # 如果没有早退的
early_name = "(空)"
else: # 有早退的
for name in left_early: # 遍历早退列表
early_name += name + " " # 拼接名字
print("早退名单:" + early_name)
10:生成考勤月报
与考勤日报不同,考勤月报是一种汇总形式的报表,可以展示员工整个月的考勤状态,因为月报表内容较多,所以不会在控制台中展示,而是生成独立的报表文件
用记事本打开CSV格式的月报
用Office Excel打开CSV格式的月报
# 创建指定月份的打卡记录月报
def get_month_report(month):
io.load_work_time_config() # 读取上下班时间
date = datetime.datetime.strptime(month, "%Y-%m") # 月份转为时间对象
monthRange = calendar.monthrange(date.year, date.month)[1] # 该月最后一天的天数
month_first_day = datetime.date(date.year, date.month, 1) # 该月的第一天
month_last_day = datetime.date(date.year, date.month, monthRange) # 该月的最后一天
clock_in = "I" # 正常上班打卡标志
clock_out = "O" # 正常下班打卡标志
late = "L" # 迟到标志
left_early = "E" # 早退标志
absent = "A" # 缺席标志
lock_report = dict() # 键为员工名,值为员工打卡情况列表
for emp in o.EMPLOYEES:
emp_lock_data = [] # 员工打卡情况列表
if emp.name in o.LOCK_RECORD.keys(): # 如果员工有打卡记录
emp_lock_list = o.LOCK_RECORD.get(emp.name) # 从打卡记录中获取该员工的记录
index_day = month_first_day # 遍历日期,从该月第一天开始
while index_day <= month_last_day:
is_absent = True # 缺席状态
earliest_time = datetime.datetime.strptime(str(index_day) + " 00:00:00", "%Y-%m-%d %H:%M:%S") # 当天0点
noon_time = datetime.datetime.strptime(str(index_day) + " 12:00:00", "%Y-%m-%d %H:%M:%S") # 当天中午12点
latest_time = datetime.datetime.strptime(str(index_day) + " 23:59:59", "%Y-%m-%d %H:%M:%S") # 当天0点之前
work_time = datetime.datetime.strptime(str(index_day) + " " + o.WORK_TIME,
"%Y-%m-%d %H:%M:%S") # 当天上班时间
closing_time = datetime.datetime.strptime(str(index_day) + " "
+ o.CLOSING_TIME, "%Y-%m-%d %H:%M:%S") # 当天下班时间
emp_today_data = "" # 员工打卡标记汇总
for lock_time_str in emp_lock_list: # 遍历所有打卡记录
lock_time = datetime.datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S") # 打卡记录转为日期格式
if earliest_time < lock_time < latest_time: # 如果当前日期有打卡记录
is_absent = False # 不缺席
if lock_time <= work_time: # 上班时间前打卡
emp_today_data += clock_in # 追加正常上班打卡标志
elif lock_time >= closing_time: # 下班时间后打卡
emp_today_data += clock_out # 追加正常下班打卡标志
elif work_time < lock_time <= noon_time: # 上班时间后、中午之前打卡
emp_today_data += late # 追加迟到标志
elif noon_time < lock_time < closing_time: # 中午之后、下班之前打卡
emp_today_data += left_early # 追加早退标志
if is_absent: # 如果缺席
emp_today_data = absent # 直接赋予缺席标志
emp_lock_data.append(emp_today_data) # 员工打卡标记添加到打卡情况列表中
index_day = index_day + datetime.timedelta(days=1) # 遍历天数递增
else: # 没有打卡记录的员工
index_day = month_first_day # 从该月第一天开始
while index_day <= month_last_day: # 遍历整月
emp_lock_data.append(absent) # 每天都缺席
index_day = index_day + datetime.timedelta(days=1) # 日期递增
lock_report[emp.name] = emp_lock_data # 将打卡情况列表保存到该员工之下
report = "\\"姓名/日期\\"" # cvs文件的文本内容,第一行第一列
index_day = month_first_day # 从该月第一天开始
while index_day <= month_last_day: # 遍历整月
report += ",\\"" + str(index_day) + "\\"" # 添加每一天的日期
index_day = index_day + datetime.timedelta(days=1) # 日期递增
report += "\\n"
for emp in lock_report.keys(): # 遍历报表中的所有员工
report += "\\"" + emp + "\\"" # 第一列为员工名
data_list = lock_report.get(emp) # 取出员工的打卡情况列表
for data in data_list: # 取出每一天的打卡情况
text = "" # CSV中显示的内容
if absent == data: # 如果是缺席
text = "【缺席】"
elif clock_in in data and clock_out in data: # 如果是全勤,不考虑迟到和早退
text = "" # 显示空白
else: # 如果不是全勤
if late in data and clock_in not in data: # 有迟到记录且无上班打卡
text += "【迟到】"
if left_early in data and clock_out not in data: # 有早退记录且无下班打卡
text += "【早退】"
if clock_out not in data and left_early not in data: # 无下班打卡和早退记录
text += "【下班未打卡】"
if clock_in not in data and late not in data: # 有无上班打卡和迟到记录
text += "【上班未打卡】"
report += ",\\"" + text + "\\""
report += "\\n"
title_date = month_first_day.strftime("%Yy%mm").format(y="年", m="月") # csv文件标题日期
file_name = title_date + "考勤月报" # CSV的文件名
io.create_CSV(file_name, report) # 生成csv文件
二、人脸识别服务模块
该模块提供以下功能
检测图像中是否有正面人脸
判断图像中的人脸属于哪个人
1:导入模块
import cv2
import numpy as np
import os
2:全局变量
RECOGNIZER = cv2.face.LBPHFaceRecognizer_create() # LBPH识别器
# RECOGNIZER = cv2.face.EigenFaceRecognizer_create()#特征脸识别器
# RECOGNIZER = cv2.face.FisherFaceRecognizer_create() # LBPH识别器
PASS_CONF = 45 # 最高评分,LBPH最高建议用45,特征脸最高建议用22000
3:训练识别器
# 训练识别器
def train(photos, lables):
RECOGNIZER.train(photos, np.array(lables)) # 识别器开始训练
4:发现人脸
用来判断图像中是否有正面人脸,参数为灰度图像,通过正面人脸获取级联分类器对检测图像中出现的人脸数量
# 识别器识别图像中的人脸
def recognise_face(photo):
label, confidence = RECOGNIZER.predict(photo) # 识别器开始分析人脸图像
if confidence > PASS_CONF: # 忽略评分大于最高评分的结果
return -1
return label
5:识别人脸
该方法用来识别图像中的人脸属于哪位员工,方法参数为被识别的图像,该方法必须在识别器接收完训练之后被调用,识别器给出分析得出的评分,如果评分大于可信范围,则认为图像中不存在任何已有员工,返回-1,否则返回已有员工的特征码
# 判断图像中是否有正面人脸
def found_face(gary_img):
faces = FACE_CASCADE.detectMultiScale(gary_img, 1.15, 4) # 找出图像中所有的人脸
return len(faces) > 0 # 返回人脸数量大于0的结果
创作不易 觉得有帮助请点赞关注收藏~~~
以上是关于Python OpenCV开发MR智能人脸识别打卡系统(四服务模块设计)的主要内容,如果未能解决你的问题,请参考以下文章
Python OpenCV开发MR智能人脸识别打卡系统(五程序入口设计与测试)
Python人脸识别智能考勤系统 (供源码,附报告)(可答疑,可调试)