需求分析
“員工刷臉考勤”系統,采用python語言開發,可以通過攝像頭添加員工面部信息,這里就涉及到兩個具體的個問題,一個是應該以什么樣的數據來標識每一個員工的面部信息,二是持久化地保存這些信息到數據庫中去。更細地,還涉及表的設計;另一個基本要求是通過攝像頭識別員工面部信息來完成考勤,這個問題基本可以通過遍歷數據庫里的員工面部數據與當前攝像頭里的員工面部數據的比對來實現,但有一個問題就是假如攝像頭里有多張人臉改怎么處理。擴展要求是導出每日的考勤表,可以拆分為兩個部分,一個是存儲考勤信息,一個是展示考勤信息。
我們希望達到的目標是:
(1)仿照通用型軟件界面設計的原則,所有的操作都在菜單欄里實現,一部分區域用于展示攝像頭實時讀取并由程序加工后的視頻流信息,另一部分區域做控制臺輸出,打印相關信息,比如提示員工面部信息添加成功、添加失敗及其原因,提示員工打卡成功、打卡失敗及其原因;添加面部信息時人是必須和程序進行交互的,比如輸入一些相關的信息,這個時候程序是阻塞的;但是在打卡的時候,程序是不阻塞的,如果不點擊關閉打卡,它會一直在打卡的模式,等待并識別每一個前來打卡的員工,這比較符合現實的使用場景。
(2)建表來存儲員工信息和考勤信息,每次新建錄入員工面部信息時,要求輸入工號、姓名,并查無重后方可錄入,錄入時只取距離屏幕最近的員工的面部信息,這是考慮到實際打卡都是依次進行而不是一群人一群人地打卡,錄入時有兩種模式可供選擇,自動模式:一旦識別到人臉就自動捕獲截圖,連續截圖達到10張就結束錄入;手動模式:點擊菜單結束錄入,不一定要得到10張。結束錄入后就開始從剛才捕獲的員工面部提取人臉特征數據并連同之前輸入的員工姓名等數據作為一行記錄保存到數據庫中,如果沒有捕獲到員工面部或者剛才捕獲的面部信息不是同一個人,這行記錄就被丟棄。
考勤時,須滿足三個條件:面部信息已錄入、在打卡時間段內、未重復打卡,只有打卡成功,打卡人姓名及工號、打卡日期及時間才會被當成一行記錄保存到數據庫并在控制臺輸出打卡成功信息,否則會在控制臺輸出失敗及其原因信息。
總而言之:我們的設計目標是規范化、人性化。
需要源碼可以關注、轉發,私信小編“01”領取,還有免費python學習視頻資料贈送。

總體設計
為了完成上述目標一,程序的界面初始化分為三部分,第一部分初始化菜單欄,第二部分初始化左邊控制臺,第三部分初始化右邊展示面板,使這三部分相互獨立;數據邏輯部分的初始化分為兩部分,第一部分是數據庫部分的初始化,如果數據庫/表不存在就新建,存在則加載相關數據,第二部分是初始化一些需要循環使用的變量,比如新建錄入時的員工姓名、工號、截圖數目計數器等,每當完成錄入時這些數據都應該被重置成初始化以待下一次錄入,把這些初始化語句寫成一個函數可以提高代碼復用度。
上述目標二主要是一些限制性條件,可以通過添加判斷語句來實現,比如對輸入id的合法性檢驗:
1
2
3
4
5
6
|
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 = "警告" ) |
其中id_worker_unaviable是id的初始化值-1,不可用,self.knew.id是從數據庫里加載出來的id列表,如果id非法(已重復或者不在0~100000000,就會一直有新的彈窗來提示輸入id。
再比如對拒絕多張人臉時、只處理距離屏幕最近的員工的面部信息:
1
2
3
4
5
6
7
8
9
10
|
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 |
dets是偵測到的所有面部數組,biggest_face是距離屏幕最近的面部。
程序框圖:

注:圖片如看不清也可在線預覽
https://www.processon.com/view/link/5bbcc953e4b08faf8c7324a1
本程序的設計思想大致可分為以下幾個方面
面向對象的原則,整個程序的主體就是一個was(workattendancesystem
)類,所有的實現都圍繞這個類展開。 界面和數據邏輯分離的原則,was類的初始化過程包括界面的初始化和數據初始化,兩者相互獨立。 代碼封裝原則,多次調用的語句集寫成接口供調用,沒有冗余的代碼。 接口隔離原則:使用多個專門的接口,而不是使用單一的總接口。 函數清單
注:所有類內的函數的第一個參數為self,表明該函數屬于該類,后面不再贅述
def __init__(self)
was類的構造函數,主要是完成一些初始化操作,如初始化菜單、信息打印面板、主展示面板以及初始化加載數據庫、初始化循環使用的變量。
def initmenu(self):
完成菜單的初始化顯示,點擊事件綁定。
def initinfotext(self):
完成左邊信息提示面板的初始化顯示。
def initgallery(self):
完成右邊主展示面板的初始化顯示。
def initdatabase(self):
數據庫的初始化,建立數據庫連接(如果數據庫inspurer.db不存在則先新建),如果數據庫中不存在員工信息worker_info和考勤logcat這兩個表,則依次創建。
def loaddatabase(self,type):
該模塊函數完成從數據庫讀取數據的操作,包括讀取員工信息和考勤信息,第二個參數type用于標識是加載員工信息還是考勤信息,一方面,可以統一接口,打開數據庫和得到游標、關閉連接是一樣的,將兩個讀取接口合二為一,提高代碼復用度;另一方面,可以減少加載的工作量,減少io,提高程序運行速度;最后,因為讀取信息前對上一次讀取的信息列表做了清空處理,用type標識可以避免讀取一個表時對另一個表造成的誤操作。
def insertarow(self,row,type):
該模塊函數完成寫數據庫操作,第二個參數為準備寫的一條記錄,第三個參數type表示要對哪一個表進行寫操作。
def adapt_array(self,arr):
將提取的人臉特征信息(列表)壓縮,入口參數就是待壓縮的數據,出口參數是壓縮后的數據,用于寫入數據庫。
def convert_array(self,text):
將讀取出來的數據解壓縮成人臉特征信息,入口參數是待解壓得數據,出口參數是解壓后的數據。
def return_euclidean_distance(feature_1, feature_2):
計算兩個人臉的歐式距離,入口參數是兩個人臉的特征數據,出口參數是判定的結果,歐式距離大于0.4判為不同,不大于判為相同。
def onnewregisterclicked(self,event):
見名知義,菜單新建錄入的監聽事件,參數event為事件信息,其他幾個菜單的(onfinishregisterclicked,onstartpunchcardclicked, onendpunchcardclicked, onopenlogcatclicked,oncloselogcatclicked)類似,在此不再贅述。
def getdateandtime(self):
得到當前日期和時間,并組裝成特定格式作為出口參數返回。 函數調用關系:箭頭指向被調用者

在線預覽地址:
https://www.processon.com/view/link/5bbe0b0de4b0534c9bfbecb4
程序運行結果 程序主界面

新建錄入



我們看到,信息欄有人臉數據重復警告,本次錄入取消。
于是我們把數據庫數據刪了重來。

下面是打印的日志信息(為保證格式,復制到記事本中截的圖)
看到已經錄入成功了。
開始打卡

提示信息打印如下

遲到與否的臨界時間是9:00
展示日志


只有已經錄入且第一次成功簽到才會寫進到數據庫,無論遲到與否。
總結
以上所述是小編給大家介紹的500行python代碼打造刷臉考勤系統,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!原文鏈接:http://developer.51cto.com/art/201906/597329.htm