人脸考勤机项目
文章内容如下:
1)项目简介
2)开发环境和使用的技术知识
3)功能实现
4)项目源码
一。项目简介
此项目是基于HOG和Dlib开发的一套实时无感考勤系统。首先是待考勤人员的个人信息录入。然后在过道或者入口处装置人脸考勤机,当有人经过时,摄像头抓取人脸并上传服务器,对抓取到的人脸进行人脸识别,判断此人身份,若此人在信息比对库中且第一次考勤,则考勤成功,并显示考勤人员姓名与比对距离,如非第一次考勤,并在一定时间隔外则更新考勤 。
二。开发环境和使用的技术知识
开发环境:Python,Opencv
技术知识:HOG+Dlib技术、Opencv视频读取-缩放-翻转-写入技术
三。功能实现
1. 人脸注册:将人脸特征存进feaure.csv
2. 人脸识别:将检测的人脸特征与feaure.csv人脸特征作比较,如果比中把考勤记录写入attendance.csv
1. 人脸注册:将人脸特征存进feaure.csv
①调取视频流,能显示人脸画面
cap = cv2.VideoCapture(0)"""调取摄像头"""while True:ret,frame = cap.read()frame =  cv2.flip(frame,1)"""y轴镜像"""cv2.imshow('Face attendance',frame)"""展示每一帧图片"""if cv2.waitKey(10) & 0xFF == ord('q'):break
cap.release()
cv2.destroyAllWindows()② 步骤如下:
第1步:启动HOG人脸检测器,读取人脸上下左右坐标,绘制人脸方框;
hog_face_detector = dlib.get_frontal_face_detector()"""启动hog人脸检测器"""
detections = hog_face_detector(frame,1)"""获取人脸参数,缩放因子为1"""
for face in detections:l,t,r,b = face.left(),face.top(),face.right(),face.bottom()"""获取人脸左,上,右,下的坐标"""
cv2.rectangle(frame,(l,t),(r,b),(0,255,0),2)"""绘制人脸框"""第2步: 启动人脸关键点检测器获取人脸68个关键点,再转为特征描述符;
shape_detector = dlib.shape_predictor('./1/shape_predictor_68_face_landmarks.dat')"""启动人脸关键点检测器"""
detections = hog_face_detector(frame,1)"""获取人脸参数,缩放因子为1""" 
for face in detections:points = shape_detector(frame,face)"""获取人脸68关键点"""
for point in points.parts():cv2.circle(frame,(point.x,point.y),2,(0,255,0),-10)"""绘制68关键点"""
face_descriptor = face_descriptor_extractor.compute_face_descriptor(frame,points)"""获取(转为)特征描述符"""
face_descriptor = [f for f in face_descriptor]"""为方便转换成列表存进feaure.csv"""①②组合在一起复合代码如下:
def faceRegister(label_id=1,name='Jie Wang',count=3,interval=3):
#1)-检测人脸#准备工作hog_face_detector = dlib.get_frontal_face_detector()#①启动hog人脸检测器shape_detector = dlib.shape_predictor('./1/shape_predictor_68_face_landmarks.dat')#①启动人脸关键点检测器face_descriptor_extractor = dlib.face_recognition_model_v1('./1/dlib_face_recognition_resnet_model_v1.dat')#①启动特征描述符检测器cap = cv2.VideoCapture(0)#②调取摄像头start_time = time.time()#开始时间,是为了interval设置的collect_count = 0#初始采集次数f = open('./2/feature.csv','a',newline="")#采集到的特征描述符放在这个文件里csv_writer = csv.writer(f)#采集3次特征  while True:ret,frame = cap.read()frame =  cv2.flip(frame,1)#y轴镜像detections = hog_face_detector(frame,1)#获取人脸参数,缩放因子为1for face in detections:l,t,r,b = face.left(),face.top(),face.right(),face.bottom()#获取人脸左,上,右,下的坐标points = shape_detector(frame,face)#获取人脸68关键点for point in points.parts():cv2.circle(frame,(point.x,point.y),2,(0,255,0),-10)#绘制68关键点cv2.rectangle(frame,(l,t),(r,b),(0,255,0),2)#绘制人脸框if collect_count < count:now = time.time()if now - start_time > interval:face_descriptor = face_descriptor_extractor.compute_face_descriptor(frame,points)#获取特征描述符face_descriptor = [f for f in face_descriptor]#转换成列表方便存进feaure.csvline = [label_id,name,face_descriptor]csv_writer.writerow(line)#写入csv_writercollect_count +=1start_time = nowprint("采集次数:{collect_count}".format(collect_count = collect_count))copy_collect_count = collect_count
#                       print(face_descriptor)else:if 3 == copy_collect_count:print("采集完毕")copy_collect_count = 0break#展示   cv2.imshow('Face attendance',frame)#展示每一帧图片if cv2.waitKey(10) & 0xFF == ord('q'):breakf.close()cap.release()cv2.destroyAllWindows()faceRegister()2. 人脸识别:将检测的人脸特征与feaure.csv人脸特征作比较,如果比中把考勤记录写入attendance.csv
①从磁盘中调取注册时的人脸特征描述符,解析它
def getFeatureList():label_list = []name_list = []featuree_list = None"""后面用的np.concatenate()方法决定了此处不能是空列表,否则无法拼接"""with open('./2/feature.csv','r') as f:csv_reader = csv.reader(f)for line in csv_reader:label_id = line[0]name = line[1]face_descriptor = eval(line[2])"""从csv文件拿出来的列表是字符串,需要eval处理一下转为list"""face_descriptor = np.asarray(face_descriptor,dtype=np.float64)face_descriptor = np.reshape(face_descriptor,(1,-1))"""转成1xn格式,期望就是这样"""label_list.append(label_id)"""label_list拼接过程"""name_list.append(name)"""name_list拼接过程"""if featuree_list is None:"""featuree_list拼接过程"""featuree_list = face_descriptorelse:featuree_list = np.concatenate((featuree_list,face_descriptor),axis=0)
#             print(name)return  label_list,name_list,featuree_listlabel_list,name_list,featuree_list = getFeatureList()"""读取人脸注册时的特征"""②特征描述符比对,计算与库的距离
distance = np.linalg.norm((face_descriptor-featuree_list),axis=1)"""范数求差"""
min_index = np.argmin(distance)"""获取最短距离索引"""
min_distance = np.argmin(distance)"""获取最短距离"""
if min_distance < threshold:"""识别到打印信息"""predict_id = label_list[min_distance]predict_name = name_list[min_distance]③依据条件确认是否记录考勤
need_insert = False"""用于后面判断是否变化了考勤,是则写入到attendance.csv文件"""
if predict_name in recog_record:"""第一次检测到考勤则记录人脸信息,记录的是名字与考勤时间组成的键值对,如这次检测与上次记录差3s,则再考勤一次。上述都不是则跳过"""if time.time()-recog_record[predict_name]>3:need_insert = Truerecog_record[predict_name] = time.time()print(predict_name)else:print("无需重复签到!")need_insert = Falsepass
else:need_insert = Truerecog_record[predict_name] = time.time()print(predict_name)④将考勤记录写入文件
if need_insert:"""考勤较上次变化了则记录"""time_local = time.localtime(recog_record[predict_name])"""时间戳"""time_str = time.strftime("%Y-%m-%d %H:%M:%S",time_local)"""化时间戳为年月日"""line = [predict_id,predict_name,min_distance,time_str]csv_writer.writerow(line)print("{name} {time}考勤记录已成功更新入文件!".format(name=predict_name,time=time_str))①-④组合在一起复合代码如下:
def faceRecognizer(threshold = 0.5):#1)实时获取视频流中人脸特征描述符;#1准备工作label_list,name_list,featuree_list = getFeatureList()#读取人脸注册时的特征hog_face_detector = dlib.get_frontal_face_detector()#①启动hog人脸检测器shape_detector = dlib.shape_predictor('./1/shape_predictor_68_face_landmarks.dat')#①启动人脸关键点检测器face_descriptor_extractor = dlib.face_recognition_model_v1('./1/dlib_face_recognition_resnet_model_v1.dat')#①启动特征描述符检测器cap = cv2.VideoCapture(0)#②调取摄像头recog_record = {}#为存考勤信息做准备f = open('./2/attendance.csv','a',newline="")#为文件性质记录考勤数据做准备csv_writer = csv.writer(f)fps_time = time.time()#画面显示fps#2获取人脸识别中采集到的特征while True:ret,frame = cap.read()frame =  cv2.flip(frame,1)#y轴镜像detections = hog_face_detector(frame,1)#获取人脸参数,缩放因子为1for face in detections:l,t,r,b = face.left(),face.top(),face.right(),face.bottom()#获取人脸左,上,右,下的坐标points = shape_detector(frame,face)#获取人脸68关键点cv2.rectangle(frame,(l,t),(r,b),(0,255,0),2)#绘制人脸框face_descriptor = face_descriptor_extractor.compute_face_descriptor(frame,points)#获取特征描述符face_descriptor = [f for f in face_descriptor]#转换成列表方便存进feaure.csv  #3计算与库的距离distance = np.linalg.norm((face_descriptor-featuree_list),axis=1)#范数求差min_index = np.argmin(distance)#获取最短距离索引min_distance = np.argmin(distance)#获取最短距离if min_distance < threshold:#识别到打印信息predict_id = label_list[min_distance]predict_name = name_list[min_distance]#6给人脸框添加内容cv2.putText(frame,predict_name+" "+str(round(min_distance,2)),(l,b+30),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,(0,255,0),1)#4是否记录考勤  need_insert = False#用于后面判断是否变化了考勤,是则写入到attendance.csv文件if predict_name in recog_record:#第一次检测到考勤则记录人脸信息,记录的是名字与考勤时间组成的键值对,如这次检测与上次记录差3s,则再考勤一次。上述都不是则跳过if time.time()-recog_record[predict_name]>3:need_insert = Truerecog_record[predict_name] = time.time()print(predict_name)else:print("无需重复签到!")need_insert = Falsepasselse:need_insert = Truerecog_record[predict_name] = time.time()print(predict_name)if need_insert:#考勤较上次变化了则记录time_local = time.localtime(recog_record[predict_name])#时间戳time_str = time.strftime("%Y-%m-%d %H:%M:%S",time_local)#化时间戳为年月日line = [predict_id,predict_name,min_distance,time_str]csv_writer.writerow(line)print("{name} {time}考勤记录已成功更新入文件!".format(name=predict_name,time=time_str))else:print("未识别到") #5增加FPSnow = time.time()fps = 1/(now - fps_time)fps_time = nowcv2.putText(frame,"FPS:"+str(round(fps,2)),(20,40),cv2.FONT_HERSHEY_COMPLEX_SMALL,1,(0,255,0),1)cv2.imshow('Face attendance',frame)#展示每一帧图片if cv2.waitKey(10) & 0xFF == ord('q'):breakf.close()cap.release()cv2.destroyAllWindows()   #读取人脸注册时的特征
def getFeatureList():label_list = []name_list = []featuree_list = None#后面用的np.concatenate()方法决定了此处不能是空列表,否则无法拼接with open('./2/feature.csv','r') as f:csv_reader = csv.reader(f)for line in csv_reader:label_id = line[0]name = line[1]face_descriptor = eval(line[2])#从csv文件拿出来的列表是字符串,需要eval处理一下转为listface_descriptor = np.asarray(face_descriptor,dtype=np.float64)face_descriptor = np.reshape(face_descriptor,(1,-1))#转成1xn格式,期望就是这样label_list.append(label_id)#label_list拼接过程name_list.append(name)#name_list拼接过程if featuree_list is None:#featuree_list拼接过程featuree_list = face_descriptorelse:featuree_list = np.concatenate((featuree_list,face_descriptor),axis=0)
#             print(name)return  label_list,name_list,featuree_listlabel_list,name_list,featuree_list = getFeatureList()
faceRecognizer(threshold = 10)
四。项目源码
源码链接:点击这里
相关文章:
人脸考勤机项目
文章内容如下: 1)项目简介 2)开发环境和使用的技术知识 3)功能实现 4)项目源码 一。项目简介 此项目是基于HOG和Dlib开发的一套实时无感考勤系统。首先是待考勤人员的个人信息录入。然后在过道或者入口处装置人脸…...
 
Python编程自动化办公案例(3)
作者简介:一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页 目录 前言 一.前几章代码 1.获取到第一题的选项单元格 2.实现批量获取文件 二. 批…...
 
Linux-MYSQL 登录数据库(命令行,图形化) 及 远程登录
命令行登录 :mysql 命令登录数据库语法 : mysql -u用户名 -p密码 -h 连接的数据库服务器的ip [-D] 数据库名 -p 端口注 : 上面的 mysql 命令是指的是 客户端的指令 ~!!-h : 指的就是 连接数据库服务器的 ip…...
electron网络环境在线/离线事件探测
electron判断网络环境问题,可以说在任何桌面应用都可以使用到,处理方式有很多种,我介绍几种办法第一种HTML5 API navigator.onLine:官方案例给的,这边为直接贴出地址了,有兴趣的同学可自行查看https://www.…...
UE 项目导航数据生成配置
WP构建及常规构建操作WP构建方式 :https://docs.unrealengine.com/5.0/zh-CN/world-partitioned-navigation-mesh/常规构建方式针对WP的构建方式特殊配置项关闭就好:取消勾选RecastNavMesh-XXX下的IsWorldPartitioned执行n.bNavMeshAllowPartitionedBuil…...
 
494.目标和
1. 回溯算法 这题和之前做的那些排列、组合的回溯稍微有些不同,你不需要每次选数据时都是for遍历去选择,很明显这是顺序选择的 比如 数组[0,1],target1; 递归数组,每个元素都 或者 - ,然后取最后结果为0…...
 
滑台模组的应用有哪些?
在自动化生产中,我们常常会看到滑台模组的身影,那么,滑台模组究竟在自动化生产设备中起着怎样的作用呢? 简单点说,滑台模组由滑块、滚珠丝杆、导轨、主体等其它传动零件组成的自动化晋级单元,经过各单元的组…...
 
CS224W课程学习笔记(四):node2vec算法原理与说明
引言 什么是图嵌入? 我想从上节的deepwalk中已经有一个十分完整的轮廓了,这里引出deepwalk论文中的一张很形象的图(当然,上节的一些实战演练,也将这种嵌入关系进行了模拟与可视化,前文为:&…...
扩展lucas定理
前置知识: lucas定理中国剩余定理 介绍 当正整数n,mn,mn,m很大,且质数ppp较小的时候,要求CnmC_n^mCnm对ppp取模后的值,可以用lucas定理。 但如果ppp不是质数,那该怎么办呢?如果mmm较小,则…...
 
医疗影像工具LEADTOOLS 入门教程: 从 PDF 中提取附件 - 控制台 C#
LEADTOOLS 是一个综合工具包的集合,用于将识别、文档、医疗、成像和多媒体技术整合到桌面、服务器、平板电脑、网络和移动解决方案中,是一项企业级文档自动化解决方案,有捕捉,OCR,OMR,表单识别和处理&#…...
 
【LVGL】学习笔记--(1)Keil中嵌入式系统移植LVGL
一 LVGL简介最近emwin用的比较烦躁,同时被LVGL酷炫的界面吸引到了,所以准备换用LVGL试试水。LVGL(轻量级和通用图形库)是一个免费和开源的图形库,它提供了创建嵌入式GUI所需的一切,具有易于使用的图形元素,美丽的视觉效…...
 
Transformer学习笔记
Transformer学习笔记1. 参考2. 模型图3.encoder部分3.1 Positional Encoding3.2 Muti-Head Attention3.3 ADD--残差连接3.4 Norm标准化3.5 单个Transformer Encoder流程图4.decoder部分4.1 mask Muti-Head Attention4.2 Muti-Head Attention5 多个Transformer Encoder和多个Tra…...
 
vue-cli引入wangEditor、Element,封装可上传附件的富文本编辑器组件(附源代码直接应用,菜单可调整)
关于Element安装引入,请参考我的另一篇文章:vue-cli引入Element Plus(element-ui),修改主题变量,定义全局样式_shawxlee的博客-CSDN博客_chalk variables 1、安装wangeditor npm i wangeditor --savewangE…...
 
移动办公时代,数智化平台如何赋能企业管理升级?
在传统的办公模式下,企业组织办公不仅时效低,周期长、成本高,且各办公系统相互独立。随着社会经济的发展,人们的工作生活变得多样化,对于办公的需求也越来越多,存在明显弊端的传统办公模式已不能满足企业对…...
2023“拼夕夕”为什么可以凭借简单的拼团做这么大?
2023“拼夕夕”为什么可以凭借简单的拼团做这么大? 2023-02-24 梦龙 大家好,我是你们熟悉而又陌生的好朋友梦龙,一个创业期的年轻人 大家都知道,拼夕夕背后的商业模式是拼团,但是大家知道为什么简单的拼团可以让拼夕…...
 
sqlmap工具
sqlmap Sqlmap是一个开源的渗透测试工具,可以用来自动化的检测,利用SQL注入漏洞,获取数据库服务器的权限。目前支持的数据库有MySQL、Oracle、PostgreSQL、Microsoft SQL Server、Microsoft Access等大多数据库 Sqlmap采用了以下5种独特的SQ…...
 
高/低压供配电系统设计——安科瑞变电站电力监控系统的应用
摘 要:在电力系统的运行过程中,变电站作为整个电力系统的核心,在保证电力系统可靠的运行方面起着至关重要的作用,基于此需对变电站监控系统的特点进行分析,结合变电站监控系统的功能需求,对变电站电力监控系…...
 
Tapdata 和 Databend 数仓数据同步实战
作者:韩山杰https://github.com/hantmacDatabend Cloud 研发工程师基础架构在云计算时代也发生着翻天地覆的变化,对于业务的支持变成了如何能利用好云资源实现降本增效,同时更好的支撑业务也成为新时代技术人员的挑战。 本篇文章通过…...
 
单核CPU, 1G内存,也能做JVM调优吗?
最近,笔者的技术群里有人问了一个有趣的技术话题:单核CPU, 1G内存的超低配机器,怎么做JVM调优?这实际上是两个问题。单核CPU的超低配机器,怎么充分利用CPU?单核CPU, 1G内存的超低配机器,怎么做J…...
《计算机应用研究》投稿经历和时间节点
记录四川计算机研究院《计算机应用研究》期刊投稿经历和时间节点。 日期状态周期2022.11.09上传稿件当天显示编辑部已接收稿件,开始初审2022.11.09 – 2022.11.15初审6天2022.11.15 – 2022.12.21外审36天2022.12.21收到退修意见(邮件形式)编…...
 
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
 
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
 
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
