python opencv人臉識別考勤系統的完整源碼
如需安裝運行環境或遠程調試,可加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
到此這篇關於python opencv人臉識別考勤系統的完整源碼的文章就介紹到這瞭,更多相關python 人臉識別考勤系統內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- python實現的人臉識別打卡系統
- Python+Opencv實戰之人臉追蹤詳解
- 教你如何用Python實現人臉識別(含源代碼)
- Python加載文件內容的兩種實現方式
- Python+LyScript實現自定義反匯編