寫在前面
本期內(nèi)容:基于OpenCV的WANT公司人臉識別打卡系統(tǒng)。
項目需求:
- pycharm
- opencv
- numpy
項目下載路徑:https://download.csdn.net/download/m0_68111267/88754360
項目分析
社會上很多公司,學院都需要使用手機或者智能軟件進行打卡簽到。隨著計算機技術(shù)的飛速發(fā)展,計算機視覺技術(shù)也越來越成熟了,例如人臉識別只需要幾行代碼就可以實現(xiàn)。打卡系統(tǒng)一般通過攝像頭掃描人臉的特征,利用人臉的差異識別不同的人員。本文將利用Python的OpenCV簡單實現(xiàn)一個公司打卡系統(tǒng)。
需求分析
打卡系統(tǒng)有 3 個核心功能: 錄入打卡人的資料、員工打卡和查看打卡記錄, 在滿足核心功能的基礎(chǔ)上需要完善一些附加功能和功能細節(jié)。在開發(fā) MR 智能視頻打卡系統(tǒng)前, 先對本系統(tǒng)的一些需求進行如下拆解和分析。
1.數(shù)據(jù)模型
本系統(tǒng)不使用第三方數(shù)據(jù)庫, 所有數(shù)據(jù)都以文本的形式保存在文件中,因此要規(guī)范數(shù)據(jù)內(nèi)容和格式, 建立統(tǒng)一模型。若把軟件的使用者設(shè)定為“公司”,那么打卡者身份可設(shè)定為“員工”, 程序中數(shù)據(jù)模型就應該是員工數(shù)據(jù)類。每一位員工都有姓名,“姓名”就作為員工類中必備的數(shù)據(jù)之一。
因為員工可能會重名, 所以必須使用另一種標記作為員工身份的認證,即為每一位員工添加不重復的員工編號。員工編號的格式為從 1 開始遞增數(shù)字, 每添加一位新員工,員工編號就+1。員工類中添加“員工編號”。
系統(tǒng)中必須保存所有員工的照片用于人臉識別。為了區(qū)分每位員工的照片文件,程序使用“員工特征碼 + 隨機值. png”的規(guī)則為照片文件命名。如果使用員工編號作為特征碼, 1號員工和 11號員工的文件名容易發(fā)生混淆,所以特征碼不能使用員工編號, 而是一種長度一致、復雜性高、不重復的字符串。員工類中添加“特征碼”。
員工與編號、姓名、特征碼是一對一的關(guān)系, 但員工與打卡記錄是一對多的關(guān)系, 所以打卡記錄可以放在員工類中保存,而不是單獨保存在打卡記錄模型中。打卡記錄需要記錄每一位員工的具體打卡時間,并能以報表的形式體現(xiàn)。可以使用字段保存打卡記錄模型,員工姓名作為key, 該員工的打卡記錄列表作為 value。
2.打卡功能
人臉打卡依賴于人臉識別功能。本程序可以使用 OpenCV 提供的人臉識別器實現(xiàn)此功能, 建議使用正確率較高的 LBPH 識別器, 其他識別器也可以考慮,但需要做好測試驗證。系統(tǒng)通過拍照保存員工的照片樣本。當員工面對攝像頭時,按 Enter鍵就可以生成一張正面特寫照片文件。為了增加識別準確率, 每位員工應拍3 張照片,也就是按3 次 Enter鍵才能完成錄入操作。每次員工打卡成功后,都應該記錄該員工的打卡時間,然后保存到文件中。
3.數(shù)據(jù)維護
數(shù)據(jù)維護總結(jié)起來就是增、刪、改、查 4 種操作。簡化版的打卡系統(tǒng)可以忽略“改”的操作,由先刪除,再新增的方式代替。本系統(tǒng)除了提供錄入新員工的功能之外,也提供刪除已有員工的功能。刪除員工之前應輸入驗證碼進行驗證,以防用戶操作失誤,誤刪重要數(shù)據(jù)。確認執(zhí)行刪除操作后,不僅要刪除員工的信息,也要同時刪除員工的打卡記錄和照片文件。完成刪除操作后,所有數(shù)據(jù)文件中不再存有被刪員工的任何數(shù)據(jù)。
4.考勤報表
每個公司的考勤制度都不同,很多公司都主動設(shè)置“上班時間”和“下班時間”來做考勤的標準。員工要在“上班時間”之前打卡才算正常到崗,在“下班時間”之后打卡才算正常離崗。未在規(guī)定時間內(nèi)打卡的情況屬于“打卡異?!保按蚩ó惓!蓖ǔ7譃?種情況: 遲到、早退或缺席(或缺勤)。本系統(tǒng)分析每一位員工在某一天的打卡記錄, 如果該員工在“上班時間”前和“下班時間”后都有打卡記錄, 則認為該員工當天全勤, 該員工當天的其他打卡記錄會被忽略。但如果該員工在“上班時間”前未能打卡, 而是在“上班時間”后到中午 12 點前打卡, 這種情況被視為遲到。如果該員工在“下班時間”后未能打卡,而是在中午12 點之后到“下班時間”前打卡, 這種情況被視為早退。當天沒有打卡記錄被視為缺席。
系統(tǒng)設(shè)計
WANT打卡系統(tǒng)
- 視頻打卡
- 管理員登錄
- 查看記錄
- 查看員工記錄
- 查看打卡記錄
- 員工管理
- 錄入新員工
- 刪除員工
- 考勤報表
- 日報
- 月報
- 報表設(shè)置
- 退出系統(tǒng)
項目設(shè)計
1.文件系統(tǒng)
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
import employees
import os
import cv2
import services
path = 'data/'
img_path = path + 'faces/'
data_file = path + 'employees.txt'
work_file = path + 'work_time.txt'
user_file = path + 'user.txt'
recode_file = path + 'record.txt'
def checking_files():
if not os.path.exists(path):
os.mkdir(path)
print("數(shù)據(jù)文件丟失,已重新創(chuàng)建:" + path)
if not os.path.exists(img_path):
os.mkdir(img_path)
print("照片文件丟失,已重新創(chuàng)建:" + img_path)
if not os.path.exists(data_file):
open(data_file, 'a+')
print("員工信息文件丟失,已重新創(chuàng)建:" + data_file)
if not os.path.exists(recode_file):
open(recode_file, 'a+')
print("打卡記錄文件丟失,已重新創(chuàng)建:" + recode_file)
if not os.path.exists(user_file):
file = open(user_file, 'a+', encoding='utf-8')
user = dict()
user['want595'] = '123456'
file.write(str(user))
file.close()
print("管理員信息文件丟失,已重新創(chuàng)建:" + user_file)
if not os.path.exists(work_file):
file = open(work_file, 'a+', encoding='utf-8')
file.write("09:00:00/17:00:00")
file.close()
print("時間配置文件丟失,已重新創(chuàng)建:", work_file)
……完整代碼請下載后查看哦
這段代碼是一個員工考勤系統(tǒng)的相關(guān)功能實現(xiàn)。它的主要功能包括員工信息的管理、打卡記錄的管理、管理員賬號的管理,以及相關(guān)文件的讀取和保存。
首先,在代碼開頭定義了一些路徑和文件的變量,用來存儲員工信息、打卡記錄、照片以及其他配置文件的路徑。
接下來,通過checking_files
函數(shù)來檢查文件是否存在,如果某個文件不存在,則會重新創(chuàng)建。
然后,通過load_employees
函數(shù)來讀取員工信息文件,并將每條信息存儲到employees
模塊中的EMPLOYEES
列表中。同時,還會記錄員工信息列表中最大的ID值。
接著,通過load_records
函數(shù)來讀取打卡記錄文件,將記錄存儲到employees
模塊中的RECORDS
字典中。
再然后,通過load_images
函數(shù)來讀取員工照片文件,并調(diào)用services
模塊的train
函數(shù)來訓練人臉識別模型。
接下來,通過load_works
函數(shù)來讀取工作時間配置文件,并將工作時間和下班時間分別保存到employees
模塊中的WORK_TIME
和CLOSING_TIME
變量中。
再然后,通過load_users
函數(shù)來讀取管理員賬號文件,并將賬號和密碼保存到employees
模塊中的USERS
字典中。
然后,通過save_employees
、save_records
、save_works
函數(shù)來保存員工信息、打卡記錄、工作時間配置到對應的文件中。
接著,通過remove_images
函數(shù)來刪除已經(jīng)刪除了的員工的照片文件。
最后,通過create_csv
函數(shù)來生成CSV文件。
這段代碼的核心邏輯是通過employees
模塊來管理員工信息、打卡記錄等數(shù)據(jù),并通過services
模塊來實現(xiàn)人臉識別的訓練和識別功能。整體上,這段代碼實現(xiàn)了一個基本的員工考勤系統(tǒng)的功能。
2.數(shù)據(jù)模塊
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
RECORDS = dict()
EMPLOYEES = list()
IMG_WIDTH = 960
IMG_HEIGHT = 540
MAX_ID = 0
CODE_LEN = 6
WORK_TIME = ""
CLOSING_TIME = ""
USERS = dict()
class Employee:
def __init__(self, id, name, code):
self.name = name
self.id = id
self.code = code
def add(e: Employee):
EMPLOYEES.append(e)
def remove(id):
for i in EMPLOYEES:
if str(id) == str(i.id):
EMPLOYEES.remove(i)
if i.name is RECORDS.keys():
del RECORDS[i.name]
break
def get_id():
global MAX_ID
MAX_ID += 1
return MAX_ID
這部分代碼定義了一些全局變量和類,用于存儲員工信息和相關(guān)數(shù)據(jù)。
首先,定義了一個RECORDS
字典,用于存儲打卡記錄。
然后,定義了一個EMPLOYEES
列表,用于存儲員工對象。
接著,定義了IMG_WIDTH
和IMG_HEIGHT
變量,用于設(shè)置圖片的寬度和高度。
然后,定義了MAX_ID
變量,用于記錄員工信息中最大的ID值。
接下來,定義了CODE_LEN
變量,表示員工的代碼長度。
再然后,定義了WORK_TIME
和CLOSING_TIME
變量,用于存儲每天的上班時間和下班時間。
最后,定義了一個USERS
字典,用于存儲管理員的賬號和密碼。
接下來,定義了一個Employee
類,表示員工對象。它有三個屬性,分別是id
、name
和code
,分別表示員工的ID、姓名和代碼。構(gòu)造函數(shù)接收這三個參數(shù)來初始化員工對象。
接著,定義了add
函數(shù),用于將員工對象添加到EMPLOYEES
列表中。
然后,定義了remove
函數(shù),用于根據(jù)員工ID從EMPLOYEES
列表中移除對應的員工對象。同時,如果該員工的姓名存在于RECORDS
字典中,也會將對應的記錄刪除。
最后,定義了get_id
函數(shù),用于獲取一個新的員工ID。它先將MAX_ID
增加1,然后返回新的ID值。
這部分代碼主要是定義了一些全局變量和類,用于存儲和操作員工信息和相關(guān)數(shù)據(jù)。
3.工具模塊
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
import random as rd
import datetime as dt
import employees
def randomCode():
first = str(rd.randint(1, 9))
last = "".join(rd.sample("1234567890", employees.CODE_LEN - 1))
return first + last
def valid_time(str):
try:
dt.datetime.strptime(str, "%H:%M:%S")
return True
except:
return False
def valid_year_month(str):
try:
dt.datetime.strptime(str, "%Y-%m")
return True
except:
return False
def valid_date(date):
try:
dt.datetime.strptime(date, "%Y-%m-%d")
return True
except:
return False
這部分代碼定義了一些輔助函數(shù),用于生成隨機代碼、驗證時間和日期的有效性。
首先,定義了一個randomCode
函數(shù),用于生成隨機的員工代碼。它首先生成一個1到9的隨機數(shù)作為代碼的第一位數(shù)字,然后使用rd.sample
函數(shù)從數(shù)字"1234567890"中隨機選擇出長度為employees.CODE_LEN - 1
的數(shù)字,將它們拼接在一起,得到最終的員工代碼。
接下來,定義了一個valid_time
函數(shù),用于驗證輸入的時間字符串是否符合格式"%H:%M:%S"。它使用datetime.datetime.strptime
函數(shù)將時間字符串轉(zhuǎn)換為日期時間對象,如果轉(zhuǎn)換成功,則說明時間字符串有效,返回True
;否則,返回False
。
然后,定義了一個valid_year_month
函數(shù),用于驗證輸入的年份和月份字符串是否符合格式"%Y-%m"。與valid_time
函數(shù)類似,它使用datetime.datetime.strptime
函數(shù)將字符串轉(zhuǎn)換為日期時間對象,如果轉(zhuǎn)換成功,則說明年份和月份字符串有效,返回True
;否則,返回False
。
最后,定義了一個valid_date
函數(shù),用于驗證輸入的日期字符串是否符合格式"%Y-%m-%d"。同樣地,它使用datetime.datetime.strptime
函數(shù)將日期字符串轉(zhuǎn)換為日期時間對象,如果轉(zhuǎn)換成功,則說明日期字符串有效,返回True
;否則,返回False
。
這些輔助函數(shù)可以在其他地方被調(diào)用,用于驗證和處理時間和日期相關(guān)的輸入。
4.服務(wù)模塊
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
import employees
import public
import inits
import datetime
import calendar
import cv2
import numpy as np
def init_data():
inits.checking_files()
inits.load_users()
inits.load_records()
inits.load_employees()
inits.load_images()
def add_employee(name):
code = public.randomCode()
employee = employees.Employee(employees.get_id(), name, code)
employees.add(employee)
inits.save_employees()
return code
def remove_employee(id):
inits.remove_images(id)
employees.remove(id)
inits.save_employees()
inits.save_records()
……完整代碼請下載后查看哦
5.人臉識別
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
import cv2
import inits
import employees
import public
import services
ESC_KEY = 27
ENTER_KEY = 13
def register(code):
capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)
success, frame = capture.read()
times = 0
while success:
cv2.imshow("register", frame)
success, frame = capture.read()
key = cv2.waitKey(1)
if key == ESC_KEY:
break
if key == ENTER_KEY:
image = cv2.resize(frame, (employees.IMG_WIDTH, employees.IMG_HEIGHT))
img_name = str('data/faces/' + code + public.randomCode() + '.png')
cv2.imwrite(img_name, image)
print("保存成功:" + img_name)
times += 1
if times == 3:
break
cv2.destroyAllWindows()
capture.release()
inits.load_images()
……完整代碼請下載后查看哦
6.主函數(shù)
"""
作者:Want595
微信號:Want_595
公眾號:Want595
"""
import camera
import public
import services
admin_login = False
def login():
while True:
username = input("請輸入管理員賬號:")
if username == "0":
return
password = input("請輸入管理員密碼:")
if services.valid_user(username.strip(), password.strip()):
global admin_login
admin_login = True
print("登錄成功!")
break
else:
print("登錄失敗!請重新登錄!!")
……完整代碼請下載后查看哦
運行結(jié)果
文章來源:http://www.zghlxwxcb.cn/news/detail-800642.html
寫在后面
我是一只有趣的兔子,感謝你的喜歡!文章來源地址http://www.zghlxwxcb.cn/news/detail-800642.html
到了這里,關(guān)于計算機視覺丨基于OpenCV的人臉識別打卡系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!