Project Address:
/king-xw/Face_Recogntion
synopsis
This repository is a simple face recognition attendance clocking system written in python.
The main functions are to enter face information, face recognition punch card, set the time of commuting to and from work, export the punch card log, etc.
Here are screenshots of the modules
home page (of a website)
Entering face information
facial recognition clocking in
Output Log
utilization
Just run **==workAttendanceSystem===**.py directly
Primary Code
import datetime import time import win32api import win32con import wx import import sqlite3 from time import localtime, strftime import os from skimage import io as iio import io import zlib import dlib # Library dlib for face recognition import numpy as np # The library numpy for data processing import cv2 # Image processing library OpenCv import _thread import threading import import tkinter as tk from tkinter import filedialog import csv spk = ("") ID_NEW_REGISTER = 160 ID_FINISH_REGISTER = 161 ID_START_PUNCHCARD = 190 ID_END_PUNCARD = 191 ID_TODAY_LOGCAT = 283 ID_CUSTOM_LOGCAT = 284 ID_WORKING_HOURS = 301 ID_OFFWORK_HOURS = 302 ID_DELETE = 303 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 predictor detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor('model/shape_predictor_68_face_landmarks.dat') def speak_info(info): (info) def return_euclidean_distance(feature_1, feature_2): feature_1 = (feature_1) feature_2 = (feature_2) dist = (((feature_1 - feature_2))) print("European distance:", dist) if dist > 0.4: return "diff" else: return "same" class WAS(): def __init__(self): .__init__(self, parent=None, title="Intelligent Monitoring and Punching System.", size=(920, 560)) = None () () () () () def initData(self): = "" = ID_WORKER_UNAVIABLE self.face_feature = "" self.pic_num = 0 self.flag_registed = False (1) def initMenu(self): menuBar = () # Generate menu bar menu_Font = () # Font(faceName="consolas",pointsize=20) menu_Font.SetPointSize(14) menu_Font.SetWeight() registerMenu = () # Generate menu self.new_register = (registerMenu, ID_NEW_REGISTER, "New Entry") self.new_register.SetBitmap(("drawable/new_register.png")) self.new_register.SetTextColour("SLATE BLACK") self.new_register.SetFont(menu_Font) (self.new_register) self.finish_register = (registerMenu, ID_FINISH_REGISTER, "Completion of entry") self.finish_register.SetBitmap(("drawable/finish_register.png")) self.finish_register.SetTextColour("SLATE BLACK") self.finish_register.SetFont(menu_Font) self.finish_register.Enable(False) (self.finish_register) puncardMenu = () self.start_punchcard = (puncardMenu, ID_START_PUNCHCARD, "Start checking in.") self.start_punchcard.SetBitmap(("drawable/start_punchcard.png")) self.start_punchcard.SetTextColour("SLATE BLACK") self.start_punchcard.SetFont(menu_Font) (self.start_punchcard) self.end_puncard = (puncardMenu, ID_END_PUNCARD, "End check-in.") self.end_puncard.SetBitmap(("drawable/end_puncard.png")) self.end_puncard.SetTextColour("SLATE BLACK") self.end_puncard.SetFont(menu_Font) self.end_puncard.Enable(False) (self.end_puncard) logcatMenu = () self.today_logcat = (logcatMenu, ID_TODAY_LOGCAT, "Output today's log.") self.today_logcat.SetBitmap(("drawable/open_logcat.png")) self.today_logcat.SetFont(menu_Font) self.today_logcat.SetTextColour("SLATE BLACK") (self.today_logcat) self.custom_logcat = (logcatMenu, ID_CUSTOM_LOGCAT, "Output custom logs") self.custom_logcat.SetBitmap(("drawable/open_logcat.png")) self.custom_logcat.SetFont(menu_Font) self.custom_logcat.SetTextColour("SLATE BLACK") (self.custom_logcat) setMenu = () self.working_hours = (setMenu, ID_WORKING_HOURS, "Office hours.") self.working_hours.SetBitmap(("drawable/close_logcat.png")) self.working_hours.SetFont(menu_Font) self.working_hours.SetTextColour("SLATE BLACK") (self.working_hours) self.offwork_hours = (setMenu, ID_OFFWORK_HOURS, "Off hours.") self.offwork_hours.SetBitmap(("drawable/open_logcat.png")) self.offwork_hours.SetFont(menu_Font) self.offwork_hours.SetTextColour("SLATE BLACK") (self.offwork_hours) = (setMenu, ID_DELETE, "Deletion of persons") (("drawable/end_puncard.png")) (menu_Font) ("SLATE BLACK") () (registerMenu, "& Face Entry") (puncardMenu, "& swipe to sign in.") (logcatMenu, "& Attendance Log") (setMenu, "& Settings") (menuBar) (wx.EVT_MENU, , id=ID_NEW_REGISTER) (wx.EVT_MENU, , id=ID_FINISH_REGISTER) (wx.EVT_MENU, , id=ID_START_PUNCHCARD) (wx.EVT_MENU, , id=ID_END_PUNCARD) (wx.EVT_MENU, , id=ID_TODAY_LOGCAT) (wx.EVT_MENU, , id=ID_CUSTOM_LOGCAT) (wx.EVT_MENU, , id=ID_WORKING_HOURS) (wx.EVT_MENU, , id=ID_OFFWORK_HOURS) (wx.EVT_MENU, , id=ID_DELETE) def SetWorkingHours(self, event): global working global setWorkingSign setWorkingSign = False (1) # self.working_hours.Enable(True) self.working_hours = (message="Please enter office hours.", caption="Warm Tips", default_value="08:00:00", parent=None) working = self.working_hours setWorkingSign = True pass def SetOffWorkHours(self, event): global offworking (1) # self.offwork_hours.Enable(True) self.offwork_hours = (message="Please enter off-duty hours.", caption="Warm Tips", default_value="18:00:00", parent=None) offworking = self.offwork_hours (0, "Please make sure to set both the start and end times and set the start time first.", "Reminder.", win32con.MB_ICONWARNING) if setWorkingSign: (4) else: (0, "You have not set your office hours.", "Reminder.", win32con.MB_ICONWARNING) pass def ExportTodayLog(self, event): global Folderpath1 Folderpath1 = "" self.save_route1(event) if not Folderpath1 == "": (3) day = ("%Y-%m-%d") path = Folderpath1 + "/" + day + ".csv" f = open(path, 'w', newline='', encoding='utf-8') csv_writer = (f) csv_writer.writerow(["No.", "Name", "Punch time.", "Whether or not you're late."]) 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; () pass def ExportCustomLog(self, event): global dialog global t1 global t2 global Folderpath2 Folderpath2 = "" dialog = (self) Label1 = (dialog, -1, "Enter employee id", pos=(30, 10)) t1 = (dialog, -1, '', pos=(130, 10), size=(130, -1)) Label2 = (dialog, -1, "Output Date(sky)", pos=(30, 50)) sampleList = [u'1', u'3', u'7', u'30'] t2 = (dialog, -1, value="1", pos=(130, 50), size=(130, -1), choices=sampleList, style=wx.CB_READONLY) button = (dialog, -1, "Select file save path", pos=(120, 90)) (wx.EVT_BUTTON, self.save_route2, button) btn_confirm = (dialog, 1, "Acknowledged.", pos=(30, 150)) btn_close = (dialog, 2, "Cancel.", pos=(250, 150)) btn_close.Bind(wx.EVT_BUTTON, , btn_close) btn_confirm.Bind(wx.EVT_BUTTON, , btn_confirm) () pass # Confirm that the main window is actually closed before closing it def OnClose(self, event): dlg = (None, u'Sure you want to close this window?', u'Operation Tips', wx.YES_NO) if () == wx.ID_YES: () def OnClose1(self, event): dlg = (None, u'Sure you want to close this window?', u'Operation Tips', wx.YES_NO) if () == wx.ID_YES: () def OnYes(self, event): dlg = (None, u'Sure you want to delete the employee with that number?', u'Operation Tips', wx.YES_NO) if () == wx.ID_YES: return True def deleteBtn(self, event): global dialog1 global t4 dialog1 = (self) Label1 = (dialog1, -1, "Enter employee id: ", pos=(40, 34)) t4 = (dialog1, -1, '', pos=(130, 30), size=(130, -1)) btn_confirm = (dialog1, 1, "Acknowledged.", pos=(30, 150)) btn_close = (dialog1, 2, "Cancel.", pos=(250, 150)) btn_close.Bind(wx.EVT_BUTTON, self.OnClose1, btn_close) btn_confirm.Bind(wx.EVT_BUTTON, , btn_confirm) () def DoCustomLog(self, event): if not Folderpath2 == "": number = () days = () flag = (number, days) print("The number of days for the query is:", days) if flag: row = len(find_id) path = Folderpath2 + '/' + find_name[0] + '.csv' f = open(path, 'w', newline='', encoding='utf-8') csv_writer = (f) csv_writer.writerow(["No.", "Name", "Punch time.", "Whether or not you're late."]) 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])]) () success = (None, 'Log saved successfully, please note to check', 'info', ) () else: warn = (None, 'The input id is incorrect, please re-enter it', 'info', ) () () else: (0, "Please enter the file export location.", "Reminder.", win32con.MB_ICONWARNING) pass def deleteById(self, event): global delete_name delete_name = [] id = () print("Delete employee with id:", id) conn = ("") # Establishment of database connections cur = () # Get the cursor object sql = 'select name from worker_info where id=' + id sql1 = 'delete from worker_info where id=' + id sql2 = 'delete from logcat where id=' + id length = len((sql).fetchall()) if length <= 0: (0, "The employee was not queried, please re-enter the ID", "Reminder.", win32con.MB_ICONWARNING) return False else: origin = (sql).fetchall() for row in origin: delete_name.append(row[0]) name = delete_name[0] print("Name.", name) if (event): (sql1) (sql2) () dir = PATH_FACE + name for file in (dir): (dir + "/" + file) print("Pictures of recorded faces have been deleted.", dir + "/" + file) (PATH_FACE + name) print("Folders of names with faces entered have been deleted.", dir) () () return True def findById(self, id, day): global find_id, find_name, find_datetime, find_late find_id = [] find_name = [] find_datetime = [] find_late = [] DayAgo = (() - (days=int(day))) # Convert to other string formats. day_before = ("%Y-%m-%d") today = () first = (day=1) last_month = first - (days=1) print(last_month.strftime("%Y-%m")) print(last_month) conn = ("") # Establishment of database connections cur = () # Get the cursor object sql = 'select id ,name,datetime,late from logcat where id=' + id if day == '30': str = "'" sql1 = 'select id ,name,datetime,late from logcat where id=' + id + ' ' + 'and datetime like ' + str + '%' + last_month.strftime( "%Y-%m") + '%' + str else: sql1 = 'select id ,name,datetime,late from logcat where id=' + id + ' ' + 'and datetime>=' + day_before length = len((sql).fetchall()) if length <= 0: return False else: (sql1) origin = () 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 True pass def save_route1(self, event): global Folderpath1 root = () () Folderpath1 = () # Get the selected folder pass def save_route2(self, event): global Folderpath2 root = () () Folderpath2 = () # Get the selected folder pass def register_cap(self, event): # Create a cv2 camera object = (0) # (propId, value) # set video parameters, video parameters set by propId, parameter values set by value # (3, 600) # (4,600) # cap is initialized successfully or not while (): # () # Returns two values: # A boolean value true/false to determine if reading the video was successful/whether it reached the end of the video # Image objects, 3D matrices of images flag, im_rd = () # 1ms delay per data frame, delay 0 reads static frames kk = (1) # of faces dets dets = detector(im_rd, 1) # Face detected if len(dets) != 0: biggest_face = dets[0] # Take the face with the largest percentage maxArea = 0 for det in dets: w = () - () h = () - () if w * h > maxArea: biggest_face = det maxArea = w * h # Draw rectangular boxes (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 = (im_rd, cv2.COLOR_BGR2RGB) pic = (img_width, img_height, image1) # Show image on panel (pic) # Get the features of all faces in the currently captured image, stored in features_cap_arr shape = predictor(im_rd, biggest_face) features_cap = facerec.compute_face_descriptor(im_rd, shape) # For a given face, iterate over all stored face features for i, knew_face_feature in enumerate(self.knew_face_feature): # Match a face with all stored face data compare = return_euclidean_distance(features_cap, knew_face_feature) if compare == "same": # And found a face to match (() + "Work number:" + str(self.knew_id[i]) + " Name:" + self.knew_name[i] + "'s face data already exists\r\n") self.flag_registed = True () _thread.exit() face_height = biggest_face.bottom() - biggest_face.top() face_width = biggest_face.right() - biggest_face.left() im_blank = ((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() > 0: ('.jpg', im_blank)[1].tofile( PATH_FACE + + "/img_face_" + str(self.pic_num) + ".jpg") # The right way self.pic_num += 1 print("Write Local:", str(PATH_FACE + ) + "/img_face_" + str(self.pic_num) + ".jpg") ( () + "Picture:" + str(PATH_FACE + ) + "/img_face_" + str( self.pic_num) + ".jpg saved successfully\r\n") except: print("Saving photo abnormal. Please focus on the camera.") if self.new_register.IsEnabled(): _thread.exit() if self.pic_num == 30: () _thread.exit() def OnNewRegisterClicked(self, event): self.new_register.Enable(False) self.finish_register.Enable(True) (1) while == ID_WORKER_UNAVIABLE: = (message="Please enter your job number(-1unavailable)", prompt="Work number.", caption="Warm Tips", value=ID_WORKER_UNAVIABLE, parent=, max=100000000, min=ID_WORKER_UNAVIABLE) for knew_id in self.knew_id: if knew_id == : = ID_WORKER_UNAVIABLE (message="Work number already exists, please re-enter.", caption="Warning.") while == '': = (message="Please enter your name to create a name folder.", caption="Warm Tips", default_value="", parent=) # Monitor for renaming for exsit_name in ((PATH_FACE)): if == exsit_name: (message="Name folder already exists, please re-enter.", caption="Warning.") = '' break (PATH_FACE + ) _thread.start_new_thread(self.register_cap, (event,)) pass def OnFinishRegister(self): self.new_register.Enable(True) self.finish_register.Enable(False) () ((self.pic_index)) if self.flag_registed == True: dir = PATH_FACE + for file in (dir): (dir + "/" + file) print("Pictures of recorded faces have been deleted.", dir + "/" + file) (PATH_FACE + ) print("Folders of names with faces entered have been deleted.", dir) () return if self.pic_num > 0: pics = (PATH_FACE + ) feature_list = [] feature_average = [] for i in range(len(pics)): pic_path = PATH_FACE + + "/" + pics[i] print("Face images being read:", pic_path) img = (pic_path) img_gray = (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("Failure to recognize a face in a photograph.") if len(feature_list) > 0: for j in range(128): # Preventing transgressions 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) ([, , feature_average], 1) (() + "Work number:" + str() + " Name:" + + " The face data has been successfully deposited into the \r\n ") pass else: (PATH_FACE + ) print("Empty folder deleted", PATH_FACE + ) () def OnFinishRegisterClicked(self, event): () pass def punchcard_cap(self, event): # Call the function that sets the office hours to determine if you are late based on the current time and the office hours = (0) # (propId, value) # set video parameters, video parameters set by propId, parameter values set by value # (3, 600) # (4,600) # cap is initialized successfully or not (5) print("The length is") print(len(working_times)) if len(working_times) == 0: (0, "You have not set your start time, please set your start time first and then set your end time", "Reminder.", 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 (): # () # Returns two values: # A boolean value true/false to determine if reading the video was successful/whether it reached the end of the video # Image objects, 3D matrices of images flag, im_rd = () # 1ms delay per data frame, delay 0 reads static frames kk = (1) # of faces dets dets = detector(im_rd, 1) # Face detected if len(dets) != 0: biggest_face = dets[0] # Take the face with the largest percentage maxArea = 0 for det in dets: w = () - () h = () - () if w * h > maxArea: biggest_face = det maxArea = w * h # Draw rectangular boxes (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 = (im_rd, cv2.COLOR_BGR2RGB) pic = (img_width, img_height, image1) # Show image on panel (pic) # Get the features of all faces in the currently captured image, stored in features_cap_arr shape = predictor(im_rd, biggest_face) features_cap = facerec.compute_face_descriptor(im_rd, shape) # For a given face, iterate over all stored face features for i, knew_face_feature in enumerate(self.knew_face_feature): # Match a face with all stored face data compare = return_euclidean_distance(features_cap, knew_face_feature) if compare == "same": # And found a face to match print("same") flag = 0 nowdt = () for j, logcat_name in enumerate(self.logcat_name): if logcat_name == self.knew_name[i] and nowdt[0:(" ")] == \ self.logcat_datetime[ j][ 0:self.logcat_datetime[ j].index(" ")]: (nowdt + "Work number:" + str(self.knew_id[i]) + " Name:" + self.knew_name[i] + " Failed to sign in, repeat signing in\r\n") speak_info(self.knew_name[i] + " Failed to sign in, repeat sign in ") flag = 1 break if flag == 1: break if nowdt[(" ") + 1:-1] <= working: (nowdt + "Work number:" + str(self.knew_id[i]) + " Name:" + self.knew_name[i] + " Successful check-in, and not late \r\n ") speak_info(self.knew_name[i] + " Successful check-in ") ([self.knew_id[i], self.knew_name[i], nowdt, "No."], 2) elif offworking >= nowdt[(" ") + 1:-1] >= working: (nowdt + "Work number:" + str(self.knew_id[i]) + " Name:" + self.knew_name[i] + "Signed in successfully, but late.") speak_info(self.knew_name[i] + "Signed in, but late.") ([self.knew_id[i], self.knew_name[i], nowdt, "Yes."], 2) elif nowdt[(" ") + 1:-1] > offworking: (nowdt + "Work number:" + str(self.knew_id[i]) + " Name:" + self.knew_name[i] + " Failed to sign in, exceeded sign in time\r\n") speak_info(self.knew_name[i] + " Failed to check in past closing time ") (2) break if self.start_punchcard.IsEnabled(): ((self.pic_index)) _thread.exit() def OnStartPunchCardClicked(self, event): self.start_punchcard.Enable(False) self.end_puncard.Enable(True) (2) (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): # missing these two sentences infoText background color setting failed, inexplicably strange resultText = (parent=self, pos=(10, 20), size=(90, 60)) () # ((12,12,12)) = "\r\n" + () + "Program initialized successfully\r\n" # The second parameter is the horizontal mixing bar = (parent=self, size=(320, 500), style=(wx.TE_MULTILINE | | wx.TE_READONLY)) # Foreground color, aka font color ('Black') () font = () (12) () (True) (font) ('WHITE') pass def initGallery(self): self.pic_index = ("drawable/", wx.BITMAP_TYPE_ANY).Scale(600, 500) = (parent=self, pos=(320, 0), bitmap=(self.pic_index)) pass def getDateAndTime(self): dateandtime = strftime("%Y-%m-%d %H:%M:%S", localtime()) return "[" + dateandtime + "]" # Database component # Initialize the database def initDatabase(self): conn = ("") # Establishment of database connections cur = () # Get the cursor object ('''create table if not exists worker_info (name text not null, id int not null primary key, face_feature array not null)''') ('''create table if not exists logcat (datetime text not null, id int not null, name text not null, late text not null)''') ('''create table if not exists time (id int constraint table_name_pk primary key, working_time time not null, offwork_time time not null)''') () () () def adapt_array(self, arr): out = () (out, arr) (0) dataa = () # Compressed data streams return ((dataa, zlib.Z_BEST_COMPRESSION)) def convert_array(self, text): out = (text) (0) dataa = () # Decompress the data stream out = ((dataa)) return (out) def insertARow(self, Row, type): conn = ("") # Establishment of database connections cur = () # Get the cursor object if type == 1: ("insert into worker_info (id,name,face_feature) values(?,?,?)", (Row[0], Row[1], self.adapt_array(Row[2]))) print("Write face data successfully.") if type == 2: ("insert into logcat (id,name,datetime,late) values(?,?,?,?)", (Row[0], Row[1], Row[2], Row[3])) print("Logging successful.") pass () () () pass def loadDataBase(self, type): nowday = () day = nowday[0:(" ")] print(day) global logcat_id, logcat_name, logcat_datetime, logcat_late, working_times, offworking_times conn = ("") # Establishment of database connections cur = () # Get the cursor object if type == 1: self.knew_id = [] self.knew_name = [] self.knew_face_feature = [] ('select id,name,face_feature from worker_info') origin = () 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 = [] ('select id,name,datetime,late from logcat') origin = () 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 ,,, from worker_info w left join logcat l on = and like' + ' ' + s + day + '%' + s + ' ' + 'order by datetime desc' print(sql) (sql) origin = () 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' (sql) countResult = (()) print(countResult) str = "'" if not countResult: sql = 'insert into time (id,working_time,offworking_time) values (1,' + str + working + str + ',' + str + offworking + str + ')' (sql) print(sql) () print("Insertion time successful.") else: str="'" sql = 'update time set working_time=' + str + working + str + ',offworking_time=' + str + offworking + str + ' where id=1' (sql) () print(sql) print("Update time successful.") if type==5: sql = 'select working_time,offworking_time from time' (sql) print(sql) origin = () print(origin) working_times = [] offworking_times = [] for row in origin: print("This is the office hours taken out of the database.") print(row[0]) working_times.append(row[0]) print("This is the off-duty time taken out of the database.") print(row[1]) offworking_times.append(row[1]) () () () pass app = () frame = WAS() () ()
Above is the detailed content of the face recognition clocking system realized by python, for more information about python face recognition clocking please pay attention to my other related articles!