人脸考勤机项目
文章内容如下:
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收到退修意见(邮件形式)编…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
