成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

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

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

熱門標(biāo)簽:海南400電話如何申請(qǐng) 廣告地圖標(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

簡(jiǎn)介

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

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

下面是各模塊截圖

首頁(yè)

錄入人臉信息

人臉識(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í)別的庫(kù)dlib
import numpy as np  # 數(shù)據(jù)處理的庫(kù)numpy
import cv2  # 圖像處理的庫(kù)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ù)測(cè)器
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="請(qǐng)輸入上班時(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="請(qǐng)輸入下班時(shí)間", caption="溫馨提示", default_value="18:00:00",
                                                parent=None)
        offworking = self.offwork_hours
        win32api.MessageBox(0, "請(qǐng)確保同時(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, '日志保存成功,請(qǐng)注意查看', 'info', wx.OK)
                success.ShowModal()
            else:
                warn = wx.MessageDialog(None, '輸入id不正確,請(qǐng)重新輸入', 'info', wx.OK)
                warn.ShowModal()
            dialog.Destroy()
        else:
            win32api.MessageBox(0, "請(qǐng)輸入文件導(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ù)庫(kù)連接
        cur = conn.cursor()  # 得到游標(biāo)對(duì)象
        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, "沒有查詢到該員工,請(qǐng)重新輸入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ù)庫(kù)連接
        cur = conn.cursor()  # 得到游標(biāo)對(duì)象
        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 攝像頭對(duì)象
        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,用來(lái)判斷讀取視頻是否成功/是否到視頻末尾
            #    圖像對(duì)象,圖像的三維矩陣
            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)

            # 檢測(cè)到人臉
            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)

                # 對(duì)于某張人臉,遍歷所有存儲(chǔ)的人臉特征
                for i, knew_face_feature in enumerate(self.knew_face_feature):
                    # 將某張人臉與存儲(chǔ)的所有人臉數(shù)據(jù)進(jìn)行比對(duì)
                    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("保存照片異常,請(qǐng)對(duì)準(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="請(qǐng)輸入您的工號(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)已存在,請(qǐng)重新輸入", caption="警告")

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

            # 監(jiān)測(cè)是否重名
            for exsit_name in (os.listdir(PATH_FACE)):
                if self.name == exsit_name:
                    wx.MessageBox(message="姓名文件夾已存在,請(qǐng)重新輸入", 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("長(zhǎng)度是")
        print(len(working_times))
        if len(working_times) == 0:
            win32api.MessageBox(0, "您未設(shè)置上班時(shí)間,請(qǐng)先設(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,用來(lái)判斷讀取視頻是否成功/是否到視頻末尾
                #    圖像對(duì)象,圖像的三維矩陣
                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)

                # 檢測(cè)到人臉
                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)

                    # 對(duì)于某張人臉,遍歷所有存儲(chǔ)的人臉特征
                    for i, knew_face_feature in enumerate(self.knew_face_feature):
                        # 將某張人臉與存儲(chǔ)的所有人臉數(shù)據(jù)進(jìn)行比對(duì)
                        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ù)庫(kù)部分
    # 初始化數(shù)據(jù)庫(kù)
    def initDatabase(self):
        conn = sqlite3.connect("inspurer.db")  # 建立數(shù)據(jù)庫(kù)連接
        cur = conn.cursor()  # 得到游標(biāo)對(duì)象
        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ù)庫(kù)連接
        cur = conn.cursor()  # 得到游標(biāo)對(duì)象
        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ù)庫(kù)連接

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

        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ù)庫(kù)取出的上班時(shí)間")
                print(row[0])
                working_times.append(row[0])
                print("這是數(shù)據(jù)庫(kù)取出的下班時(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í)別打卡的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

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

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

巨人網(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)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于python實(shí)現(xiàn)的人臉識(shí)別打卡系統(tǒng)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    四虎影视精品永久在线观看| 亚洲色图视频网| 美国十次av导航亚洲入口| 国产中文在线视频| 丰满少妇高潮一区二区| 国产精品久久999| 日韩中文字幕a| 国产视频一区二区三区在线观看| 91免费高清视频| yw193.com尤物在线| 久久伊99综合婷婷久久伊| 久久久不卡网国产精品二区| 国产精品yjizz| 日韩av在线播放不卡| 国产三级视频在线播放线观看| 精品在线免费视频| 欧美精品欧美精品系列| 亚洲精品乱码久久久久久蜜桃麻豆| 久久久久97国产| 最新国产中文字幕| 久久久久毛片免费观看| 欧美激情 亚洲| 男人天堂网站在线| 精品免费在线| 国产精品久久精品日日| 国产超级va在线视频| 青青草在线播放| 综合久久2023| 色吊丝中文字幕| 免费观看污网站| 精品一区二区三区无码视频| 91超碰国产精品| 成人乱码一区二区三区| 国产精品日韩欧美一区二区三区| 视频亚洲一区二区| 久久久久久国产精品| 久久久噜噜噜久噜久久| 国产综合精品一区| 亚洲精品鲁一鲁一区二区三区| 宅男在线一区| 手机在线视频一区| 亚洲精品.com| 欧美亚洲国产精品久久| 欧美日韩视频一区二区三区| 久久资源在线| 牛人国产偷窥女洗浴在线观看| www.成人免费视频| 1769视频在线播放免费观看| 精品一区二区三区蜜桃| 精品不卡在线| 国产精品熟女久久久久久| 久久久久久9| 一级美女在线| 天堂а√在线8种子蜜桃视频| 两个人日本在线观看视频| 少女频道在线观看高清| 中文字幕亚洲欧美一区二区三区| 无码人妻久久一区二区三区不卡| 精品一区久久久久久| 精品999视频| 香港三级韩国三级日本三级| 一区二区中文字| 91国偷自产一区二区三区观看| av2020不卡| 日韩伦理在线电影| 黄色av免费在线播放| 欧美精品一区二区三区一线天视频| 国产精品久久久久久久久久免费| 精品欧美一区免费观看α√| 日本三级免费观看| 亚洲福利视频网| 国产又粗又猛又爽又黄的| 97久久国产精品| 91精彩在线视频| 欧美优质美女网站| 欧美伦理视频网站| www.天堂在线| 国产免费高清| av在线观看地址| 一级毛片高清视频| 91精品国产高清一区二区三区蜜臀| www.99视频| 先锋影音av资源在线| 高清不卡一区二区| 国产一区二区h| 免费99精品国产自在在线| 国产又粗又猛又色| 蜜桃一区二区三区在线| 亚洲av综合色区无码一二三区| 色噜噜狠狠成人中文综合| 91丨九色丨国产丨porny| 1区2区3区在线观看| 91超碰rencao97精品| 真实乱视频国产免费观看| 亚洲精品v欧美精品v日韩精品| 国产成人强伦免费视频网站| 久久观看最新视频| 国产一区二区三区四区五区加勒比| 95影院理论片在线观看| 亚洲人成亚洲人成在线观看图片| 96sao精品视频在线观看| 欧美日本高清视频| 国产精品第一页在线| 日日干夜夜骑| 国产经典自拍视频在线观看| wwwww在线观看免费视频| 亚洲成人1区2区| 在线观看黄色| 欧美专区在线观看一区| 欧美7777| 亚洲欧美视频一区二区| 麻豆久久一区二区| 91精品国产综合久久久久久豆腐| 久久精品国亚洲| 国产精品高清无码在线观看| 国产美女精品视频国产| 日本大香伊一区二区三区| 亚洲精品一区二区三区影院| 国产激情视频网址| av动漫免费看| 男人天堂午夜在线| 四虎成人免费观看在线网址| 一本到12不卡视频在线dvd| 欧美aaaa视频| 日韩美女av在线| 国产成人在线色| 久久成人国产精品| 精品久久久久久中文字幕动漫| 国产乱子伦精品| 国产一级片网站| 免费欧美一级片| 澳门av一区二区三区| 成人美女视频| 免费一级淫片| 亚洲japanese制服美女| 亚洲娇小xxxx欧美娇小| 乱中年女人伦av一区二区| 99久久99久久精品| 国产99视频精品免费视频36| 日韩三级电影| 99久久久国产精品| 女人喷潮完整视频| 色姑娘综合网| 国产又爽又黄ai换脸| 欧美激情亚洲一区| 中文字幕 欧美激情| 秋霞网一区二区| 九九九九免费视频| 乳色吐息在线观看| 在线黄色国产视频| 在线免费观看a视频| 免费看的www视频网站视频| 中文字幕永久有效| 一级黄色片在线观看| 国产视频一区二区在线播放| 日韩一区免费观看| 国产精品国模大尺度私拍| 欧美日韩成人综合天天影院| 男人添女荫道口女人有什么感觉| 日韩欧美一区二区视频在线播放| 催眠调教后宫乱淫校园| 好吊视频在线观看| 国产97色在线|日韩| 成人网站免费观看| 精品一区二区在线免费观看| 国产三级精品在线观看| av亚洲精华国产精华精| bt7086福利一区国产| 国产亚洲福利一区| 欧美tk丨vk视频| 未来日记在线观看| 国产欧美一区二区三区米奇| 狠狠人妻久久久久久综合| 美女高潮久久久| 中国成人一区| 亚洲国产精品久久久久久| 久久精品成人| aaa黄色大片| 人妻精品久久久久中文| 亚洲在线色站| 精品一区免费观看| 中文字幕在线观看91| 日韩一区日韩二区| 电影午夜精品一区二区三区| 午夜影院免费体验区| 九九热免费在线| 一区二区三区在线视频观看58| 妺妺窝人体色www婷婷| 你懂的网站在线播放| 国产亚洲精品中文字幕| 黄色三级视频在线| 国产国语刺激对白av不卡| 亚洲三级在线免费观看| 老司机免费视频一区二区| 欧美精品三区| av有码在线观看| 欧美专区18| 国产激情偷乱视频一区二区三区| 中文字幕精品—区二区日日骚| 欧美乱大交xxxxx| jlzzjlzz亚洲日本少妇| 日韩国产在线一区| 天堂蜜桃一区二区三区| 青草全福视在线| 精品福利一区二区三区| 成人免费黄色在线| 国产精品美女免费视频| 在线看日韩av| 国产伦理在线观看| 日本三级小视频| 免费在线视频你懂得| 国产精品国产亚洲精品| 在线看日韩精品电影| 日日狠狠久久偷偷综合色| 国产精品51麻豆cm传媒| 97精品国产97久久久久久春色| 国产视频青青| 免费黄色av网站| 成人看片app| 全彩无遮挡全彩口工漫画h#| 欧美色图另类图片| 国产又粗又长视频| 久久撸在线视频| 六九午夜精品视频| 亚洲精品国产av| 国产又黄又粗又猛又爽的视频| 亚洲色图欧美在线| 国产精品18久久久久久首页狼| 日韩麻豆第一页| 四虎精品在永久在线观看| 日韩啪啪电影网| 国产精品2023| 久久久久久欧美精品色一二三四| 你懂的在线观看| 青青草视频在线观看| 久久不射中文字幕| 欧美在线观看在线观看| 波多野结衣一区| 国产午夜精品一区理论片飘花| 久草手机视频在线观看| 激情久久一区二区| 麻豆av在线免费观看| 成人午夜视频免费看| 亚洲 欧美 精品| 精品国产一区二区在线观看| 天天骑夜夜操| 欧美大成色www永久网站婷| 精品中文在线| 国产97免费视| 国产91美女视频| 久久成人精品无人区| 亚洲欧美小说色综合小说一区| 欧美一区二区三区视频在线| 亚洲视频在线观看一区二区三区| 精品国产高清a毛片无毒不卡| 国产天堂av| 久久五月天色综合| 欧美在线亚洲在线| 日韩精品电影一区亚洲| 自拍偷拍国产亚洲| 久久精品国产亚洲一区二区| 欧美激情a∨在线视频播放| 日韩免费精品视频| 51精品久久久久久久蜜臀| 日韩免费毛片视频| 小泽玛利亚一区二区三区视频| 成年人午夜久久久| 久久久久久欧美精品se一二三四| 91精品婷婷国产综合久久| av影院在线播放| 一区二区成人在线视频| 综合国产在线视频| 丁香婷婷综合激情| 国产精品一区二区av日韩在线| 久草免费在线观看| 在线中文字幕视频| 国产欧美精品一区二区色综合朱莉| 亚洲一区自拍偷拍| 欧美高清精品3d| 干日本少妇首页| 一区二区黄色片| 一区二区在线中文字幕电影视频| 四虎影音在线| 中文字幕一区二区三区欧美日韩| 37p粉嫩大胆色噜噜噜| 成人黄色图片网站| 免费观看黄一级视频| 精品亚洲一区二区三区在线播放| 亚洲自拍另类| 婷婷综合激情网| 99精品欧美| 日韩av电影网址| 色综合影院在线观看| 91精品在线观看入口| 欧美夫妻性生活xx| 亚洲av人人澡人人爽人人夜夜| 黑人巨大精品欧美一区二区一视频| 久久一留热品黄| 国模精品一区二区三区色天香| 久久亚洲AV无码| 欧美一区二区精品| 天堂电影院在线| 激情av综合| 欧美精品免费在线观看| 五月天激情在线| av在线com| 美女91在线看| 日韩不卡av| 成人影音在线| 99精品欧美一区二区| 黄网站在线免费看| 亚洲无线一线二线三线区别av| 国产一级做a爰片在线看免费| 日韩免费特黄一二三区| 午夜av入18在线| 一个人看的视频www在线观看免费| 日韩暖暖在线视频| 美女100%露胸无遮挡| 美女被艹网站| 成人免费自拍视频| 久久久不卡网国产精品二区| 亚洲国产精品免费在线观看| 亚洲v日韩v欧美v综合| 欧美做爰性生交视频| 欧美 日韩 人妻 高清 中文| 在线播放精品一区二区三区| 你懂的国产视频| 中文一区一区三区免费|