婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識(shí)庫 > python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)

python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)

熱門標(biāo)簽:海南400電話如何申請 廣告地圖標(biāo)注app 白銀外呼系統(tǒng) 騰訊外呼線路 公司電話機(jī)器人 哈爾濱ai外呼系統(tǒng)定制 唐山智能外呼系統(tǒng)一般多少錢 陜西金融外呼系統(tǒng) 激戰(zhàn)2地圖標(biāo)注

項(xiàng)目地址:

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

簡介

本倉庫是使用python編寫的一個(gè)簡單的人臉識(shí)別考勤打卡系統(tǒng)

主要功能有錄入人臉信息、人臉識(shí)別打卡、設(shè)置上下班時(shí)間、導(dǎo)出打卡日志等

下面是各模塊截圖

首頁

錄入人臉信息

人臉識(shí)別打卡

輸出日志

使用

直接運(yùn)行**==workAttendanceSystem==**.py即可

主要代碼

import datetime
import time
import win32api
import win32con
import wx
import wx.grid
import sqlite3
from time import localtime, strftime
import os
from skimage import io as iio
import io
import zlib
import dlib  # 人臉識(shí)別的庫dlib
import numpy as np  # 數(shù)據(jù)處理的庫numpy
import cv2  # 圖像處理的庫OpenCv
import _thread
import threading
import win32com.client
import tkinter as tk
from tkinter import filedialog
import csv

spk = win32com.client.Dispatch("SAPI.SpVoice")

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 預(yù)測器
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, title="智能監(jiān)控打卡系統(tǒng)", size=(920, 560))

        self.Folderpath = None
        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.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, "結(jié)束簽到")
        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, "上班時(shí)間")
        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, "下班時(shí)間")
        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, "設(shè)置")

        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 working
        global setWorkingSign
        setWorkingSign = False
        self.loadDataBase(1)
        # self.working_hours.Enable(True)
        self.working_hours = wx.GetTextFromUser(message="請輸入上班時(shí)間", caption="溫馨提示", default_value="08:00:00",
                                                parent=None)
        working = self.working_hours
        setWorkingSign = True
        pass

    def SetOffWorkHours(self, event):
        global offworking
        self.loadDataBase(1)
        # self.offwork_hours.Enable(True)
        self.offwork_hours = wx.GetTextFromUser(message="請輸入下班時(shí)間", caption="溫馨提示", default_value="18:00:00",
                                                parent=None)
        offworking = self.offwork_hours
        win32api.MessageBox(0, "請確保同時(shí)設(shè)置上班時(shí)間和下班時(shí)間并且先設(shè)置上班時(shí)間", "提醒", win32con.MB_ICONWARNING)
        if setWorkingSign:
            self.loadDataBase(4)
        else:
            win32api.MessageBox(0, "您未設(shè)置上班時(shí)間", "提醒", win32con.MB_ICONWARNING)
        pass

    def ExportTodayLog(self, event):
        global Folderpath1
        Folderpath1 = ""
        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(["編號(hào)", "姓名", "打卡時(shí)間", "是否遲到"])
            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 dialog
        global t1
        global t2
        global Folderpath2
        Folderpath2 = ""
        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, "確認(rèn)", 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

    # 關(guān)閉主窗口前確認(rèn)一下是否真的關(guān)閉
    def OnClose(self, event):
        dlg = wx.MessageDialog(None, u'確定要關(guān)閉本窗口嗎?', u'操作提示', wx.YES_NO)
        if dlg.ShowModal() == wx.ID_YES:
            dialog.Destroy()

    def OnClose1(self, event):
        dlg = wx.MessageDialog(None, u'確定要關(guān)閉本窗口嗎?', u'操作提示', wx.YES_NO)
        if dlg.ShowModal() == wx.ID_YES:
            dialog1.Destroy()

    def OnYes(self, event):
        dlg = wx.MessageDialog(None, u'確定要?jiǎng)h除該編號(hào)的員工?', u'操作提示', wx.YES_NO)
        if dlg.ShowModal() == wx.ID_YES:
            return True

    def deleteBtn(self, event):
        global dialog1
        global t4
        dialog1 = 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, "確認(rèn)", 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("查詢的天數(shù)是:", 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(["編號(hào)", "姓名", "打卡時(shí)間", "是否遲到"])
                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, "請輸入文件導(dǎo)出位置", "提醒", win32con.MB_ICONWARNING)

        pass

    def deleteById(self, event):
        global delete_name
        delete_name = []
        id = t4.GetValue()
        print("刪除員工的id為:", id)
        conn = sqlite3.connect("inspurer.db")  # 建立數(shù)據(jù)庫連接
        cur = conn.cursor()  # 得到游標(biāo)對象
        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(cur.execute(sql).fetchall())
        if length = 0:
            win32api.MessageBox(0, "沒有查詢到該員工,請重新輸入ID", "提醒", win32con.MB_ICONWARNING)
            return False
        else:
            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 + name
                for 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_late
        find_id = []
        find_name = []
        find_datetime = []
        find_late = []
        DayAgo = (datetime.datetime.now() - datetime.timedelta(days=int(day)))
        # 轉(zhuǎn)換為其他字符串格式:
        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")  # 建立數(shù)據(jù)庫連接
        cur = conn.cursor()  # 得到游標(biāo)對象
        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(cur.execute(sql).fetchall())
        if length = 0:
            return False
        else:
            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 True
        pass

    def save_route1(self, event):
        global Folderpath1
        root = tk.Tk()
        root.withdraw()
        Folderpath1 = filedialog.askdirectory()  # 獲得選擇好的文件夾
        pass

    def save_route2(self, event):
        global Folderpath2
        root = tk.Tk()
        root.withdraw()
        Folderpath2 = filedialog.askdirectory()  # 獲得選擇好的文件夾
        pass

    def register_cap(self, event):
        # 創(chuàng)建 cv2 攝像頭對象
        self.cap = cv2.VideoCapture(0)
        # cap.set(propId, value)
        # 設(shè)置視頻參數(shù),propId設(shè)置的視頻參數(shù),value設(shè)置的參數(shù)值
        # self.cap.set(3, 600)
        # self.cap.set(4,600)
        # cap是否初始化成功
        while self.cap.isOpened():
            # cap.read()
            # 返回兩個(gè)值:
            #    一個(gè)布爾值true/false,用來判斷讀取視頻是否成功/是否到視頻末尾
            #    圖像對象,圖像的三維矩陣
            flag, im_rd = self.cap.read()

            # 每幀數(shù)據(jù)延時(shí)1ms,延時(shí)為0讀取的是靜態(tài)幀
            kk = cv2.waitKey(1)
            # 人臉數(shù) 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)

                # 獲取當(dāng)前捕獲到的圖像的所有人臉的特征,存儲(chǔ)到 features_cap_arr
                shape = predictor(im_rd, biggest_face)
                features_cap = facerec.compute_face_descriptor(im_rd, shape)

                # 對于某張人臉,遍歷所有存儲(chǔ)的人臉特征
                for i, knew_face_feature in enumerate(self.knew_face_feature):
                    # 將某張人臉與存儲(chǔ)的所有人臉數(shù)據(jù)進(jìn)行比對
                    compare = return_euclidean_distance(features_cap, knew_face_feature)
                    if compare == "same":  # 找到了相似臉
                        self.infoText.AppendText(self.getDateAndTime() + "工號(hào):" + str(self.knew_id[i])
                                                 + " 姓名:" + self.knew_name[i] + " 的人臉數(shù)據(jù)已存在\r\n")
                        self.flag_registed = True
                        self.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 += 1
                        print("寫入本地:", 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保存成功\r\n")
                except:
                    print("保存照片異常,請對準(zhǔn)攝像頭")

                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="請輸入您的工號(hào)(-1不可用)",
                                           prompt="工號(hào)", 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="工號(hào)已存在,請重新輸入", caption="警告")

        while self.name == '':
            self.name = wx.GetTextFromUser(message="請輸入您的的姓名,用于創(chuàng)建姓名文件夾",
                                           caption="溫馨提示",
                                           default_value="", parent=self.bmp)

            # 監(jiān)測是否重名
            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("未在照片中識(shí)別到人臉")
            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() + "工號(hào):" + str(self.id)
                                         + " 姓名:" + self.name + " 的人臉數(shù)據(jù)已成功存入\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 punchcard_cap(self, event):

        # 調(diào)用設(shè)置上班時(shí)間的函數(shù),根據(jù)當(dāng)前時(shí)間和上班時(shí)間判斷是否遲到

        self.cap = cv2.VideoCapture(0)
        # cap.set(propId, value)
        # 設(shè)置視頻參數(shù),propId設(shè)置的視頻參數(shù),value設(shè)置的參數(shù)值
        # 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, "您未設(shè)置上班時(shí)間,請先設(shè)置上班時(shí)間后再設(shè)置下班時(shí)間", "提醒", 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()
                # 返回兩個(gè)值:
                #    一個(gè)布爾值true/false,用來判斷讀取視頻是否成功/是否到視頻末尾
                #    圖像對象,圖像的三維矩陣
                flag, im_rd = self.cap.read()
                # 每幀數(shù)據(jù)延時(shí)1ms,延時(shí)為0讀取的是靜態(tài)幀
                kk = cv2.waitKey(1)
                # 人臉數(shù) 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, 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)

                    # 獲取當(dāng)前捕獲到的圖像的所有人臉的特征,存儲(chǔ)到 features_cap_arr
                    shape = predictor(im_rd, biggest_face)
                    features_cap = facerec.compute_face_descriptor(im_rd, shape)

                    # 對于某張人臉,遍歷所有存儲(chǔ)的人臉特征
                    for i, knew_face_feature in enumerate(self.knew_face_feature):
                        # 將某張人臉與存儲(chǔ)的所有人臉數(shù)據(jù)進(jìn)行比對
                        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 + "工號(hào):" + str(self.knew_id[i])
                                                             + " 姓名:" + self.knew_name[i] + " 簽到失敗,重復(fù)簽到\r\n")
                                    speak_info(self.knew_name[i] + " 簽到失敗,重復(fù)簽到 ")
                                    flag = 1
                                    break

                            if flag == 1:
                                break

                            if nowdt[nowdt.index(" ") + 1:-1] = working:
                                self.infoText.AppendText(nowdt + "工號(hào):" + str(self.knew_id[i])
                                                         + " 姓名:" + self.knew_name[i] + " 成功簽到,且未遲到\r\n")
                                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 + "工號(hào):" + str(self.knew_id[i])
                                                         + " 姓名:" + self.knew_name[i] + " 成功簽到,但遲到了\r\n")
                                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 + "工號(hào):" + str(self.knew_id[i])
                                                         + " 姓名:" + self.knew_name[i] + " 簽到失敗,超過簽到時(shí)間\r\n")
                                speak_info(self.knew_name[i] + " 簽到失敗,超過下班時(shí)間 ")
                            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背景顏色設(shè)置失敗,莫名奇怪
        resultText = wx.StaticText(parent=self, pos=(10, 20), size=(90, 60))
        resultText.SetBackgroundColour(wx.GREEN)
        # resultText.SetBackgroundColour((12,12,12))
        self.info = "\r\n" + self.getDateAndTime() + "程序初始化成功\r\n"
        # 第二個(gè)參數(shù)水平混動(dòng)條
        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 + "]"

    # 數(shù)據(jù)庫部分
    # 初始化數(shù)據(jù)庫
    def initDatabase(self):
        conn = sqlite3.connect("inspurer.db")  # 建立數(shù)據(jù)庫連接
        cur = conn.cursor()  # 得到游標(biāo)對象
        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 int
		constraint table_name_pk
			primary 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()
        # 壓縮數(shù)據(jù)流
        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()
        # 解壓縮數(shù)據(jù)流
        out = io.BytesIO(zlib.decompress(dataa))
        return np.load(out)

    def insertARow(self, Row, type):
        conn = sqlite3.connect("inspurer.db")  # 建立數(shù)據(jù)庫連接
        cur = conn.cursor()  # 得到游標(biāo)對象
        if type == 1:
            cur.execute("insert into worker_info (id,name,face_feature) values(?,?,?)",
                        (Row[0], Row[1], self.adapt_array(Row[2])))
            print("寫人臉數(shù)據(jù)成功")
        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):
        nowday = self.getDateAndTime()
        day = nowday[0:nowday.index(" ")]
        print(day)
        global logcat_id, logcat_name, logcat_datetime, logcat_late, working_times, offworking_times
        conn = sqlite3.connect("inspurer.db")  # 建立數(shù)據(jù)庫連接

        cur = conn.cursor()  # 得到游標(biāo)對象

        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("插入時(shí)間成功")
            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("更新時(shí)間成功")

        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("這是數(shù)據(jù)庫取出的上班時(shí)間")
                print(row[0])
                working_times.append(row[0])
                print("這是數(shù)據(jù)庫取出的下班時(shí)間")
                print(row[1])
                offworking_times.append(row[1])
        cur.close()
        conn.commit()
        conn.close()
        pass


app = wx.App()
frame = WAS()
frame.Show()
app.MainLoop()

以上就是python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于python 人臉識(shí)別打卡的資料請關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • python opencv人臉識(shí)別考勤系統(tǒng)的完整源碼
  • 10分鐘學(xué)會(huì)使用python實(shí)現(xiàn)人臉識(shí)別(附源碼)
  • 用Python實(shí)現(xiàn)簡單的人臉識(shí)別功能步驟詳解
  • 教你如何用Python實(shí)現(xiàn)人臉識(shí)別(含源代碼)

標(biāo)簽:惠州 常德 四川 上海 黑龍江 鷹潭 黔西 益陽

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)》,本文關(guān)鍵詞  python,實(shí)現(xiàn),的,人臉,識(shí)別,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)》相關(guān)的同類信息!
  • 本頁收集關(guān)于python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    同产精品九九九| 在线视频综合导航| 91丨九色丨国产丨porny| 欧美精品一区二区三区久久久 | 爽爽淫人综合网网站| 色噜噜偷拍精品综合在线| 亚洲日本韩国一区| 欧美日韩精品三区| 国产在线一区二区综合免费视频| 日韩精品一区二区三区老鸭窝| 国产乱理伦片在线观看夜一区| 国产**成人网毛片九色| 美女视频黄a大片欧美| 日本中文一区二区三区| 五月婷婷综合在线| 日本午夜一本久久久综合| 日韩电影在线免费看| 石原莉奈在线亚洲三区| 亚洲18女电影在线观看| 天堂va蜜桃一区二区三区| 天堂va蜜桃一区二区三区漫画版 | 亚洲一区二区精品久久av| 亚洲欧美电影一区二区| 一个色综合av| 婷婷国产在线综合| 久久精品国产精品青草| 精品一区二区av| 国产精品亚洲专一区二区三区| 国产成人精品一区二区三区网站观看| 国产成人av一区二区三区在线 | 偷拍日韩校园综合在线| 日韩高清不卡一区| 激情文学综合丁香| 成人国产一区二区三区精品| 色吊一区二区三区| 日韩视频在线观看一区二区| 亚洲精品一线二线三线| 国产精品你懂的| 久久99久久99小草精品免视看| 精品一区二区在线播放| 成人综合婷婷国产精品久久免费| 91蝌蚪porny| 欧美一区二区二区| 国产精品你懂的在线| 午夜国产精品一区| 成人午夜av影视| 在线不卡免费av| 国产精品国模大尺度视频| 午夜日韩在线电影| 成人国产亚洲欧美成人综合网| 欧美日韩国产经典色站一区二区三区| 99精品视频中文字幕| 成人av网址在线| 成人精品电影在线观看| 国产在线播精品第三| 韩国av一区二区三区在线观看| 偷拍一区二区三区四区| 亚洲成人综合在线| 三级不卡在线观看| 久久久久88色偷偷免费| 一区二区三区不卡在线观看| 国产乱子伦视频一区二区三区 | 久久综合久色欧美综合狠狠| 日韩理论片一区二区| 久99久精品视频免费观看| av一区二区三区在线| 精品国产乱码久久久久久闺蜜| 亚洲国产精品久久不卡毛片| 成人av动漫网站| 国产清纯白嫩初高生在线观看91| 偷偷要91色婷婷| 欧美亚洲一区三区| 1000部国产精品成人观看| 久久成人av少妇免费| 欧美三级三级三级爽爽爽| 亚洲欧美日韩在线| 成人免费毛片app| 久久精品视频一区二区三区| 麻豆91免费观看| 91麻豆精品国产91久久久资源速度| 亚洲狼人国产精品| 色综合天天综合网天天看片| 中文字幕不卡的av| 国产99久久久久久免费看农村| 欧美va在线播放| 久久精品72免费观看| 欧美一级高清片在线观看| 丝袜美腿亚洲色图| 国产精品女上位| 99久久久国产精品| 亚洲欧美自拍偷拍色图| 成人av电影观看| 日韩理论片中文av| 国产激情偷乱视频一区二区三区| 日韩精品专区在线影院重磅| 久久精品国产免费看久久精品| 精品三级在线看| 国产一区二区美女诱惑| 中文字幕不卡的av| 国产91露脸合集magnet| 亚洲美女淫视频| 国产酒店精品激情| 精品视频在线免费看| 国产精品看片你懂得| 热久久一区二区| 在线中文字幕一区| 欧美国产一区二区在线观看| 天天免费综合色| 91天堂素人约啪| 波多野结衣中文一区| 日韩午夜av一区| 粉嫩欧美一区二区三区高清影视| 中文乱码免费一区二区| 在线免费精品视频| 日韩成人一级大片| 久久亚洲私人国产精品va媚药| www.视频一区| 天天色综合天天| 欧美国产日韩在线观看| 色综合久久中文字幕| 日本欧美一区二区在线观看| 久久久亚洲高清| 欧洲人成人精品| 久久福利视频一区二区| 国产亚洲欧美在线| 色婷婷精品久久二区二区蜜臀av| 日韩高清不卡在线| 国产精品国产三级国产普通话99| 欧美日韩一级黄| 国产高清精品久久久久| 亚洲精品久久7777| 日韩欧美精品在线视频| 91性感美女视频| 国产伦精一区二区三区| 一区二区三区丝袜| 久久亚洲综合色一区二区三区| 一本色道亚洲精品aⅴ| 久久99精品一区二区三区| 一区二区三区四区不卡视频| 国产亚洲精品超碰| 欧美一区三区四区| 色狠狠综合天天综合综合| 日韩免费在线观看| 日本最新不卡在线| 中文字幕人成不卡一区| 欧美一区二区观看视频| 欧美片网站yy| 欧美在线你懂的| www.亚洲国产| 波多野结衣中文字幕一区| 久久理论电影网| 九九国产精品视频| 欧美一卡二卡三卡| 精品一区免费av| 欧美精品一区二区三区高清aⅴ| 丝袜美腿一区二区三区| 91精品国产高清一区二区三区| 美女网站色91| 国产午夜亚洲精品理论片色戒| 国产福利精品导航| 亚洲天堂成人网| 欧美三级在线视频| 美女视频黄免费的久久 | 亚洲欧美一区二区不卡| 丁香六月综合激情| 亚洲国产精品视频| 日韩免费观看高清完整版| 国产成人精品免费视频网站| 国产精品短视频| 欧美视频一区在线| 紧缚奴在线一区二区三区| 中文字幕巨乱亚洲| 欧美三级日本三级少妇99| 国产二区国产一区在线观看| 亚洲免费看黄网站| 精品日韩在线一区| 在线日韩一区二区| 国产精品18久久久| 一区av在线播放| 精品国产青草久久久久福利| 欧洲视频一区二区| 国产精品一区二区视频| 亚洲成人av电影在线| 国产欧美一区二区三区沐欲| 91精品婷婷国产综合久久性色| jizzjizzjizz欧美| 久久精品国产亚洲一区二区三区| 依依成人精品视频| 中文字幕欧美日本乱码一线二线| 777色狠狠一区二区三区| 色综合天天在线| 顶级嫩模精品视频在线看| 美腿丝袜亚洲综合| 秋霞影院一区二区| 亚洲综合无码一区二区| 欧美国产日本视频| 2023国产精品自拍| 日韩午夜激情免费电影| 欧美日韩综合不卡| 色播五月激情综合网|