python opencv人脸识别考勤系统的完整源码
作者:alicema1111 发布时间:2022-03-20 21:15:43
标签:python,人脸识别,考勤系统
如需安装运行环境或远程调试,可加QQ905733049, 或QQ2945218359由专业技术人员远程协助!
运行结果如下:
代码如下:
import wx
import wx.grid
from time import localtime,strftime
import os
import io
import zlib
import dlib # 人脸识别的库dlib
import numpy as np # 数据处理的库numpy
import cv2 # 图像处理的库OpenCv
import _thread
import threading
ID_NEW_REGISTER = 160
ID_FINISH_REGISTER = 161
ID_START_PUNCHCARD = 190
ID_END_PUNCARD = 191
ID_OPEN_LOGCAT = 283
ID_CLOSE_LOGCAT = 284
ID_WORKER_UNAVIABLE = -1
PATH_FACE = "data/face_img_database/"
# face recognition model, the object maps human faces into 128D vectors
facerec = dlib.face_recognition_model_v1("model/dlib_face_recognition_resnet_model_v1.dat")
# Dlib 预测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('model/shape_predictor_68_face_landmarks.dat')
class WAS(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,parent=None,title="员工考勤系统",size=(920,560))
self.initMenu()
self.initInfoText()
self.initGallery()
self.initDatabase()
self.initData()
def initData(self):
self.name = ""
self.id =ID_WORKER_UNAVIABLE
self.face_feature = ""
self.pic_num = 0
self.flag_registed = False
self.puncard_time = "21:00:00"
self.loadDataBase(1)
def initMenu(self):
menuBar = wx.MenuBar() #生成菜单栏
menu_Font = wx.Font()#Font(faceName="consolas",pointsize=20)
menu_Font.SetPointSize(14)
menu_Font.SetWeight(wx.BOLD)
registerMenu = wx.Menu() #生成菜单
self.new_register = wx.MenuItem(registerMenu,ID_NEW_REGISTER,"新建录入")
self.new_register.SetBitmap(wx.Bitmap("drawable/new_register.png"))
self.new_register.SetTextColour("SLATE BLUE")
self.new_register.SetFont(menu_Font)
registerMenu.Append(self.new_register)
self.finish_register = wx.MenuItem(registerMenu,ID_FINISH_REGISTER,"完成录入")
self.finish_register.SetBitmap(wx.Bitmap("drawable/finish_register.png"))
self.finish_register.SetTextColour("SLATE BLUE")
self.finish_register.SetFont(menu_Font)
self.finish_register.Enable(False)
registerMenu.Append(self.finish_register)
puncardMenu = wx.Menu()
self.start_punchcard = wx.MenuItem(puncardMenu,ID_START_PUNCHCARD,"开始签到")
self.start_punchcard.SetBitmap(wx.Bitmap("drawable/start_punchcard.png"))
self.start_punchcard.SetTextColour("SLATE BLUE")
self.start_punchcard.SetFont(menu_Font)
puncardMenu.Append(self.start_punchcard)
self.close_logcat = wx.MenuItem(logcatMenu, ID_CLOSE_LOGCAT, "关闭日志")
self.close_logcat.SetBitmap(wx.Bitmap("drawable/close_logcat.png"))
self.close_logcat.SetFont(menu_Font)
self.close_logcat.SetTextColour("SLATE BLUE")
logcatMenu.Append(self.close_logcat)
menuBar.Append(registerMenu,"&人脸录入")
menuBar.Append(puncardMenu,"&刷脸签到")
menuBar.Append(logcatMenu,"&考勤日志")
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU,self.OnNewRegisterClicked,id=ID_NEW_REGISTER)
self.Bind(wx.EVT_MENU,self.OnFinishRegisterClicked,id=ID_FINISH_REGISTER)
self.Bind(wx.EVT_MENU,self.OnStartPunchCardClicked,id=ID_START_PUNCHCARD)
self.Bind(wx.EVT_MENU,self.OnEndPunchCardClicked,id=ID_END_PUNCARD)
self.Bind(wx.EVT_MENU,self.OnOpenLogcatClicked,id=ID_OPEN_LOGCAT)
self.Bind(wx.EVT_MENU,self.OnCloseLogcatClicked,id=ID_CLOSE_LOGCAT)
pass
def OnCloseLogcatClicked(self,event):
self.SetSize(920,560)
self.initGallery()
pass
def register_cap(self,event):
# 创建 cv2 摄像头对象
self.cap = cv2.VideoCapture(0)
# cap.set(propId, value)
# 设置视频参数,propId设置的视频参数,value设置的参数值
# self.cap.set(3, 600)
# self.cap.set(4,600)
# cap是否初始化成功
while self.cap.isOpened():
# cap.read()
# 返回两个值:
# 一个布尔值true/false,用来判断读取视频是否成功/是否到视频末尾
# 图像对象,图像的三维矩阵
flag, im_rd = self.cap.read()
# 每帧数据延时1ms,延时为0读取的是静态帧
kk = cv2.waitKey(1)
# 人脸数 dets
dets = detector(im_rd, 1)
# 检测到人脸
if len(dets) != 0:
biggest_face = dets[0]
#取占比最大的脸
maxArea = 0
for det in dets:
w = det.right() - det.left()
h = det.top()-det.bottom()
if w*h > maxArea:
biggest_face = det
maxArea = w*h
# 绘制矩形框
cv2.rectangle(im_rd, tuple([biggest_face.left(), biggest_face.top()]),
tuple([biggest_face.right(), biggest_face.bottom()]),
(255, 0, 0), 2)
img_height, img_width = im_rd.shape[:2]
image1 = cv2.cvtColor(im_rd, cv2.COLOR_BGR2RGB)
pic = wx.Bitmap.FromBuffer(img_width, img_height, image1)
# 显示图片在panel上
self.bmp.SetBitmap(pic)
# 获取当前捕获到的图像的所有人脸的特征,存储到 features_cap_arr
shape = predictor(im_rd, biggest_face)
features_cap = facerec.compute_face_descriptor(im_rd, shape)
# 对于某张人脸,遍历所有存储的人脸特征
for i,knew_face_feature in enumerate(self.knew_face_feature):
# 将某张人脸与存储的所有人脸数据进行比对
compare = return_euclidean_distance(features_cap, knew_face_feature)
if compare == "same": # 找到了相似脸
self.infoText.AppendText(self.getDateAndTime()+"工号:"+str(self.knew_id[i])
+" 姓名:"+self.knew_name[i]+" 的人脸数据已存在\r\n")
self.flag_registed = True
self.OnFinishRegister()
_thread.exit()
# print(features_known_arr[i][-1])
face_height = biggest_face.bottom()-biggest_face.top()
face_width = biggest_face.right()- biggest_face.left()
im_blank = np.zeros((face_height, face_width, 3), np.uint8)
try:
for ii in range(face_height):
for jj in range(face_width):
im_blank[ii][jj] = im_rd[biggest_face.top() + ii]parent=self.bmp,max=100000000,min=ID_WORKER_UNAVIABLE)
for knew_id in self.knew_id:
if knew_id == self.id:
self.id = ID_WORKER_UNAVIABLE
wx.MessageBox(message="工号已存在,请重新输入", caption="警告")
while self.name == '':
self.name = wx.GetTextFromUser(message="请输入您的的姓名,用于创建姓名文件夹",
caption="温馨提示",
default_value="", parent=self.bmp)
# 监测是否重名
for exsit_name in (os.listdir(PATH_FACE)):
if self.name == exsit_name:
wx.MessageBox(message="姓名文件夹已存在,请重新输入", caption="警告")
self.name = ''
break
os.makedirs(PATH_FACE+self.name)
_thread.start_new_thread(self.register_cap,(event,))
pass
def OnFinishRegister(self):
self.new_register.Enable(True)
self.finish_register.Enable(False)
self.cap.release()
self.bmp.SetBitmap(wx.Bitmap(self.pic_index))
if self.flag_registed == True:
dir = PATH_FACE + self.name
for file in os.listdir(dir):
os.remove(dir+"/"+file)
print("已删除已录入人脸的图片", dir+"/"+file)
os.rmdir(PATH_FACE + self.name)
print("已删除已录入人脸的姓名文件夹", dir)
self.initData()
return
if self.pic_num>0:
pics = os.listdir(PATH_FACE + self.name)
feature_list = []
feature_average = []
for i in range(len(pics)):
pic_path = PATH_FACE + self.name + "/" + pics[i]
print("正在读的人脸图像:", pic_path)
img = iio.imread(pic_path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
dets = detector(img_gray, 1)
if len(dets) != 0:
shape = predictor(img_gray, dets[0])
face_descriptor = facerec.compute_face_descriptor(img_gray, shape)
feature_list.append(face_descriptor)
else:
face_descriptor = 0
print("未在照片中识别到人脸")
if len(feature_list) > 0:
for j in range(128):
#防止越界
feature_average.append(0)
for i in range(len(feature_list)):
feature_average[j] += feature_list[i][j]
feature_average[j] = (feature_average[j]) / len(feature_list)
self.insertARow([self.id,self.name,feature_average],1)
self.infoText.AppendText(self.getDateAndTime()+"工号:"+str(self.id)
+" 姓名:"+self.name+" 的人脸数据已成功存入\r\n")
pass
else:
os.rmdir(PATH_FACE + self.name)
print("已删除空文件夹",PATH_FACE + self.name)
self.initData()
def OnFinishRegisterClicked(self,event):
self.OnFinishRegister()
pass
def OnStartPunchCardClicked(self,event):
# cur_hour = datetime.datetime.now().hour
# print(cur_hour)
# if cur_hour>=8 or cur_hour<6:
# wx.MessageBox(message='''您错过了今天的签到时间,请明天再来\n
# 每天的签到时间是:6:00~7:59''', caption="警告")
# return
self.start_punchcard.Enable(False)
self.end_puncard.Enable(True)
self.loadDataBase(2)
threading.Thread(target=self.punchcard_cap,args=(event,)).start()
#_thread.start_new_thread(self.punchcard_cap,(event,))
pass
def OnEndPunchCardClicked(self,event):
self.start_punchcard.Enable(True)
self.end_puncard.Enable(False)
pass
def initGallery(self):
self.pic_index = wx.Image("drawable/index.png", wx.BITMAP_TYPE_ANY).Scale(600, 500)
self.bmp = wx.StaticBitmap(parent=self, pos=(320,0), bitmap=wx.Bitmap(self.pic_index))
pass
def getDateAndTime(self):
dateandtime = strftime("%Y-%m-%d %H:%M:%S",localtime())
return "["+dateandtime+"]"
#数据库部分
#初始化数据库
def initDatabase(self):
conn = sqlite3.connect("inspurer.db") #建立数据库连接
cur = conn.cursor() #得到游标对象
cur.execute('''create table if not exists worker_info
(name text not null,
id int not null primary key,
face_feature array not null)''')
cur.execute('''create table if not exists logcat
(datetime text not null,
id int not null,
name text not null,
late text not null)''')
cur.close()
conn.commit()
conn.close()
def adapt_array(self,arr):
out = io.BytesIO()
np.save(out, arr)
out.seek(0)
dataa = out.read()
# 压缩数据流
return sqlite3.Binary(zlib.compress(dataa, zlib.Z_BEST_COMPRESSION))
def convert_array(self,text):
out = io.BytesIO(text)
out.seek(0)
dataa = out.read()
# 解压缩数据流
out = io.BytesIO(zlib.decompress(dataa))
return np.load(out)
def insertARow(self,Row,type):
conn = sqlite3.connect("inspurer.db") # 建立数据库连接
cur = conn.cursor() # 得到游标对象
if type == 1:
cur.execute("insert into worker_info (id,name,face_feature) values(?,?,?)",
(Row[0],Row[1],self.adapt_array(Row[2])))
print("写人脸数据成功")
if type == 2:
cur.execute("insert into logcat (id,name,datetime,late) values(?,?,?,?)",
(Row[0],Row[1],Row[2],Row[3]))
print("写日志成功")
pass
cur.close()
conn.commit()
conn.close()
pass
def loadDataBase(self,type):
conn = sqlite3.connect("inspurer.db") # 建立数据库连接
cur = conn.cursor() # 得到游标对象
if type == 1:
self.knew_id = []
self.knew_name = []
self.knew_face_feature = []
cur.execute('select id,name,face_feature from worker_info')
origin = cur.fetchall()
for row in origin:
print(row[0])
self.knew_id.append(row[0])
print(row[1])
self.knew_name.append(row[1])
print(self.convert_array(row[2]))
self.knew_face_feature.append(self.convert_array(row[2]))
if type == 2:
self.logcat_id = []
self.logcat_name = []
self.logcat_datetime = []
self.logcat_late = []
cur.execute('select id,name,datetime,late from logcat')
origin = cur.fetchall()
for row in origin:
print(row[0])
self.logcat_id.append(row[0])
print(row[1])
self.logcat_name.append(row[1])
print(row[2])
self.logcat_datetime.append(row[2])
print(row[3])
self.logcat_late.append(row[3])
pass
app = wx.App()
frame = WAS()
frame.Show()
app.MainLoop()
运行结果如下:
C++学习参考实例:
使用C++ MFC编写一个简单的五子棋游戏程序
https://www.jb51.net/article/180940.htm
C++实现简易五子棋游戏
https://www.jb51.net/article/190548.htm
c++ 基于opencv 识别、定位二维码
https://www.jb51.net/article/207158.htm
来源:https://blog.csdn.net/alicema1111/article/details/116088711


猜你喜欢
- 背景: 在我们使用Golang进行开发过程中,总是绕不开对字符或字符串的处理,而在Golang语言中,对字符和字符串的处理方式可能和其他语言
- 前言:python利用matplotlib库中的plt.ion()函数实现即时数据动态显示:1.非定长的时间轴代码示例:# -*- codi
- Python中try块可以捕获测试代码块中的错误。except块可以处理错误。finally块可以执行代码,而不管try-和except块的
- 本文实例为大家分享了asp.net存储和读取数据库图片的具体代码,供大家参考,具体内容如下1. 创建asp.net web窗体项目代码如下:
- 1、bootstrapBootstrap 是Twitter推出的一个用于前端开发的,一个用于 HTML、CSS 和 JS 开发的开源工具包,
- Python模块,简单说就是一个.py文件,其中可以包含我们需要的任意Python代码。迄今为止,我们所编写的所有程序都包含在单独的.py文
- 本文实例为大家分享了PHP变量传值赋值和引用赋值变量销毁的具体代码,供大家参考,具体内容如下<?php $a = 100
- mulLine = """Hello!!! Wellcome to Python's world! T
- 1 算术运算add(other)比如进行数学运算加上具体的一个数字data['open'].add(1)2018-02-27
- 具体如何屏蔽更多的快捷键可以自行google搜索。 这里要说的是如何屏蔽后去执行自定义的事件。这里为了方便使用的Kibo做例子,使用goog
- 1.文本框只能输入数字代码(小数点也不能输入)<input onkeyup="this.value=this.va
- --处理表重复记录(查询和删除)/*****************************************************
- 本文实例为大家分享了利用python和OpenCV实现图像拼接,供大家参考,具体内容如下python+OpenCV实现image stitc
- 先给大家展示下效果图,大家感觉不错,请参考实现代码:实现原理:点击按钮,往需要动画的div中添加或移除拥有动画效果的class。由于微信小程
- 今天写了这样的代码 DECLARE @atr NVARCHAR(20) SET @atr = NULL IF(@atr = NULL) BE
- 本文实例讲解了4种JavaScript实现简单tab选项卡切换的方法,分享给大家供大家参考,具体内容如下效果图: 方法一:for循
- 随着当今世界的发展,计算机视觉技术的应用越来越广泛。伴随着硬件设备的不断升级,构造复杂的计算机视觉应用变得越来越容易了。OpenCV像是一个
- 一、引子Django 分页查询并返回 json ,需要将返回的 queryset 序列化, demo 如下:# coding=UTF-8im
- 代码如下: '排序 Function Sort1(ary) Dim KeepChecking,I,FirstValue,Second
- reduce函数原本在python2中也是个内置函数,不过在python3中被移到functools模块中。reduce函数先从列表(或序列