亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

python實現的人臉識別打卡系統

瀏覽:57日期:2022-06-20 11:26:36
目錄項目地址:簡介使用主要代碼項目地址:

https://github.com/king-xw/Face_Recogntion

簡介

本倉庫是使用python編寫的一個簡單的人臉識別考勤打卡系統

主要功能有錄入人臉信息、人臉識別打卡、設置上下班時間、導出打卡日志等

下面是各模塊截圖

首頁

python實現的人臉識別打卡系統

錄入人臉信息

python實現的人臉識別打卡系統

人臉識別打卡

python實現的人臉識別打卡系統

輸出日志

python實現的人臉識別打卡系統

使用

直接運行**==workAttendanceSystem==**.py即可

主要代碼

import datetimeimport timeimport win32apiimport win32conimport wximport wx.gridimport sqlite3from time import localtime, strftimeimport osfrom skimage import io as iioimport ioimport zlibimport dlib # 人臉識別的庫dlibimport numpy as np # 數據處理的庫numpyimport cv2 # 圖像處理的庫OpenCvimport _threadimport threadingimport win32com.clientimport tkinter as tkfrom tkinter import filedialogimport csvspk = win32com.client.Dispatch('SAPI.SpVoice')ID_NEW_REGISTER = 160ID_FINISH_REGISTER = 161ID_START_PUNCHCARD = 190ID_END_PUNCARD = 191ID_TODAY_LOGCAT = 283ID_CUSTOM_LOGCAT = 284ID_WORKING_HOURS = 301ID_OFFWORK_HOURS = 302ID_DELETE = 303ID_WORKER_UNAVIABLE = -1PATH_FACE = 'data/face_img_database/'# face recognition model, the object maps human faces into 128D vectorsfacerec = 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’)def speak_info(info): spk.Speak(info)def return_euclidean_distance(feature_1, feature_2): feature_1 = np.array(feature_1) feature_2 = np.array(feature_2) dist = np.sqrt(np.sum(np.square(feature_1 - feature_2))) print('歐式距離: ', dist) if dist > 0.4:return 'diff' else:return 'same'class WAS(wx.Frame): def __init__(self):wx.Frame.__init__(self, parent=None,, size=(920, 560))self.Folderpath = Noneself.initMenu()self.initInfoText()self.initGallery()self.initDatabase()self.initData() def initData(self):self.name = ''self.id = ID_WORKER_UNAVIABLEself.face_feature = ''self.pic_num = 0self.flag_registed = Falseself.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 BLACK')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 BLACK')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 BLACK')self.start_punchcard.SetFont(menu_Font)puncardMenu.Append(self.start_punchcard)self.end_puncard = wx.MenuItem(puncardMenu, ID_END_PUNCARD, '結束簽到')self.end_puncard.SetBitmap(wx.Bitmap('drawable/end_puncard.png'))self.end_puncard.SetTextColour('SLATE BLACK')self.end_puncard.SetFont(menu_Font)self.end_puncard.Enable(False)puncardMenu.Append(self.end_puncard)logcatMenu = wx.Menu()self.today_logcat = wx.MenuItem(logcatMenu, ID_TODAY_LOGCAT, '輸出今日日志')self.today_logcat.SetBitmap(wx.Bitmap('drawable/open_logcat.png'))self.today_logcat.SetFont(menu_Font)self.today_logcat.SetTextColour('SLATE BLACK')logcatMenu.Append(self.today_logcat)self.custom_logcat = wx.MenuItem(logcatMenu, ID_CUSTOM_LOGCAT, '輸出自定義日志')self.custom_logcat.SetBitmap(wx.Bitmap('drawable/open_logcat.png'))self.custom_logcat.SetFont(menu_Font)self.custom_logcat.SetTextColour('SLATE BLACK')logcatMenu.Append(self.custom_logcat)setMenu = wx.Menu()self.working_hours = wx.MenuItem(setMenu, ID_WORKING_HOURS, '上班時間')self.working_hours.SetBitmap(wx.Bitmap('drawable/close_logcat.png'))self.working_hours.SetFont(menu_Font)self.working_hours.SetTextColour('SLATE BLACK')setMenu.Append(self.working_hours)self.offwork_hours = wx.MenuItem(setMenu, ID_OFFWORK_HOURS, '下班時間')self.offwork_hours.SetBitmap(wx.Bitmap('drawable/open_logcat.png'))self.offwork_hours.SetFont(menu_Font)self.offwork_hours.SetTextColour('SLATE BLACK')setMenu.Append(self.offwork_hours)self.delete = wx.MenuItem(setMenu, ID_DELETE, '刪除人員')self.delete.SetBitmap(wx.Bitmap('drawable/end_puncard.png'))self.delete.SetFont(menu_Font)self.delete.SetTextColour('SLATE BLACK')setMenu.Append(self.delete)menuBar.Append(registerMenu, '&人臉錄入')menuBar.Append(puncardMenu, '&刷臉簽到')menuBar.Append(logcatMenu, '&考勤日志')menuBar.Append(setMenu, '&設置')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.ExportTodayLog, id=ID_TODAY_LOGCAT)self.Bind(wx.EVT_MENU, self.ExportCustomLog, id=ID_CUSTOM_LOGCAT)self.Bind(wx.EVT_MENU, self.SetWorkingHours, id=ID_WORKING_HOURS)self.Bind(wx.EVT_MENU, self.SetOffWorkHours, id=ID_OFFWORK_HOURS)self.Bind(wx.EVT_MENU, self.deleteBtn, id=ID_DELETE) def SetWorkingHours(self, event):global workingglobal setWorkingSignsetWorkingSign = Falseself.loadDataBase(1)# self.working_hours.Enable(True)self.working_hours = wx.GetTextFromUser(message='請輸入上班時間', caption='溫馨提示', default_value='08:00:00',parent=None)working = self.working_hourssetWorkingSign = Truepass def SetOffWorkHours(self, event):global offworkingself.loadDataBase(1)# self.offwork_hours.Enable(True)self.offwork_hours = wx.GetTextFromUser(message='請輸入下班時間', caption='溫馨提示', default_value='18:00:00',parent=None)offworking = self.offwork_hourswin32api.MessageBox(0, '請確保同時設置上班時間和下班時間并且先設置上班時間', '提醒', win32con.MB_ICONWARNING)if setWorkingSign: self.loadDataBase(4)else: win32api.MessageBox(0, '您未設置上班時間', '提醒', win32con.MB_ICONWARNING)pass def ExportTodayLog(self, event):global Folderpath1Folderpath1 = ''self.save_route1(event)if not Folderpath1 == '': self.loadDataBase(3) day = time.strftime('%Y-%m-%d') path = Folderpath1 + '/' + day + '.csv' f = open(path, ’w’, newline=’’, encoding=’utf-8’) csv_writer = csv.writer(f) csv_writer.writerow(['編號', '姓名', '打卡時間', '是否遲到']) size = len(logcat_id) index = 0 while size - 1 >= index:localtime1 = str(logcat_datetime[index]).replace(’[’, ’’).replace(’]’, ’’)csv_writer.writerow([logcat_id[index], logcat_name[index], localtime1, logcat_late[index]])index += 1; f.close()pass def ExportCustomLog(self, event):global dialogglobal t1global t2global Folderpath2Folderpath2 = ''dialog = wx.Dialog(self)Label1 = wx.StaticText(dialog, -1, '輸入員工id', pos=(30, 10))t1 = wx.TextCtrl(dialog, -1, ’’, pos=(130, 10), size=(130, -1))Label2 = wx.StaticText(dialog, -1, '輸出日期(天)', pos=(30, 50))sampleList = [u’1’, u’3’, u’7’, u’30’]t2 = wx.ComboBox(dialog, -1, value='1', pos=(130, 50), size=(130, -1), choices=sampleList, style=wx.CB_READONLY)button = wx.Button(dialog, -1, '選擇文件保存路徑', pos=(120, 90))button.Bind(wx.EVT_BUTTON, self.save_route2, button)btn_confirm = wx.Button(dialog, 1, '確認', pos=(30, 150))btn_close = wx.Button(dialog, 2, '取消', pos=(250, 150))btn_close.Bind(wx.EVT_BUTTON, self.OnClose, btn_close)btn_confirm.Bind(wx.EVT_BUTTON, self.DoCustomLog, btn_confirm)dialog.ShowModal()pass # 關閉主窗口前確認一下是否真的關閉 def OnClose(self, event):dlg = wx.MessageDialog(None, u’確定要關閉本窗口嗎?’, u’操作提示’, wx.YES_NO)if dlg.ShowModal() == wx.ID_YES: dialog.Destroy() def OnClose1(self, event):dlg = wx.MessageDialog(None, u’確定要關閉本窗口嗎?’, u’操作提示’, wx.YES_NO)if dlg.ShowModal() == wx.ID_YES: dialog1.Destroy() def OnYes(self, event):dlg = wx.MessageDialog(None, u’確定要刪除該編號的員工?’, u’操作提示’, wx.YES_NO)if dlg.ShowModal() == wx.ID_YES: return True def deleteBtn(self, event):global dialog1global t4dialog1 = wx.Dialog(self)Label1 = wx.StaticText(dialog1, -1, '輸入員工id: ', pos=(40, 34))t4 = wx.TextCtrl(dialog1, -1, ’’, pos=(130, 30), size=(130, -1))btn_confirm = wx.Button(dialog1, 1, '確認', pos=(30, 150))btn_close = wx.Button(dialog1, 2, '取消', pos=(250, 150))btn_close.Bind(wx.EVT_BUTTON, self.OnClose1, btn_close)btn_confirm.Bind(wx.EVT_BUTTON, self.deleteById, btn_confirm)dialog1.ShowModal() def DoCustomLog(self, event):if not Folderpath2 == '': number = t1.GetValue() days = t2.GetValue() flag = self.findById(number, days) print('查詢的天數是:', days) if flag:row = len(find_id)path = Folderpath2 + ’/’ + find_name[0] + ’.csv’f = open(path, ’w’, newline=’’, encoding=’utf-8’)csv_writer = csv.writer(f)csv_writer.writerow(['編號', '姓名', '打卡時間', '是否遲到'])for index in range(row): s1 = str(find_datetime[index]).replace(’[’, ’’).replace(’]’, ’’) csv_writer.writerow([str(find_id[index]), str(find_name[index]), s1, str(find_late[index])])f.close()success = wx.MessageDialog(None, ’日志保存成功,請注意查看’, ’info’, wx.OK)success.ShowModal() else:warn = wx.MessageDialog(None, ’輸入id不正確,請重新輸入’, ’info’, wx.OK)warn.ShowModal() dialog.Destroy()else: win32api.MessageBox(0, '請輸入文件導出位置', '提醒', win32con.MB_ICONWARNING)pass def deleteById(self, event):global delete_namedelete_name = []id = t4.GetValue()print('刪除員工的id為:', id)conn = sqlite3.connect('inspurer.db') # 建立數據庫連接cur = conn.cursor() # 得到游標對象sql = ’select name from worker_info where id=’ + idsql1 = ’delete from worker_info where id=’ + idsql2 = ’delete from logcat where id=’ + idlength = len(cur.execute(sql).fetchall())if length <= 0: win32api.MessageBox(0, '沒有查詢到該員工,請重新輸入ID', '提醒', win32con.MB_ICONWARNING) return Falseelse: origin = cur.execute(sql).fetchall() for row in origin:delete_name.append(row[0])name = delete_name[0]print('名字是', name) if self.OnYes(event):cur.execute(sql1)cur.execute(sql2)conn.commit()dir = PATH_FACE + namefor file in os.listdir(dir): os.remove(dir + '/' + file) print('已刪除已錄入人臉的圖片', dir + '/' + file)os.rmdir(PATH_FACE + name)print('已刪除已錄入人臉的姓名文件夾', dir)dialog1.Destroy()self.initData()return True def findById(self, id, day):global find_id, find_name, find_datetime, find_latefind_id = []find_name = []find_datetime = []find_late = []DayAgo = (datetime.datetime.now() - datetime.timedelta(days=int(day)))# 轉換為其他字符串格式:day_before = DayAgo.strftime('%Y-%m-%d')today = datetime.date.today()first = today.replace(day=1)last_month = first - datetime.timedelta(days=1)print(last_month.strftime('%Y-%m'))print(last_month)conn = sqlite3.connect('inspurer.db') # 建立數據庫連接cur = conn.cursor() # 得到游標對象sql = ’select id ,name,datetime,late from logcat where id=’ + idif day == ’30’: str = '’' sql1 = ’select id ,name,datetime,late from logcat where id=’ + id + ’ ’ + ’and datetime like ’ + str + ’%’ + last_month.strftime('%Y-%m') + ’%’ + strelse: sql1 = ’select id ,name,datetime,late from logcat where id=’ + id + ’ ’ + ’and datetime>=’ + day_beforelength = len(cur.execute(sql).fetchall())if length <= 0: return Falseelse: cur.execute(sql1) origin = cur.fetchall() for row in origin:find_id.append(row[0])find_name.append(row[1])find_datetime.append(row[2])find_late.append(row[3]) return Truepass def save_route1(self, event):global Folderpath1root = tk.Tk()root.withdraw()Folderpath1 = filedialog.askdirectory() # 獲得選擇好的文件夾pass def save_route2(self, event):global Folderpath2root = tk.Tk()root.withdraw()Folderpath2 = filedialog.askdirectory() # 獲得選擇好的文件夾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 = 0for det in dets: w = det.right() - det.left() h = det.top() - det.bottom() if w * h > maxArea:biggest_face = detmaxArea = 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_arrshape = 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] + ' 的人臉數據已存在rn')self.flag_registed = Trueself.OnFinishRegister()_thread.exit()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][biggest_face.left() + jj] if len(self.name) > 0:cv2.imencode(’.jpg’, im_blank)[1].tofile( PATH_FACE + self.name + '/img_face_' + str(self.pic_num) + '.jpg') # 正確方法self.pic_num += 1print('寫入本地:', str(PATH_FACE + self.name) + '/img_face_' + str(self.pic_num) + '.jpg')self.infoText.AppendText( self.getDateAndTime() + '圖片:' + str(PATH_FACE + self.name) + '/img_face_' + str(self.pic_num) + '.jpg保存成功rn')except: print('保存照片異常,請對準攝像頭')if self.new_register.IsEnabled(): _thread.exit()if self.pic_num == 30: self.OnFinishRegister() _thread.exit() def OnNewRegisterClicked(self, event):self.new_register.Enable(False)self.finish_register.Enable(True)self.loadDataBase(1)while self.id == ID_WORKER_UNAVIABLE: self.id = wx.GetNumberFromUser(message='請輸入您的工號(-1不可用)', prompt='工號', caption='溫馨提示', value=ID_WORKER_UNAVIABLE, 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 = ’’ breakos.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() returnif 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 + ' 的人臉數據已成功存入rn') passelse: os.rmdir(PATH_FACE + self.name) print('已刪除空文件夾', PATH_FACE + self.name)self.initData() def OnFinishRegisterClicked(self, event):self.OnFinishRegister()pass def punchcard_cap(self, event):# 調用設置上班時間的函數,根據當前時間和上班時間判斷是否遲到self.cap = cv2.VideoCapture(0)# cap.set(propId, value)# 設置視頻參數,propId設置的視頻參數,value設置的參數值# self.cap.set(3, 600)# self.cap.set(4,600)# cap是否初始化成功self.loadDataBase(5)print('長度是')print(len(working_times))if len(working_times) == 0: win32api.MessageBox(0, '您未設置上班時間,請先設置上班時間后再設置下班時間', '提醒', win32con.MB_ICONWARNING) self.start_punchcard.Enable(True) self.end_puncard.Enable(False)else: working = working_times[0] print('-----------') print(working) offworking = offworking_times[0] print('-----------') print(offworking) while self.cap.isOpened():# cap.read()# 返回兩個值:# 一個布爾值true/false,用來判斷讀取視頻是否成功/是否到視頻末尾# 圖像對象,圖像的三維矩陣flag, im_rd = self.cap.read()# 每幀數據延時1ms,延時為0讀取的是靜態幀kk = cv2.waitKey(1)# 人臉數 detsdets = 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, 255), 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': # 找到了相似臉 print('same') flag = 0 nowdt = self.getDateAndTime() for j, logcat_name in enumerate(self.logcat_name):if logcat_name == self.knew_name[i] and nowdt[0:nowdt.index(' ')] == self.logcat_datetime[ j][0:self.logcat_datetime[ j].index(' ')]: self.infoText.AppendText(nowdt + '工號:' + str(self.knew_id[i]) + ' 姓名:' + self.knew_name[i] + ' 簽到失敗,重復簽到rn') speak_info(self.knew_name[i] + ' 簽到失敗,重復簽到 ') flag = 1 break if flag == 1:break if nowdt[nowdt.index(' ') + 1:-1] <= working:self.infoText.AppendText(nowdt + '工號:' + str(self.knew_id[i]) + ' 姓名:' + self.knew_name[i] + ' 成功簽到,且未遲到rn')speak_info(self.knew_name[i] + ' 成功簽到 ')self.insertARow([self.knew_id[i], self.knew_name[i], nowdt, '否'], 2) elif offworking >= nowdt[nowdt.index(' ') + 1:-1] >= working:self.infoText.AppendText(nowdt + '工號:' + str(self.knew_id[i]) + ' 姓名:' + self.knew_name[i] + ' 成功簽到,但遲到了rn')speak_info(self.knew_name[i] + ' 成功簽到,但遲到了 ')self.insertARow([self.knew_id[i], self.knew_name[i], nowdt, '是'], 2) elif nowdt[nowdt.index(' ') + 1:-1] > offworking:self.infoText.AppendText(nowdt + '工號:' + str(self.knew_id[i]) + ' 姓名:' + self.knew_name[i] + ' 簽到失敗,超過簽到時間rn')speak_info(self.knew_name[i] + ' 簽到失敗,超過下班時間 ') self.loadDataBase(2) break if self.start_punchcard.IsEnabled():self.bmp.SetBitmap(wx.Bitmap(self.pic_index))_thread.exit() def OnStartPunchCardClicked(self, event):self.start_punchcard.Enable(False)self.end_puncard.Enable(True)self.loadDataBase(2)threading.Thread(target=self.punchcard_cap, args=(event,)).start()pass def OnEndPunchCardClicked(self, event):self.start_punchcard.Enable(True)self.end_puncard.Enable(False)pass def initInfoText(self):# 少了這兩句infoText背景顏色設置失敗,莫名奇怪resultText = wx.StaticText(parent=self, pos=(10, 20), size=(90, 60))resultText.SetBackgroundColour(wx.GREEN)# resultText.SetBackgroundColour((12,12,12))self.info = 'rn' + self.getDateAndTime() + '程序初始化成功rn'# 第二個參數水平混動條self.infoText = wx.TextCtrl(parent=self, size=(320, 500), style=(wx.TE_MULTILINE | wx.HSCROLL | wx.TE_READONLY))# 前景色,也就是字體顏色self.infoText.SetForegroundColour(’Black’)self.infoText.SetLabel(self.info)font = wx.Font()font.SetPointSize(12)font.SetWeight(wx.BOLD)font.SetUnderlined(True)self.infoText.SetFont(font)self.infoText.SetBackgroundColour(’WHITE’)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.execute(’’’create table if not exists time (id intconstraint table_name_pkprimary key, working_time time not null, offwork_time time 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('寫日志成功') passcur.close()conn.commit()conn.close()pass def loadDataBase(self, type):nowday = self.getDateAndTime()day = nowday[0:nowday.index(' ')]print(day)global logcat_id, logcat_name, logcat_datetime, logcat_late, working_times, offworking_timesconn = 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])if type == 3: logcat_id = [] logcat_name = [] logcat_datetime = [] logcat_late = [] s = '’' sql = ’select w.id,w.name,l.datetime,l.late from worker_info w left join logcat l on w.id=l.id and l.datetime like’ + ’ ’ + s + day + ’%’ + s + ’ ’ + ’order by datetime desc’ print(sql) cur.execute(sql) origin = cur.fetchall() for row in origin:print(row[0])logcat_id.append(row[0])print(row[1])logcat_name.append(row[1])print(row[2])logcat_datetime.append(row[2])print(row[3])logcat_late.append(row[3])if type == 4: sql = ’select working_time from time’ cur.execute(sql) countResult = (cur.fetchall()) print(countResult) str = '’' if not countResult:sql = ’insert into time (id,working_time,offworking_time) values (1,’ + str + working + str + ’,’ + str + offworking + str + ’)’cur.execute(sql)print(sql)conn.commit()print('插入時間成功') else:str='’'sql = ’update time set working_time=’ + str + working + str + ’,offworking_time=’ + str + offworking + str + ’ where id=1’cur.execute(sql)conn.commit()print(sql)print('更新時間成功')if type==5: sql = ’select working_time,offworking_time from time’ cur.execute(sql) print(sql) origin = cur.fetchall() print(origin) working_times = [] offworking_times = [] for row in origin:print('這是數據庫取出的上班時間')print(row[0])working_times.append(row[0])print('這是數據庫取出的下班時間')print(row[1])offworking_times.append(row[1])cur.close()conn.commit()conn.close()passapp = wx.App()frame = WAS()frame.Show()app.MainLoop()

以上就是python實現的人臉識別打卡系統的詳細內容,更多關于python 人臉識別打卡的資料請關注好吧啦網其它相關文章!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 国产乱色 | 六月丁香伊人 | 亚洲国产成人久久99精品 | 一区 在线播放 | 精品在线播放 | 欧洲在线观看在线视频吗 | 国产一级特黄aa毛片 | 日韩欧美成人免费中文字幕 | 欧美性色黄大片www 欧美性色黄大片一级毛片视频 | 国产三级全黄 | 分享一个无毒不卡免费国产 | 91久久国产精品视频 | 欧美综合图区亚欧综合图区 | 美国一级毛片片免费 | 亚洲第五色综合网 | 日韩精品在线观看免费 | 精品湿 | 欧美一区二区三区在线播放 | 韩国深夜福利视频19禁在线观看 | 亚洲精品国产综合久久一线 | 欧日韩一区二区三区 | 搞黄视频在线观看 | 黄色性生活视频 | 精品久久久一二三区 | 久久国产精品-久久精品 | 激情婷婷色 | 日本一级毛片毛片一级毛片 | xxxx久久| 拍拍拍精品视频在线观看 | 三级欧美在线 | 中文字幕成人乱码在线电影 | 2022色婷婷综合久久久 | 国产专区自拍 | 国产日本欧美亚洲精品视 | 国产欧美专区在线观看 | 国产精品一国产精品 | 在线观看亚洲 | 欧美成人精品手机在线观看 | 国产91精品高清一区二区三区 | 日韩一级黄色毛片 | 欧美日韩亚洲精品一区二区三区 |