import xlrd
import xlwt
from xlrd.sheet import Sheet
from xlutils.copy import copy
from datetime import datetime
import cv2
import time
import tkinter as tk


class faceRecognitionGUI:

    def __init__(self):
        # 初始化GUI
        self.root = tk.Tk()
        self.root.title("人脸识别签到系统")
        self.root.geometry("400x350+400+200")

        # 添加签到按钮
        self.sign_button = tk.Button(self.root, text="开始签到", command=self.sign_in, font=("微软雅黑", 16), width=15, height=2)
        self.sign_button.pack()

        # 添加签到结果文本框
        self.result_text = tk.StringVar()
        self.result_text.set("请点击“开始签到”按钮进行签到。")
        self.result_label = tk.Label(self.root, textvariable=self.result_text,font=("微软雅黑", 16))
        self.result_label.pack()

        # 添加查看签到表按钮
        self.check_button = tk.Button(self.root, text="查看签到表", command=self.check_signin_list, font=("微软雅黑", 16), width=15, height=2)
        self.check_button.pack()

        # 添加退出按钮
        self.quit_button = tk.Button(self.root, text="退出程序", command=self.root.quit, font=("微软雅黑", 16), width=15, height=2)
        self.quit_button.pack()

        # 导入应到学生（用户）名单
        self.workbook = xlrd.open_workbook('签到表.xls')  # 导入考勤记录表
        self.worksheet = self.workbook.sheet_by_index(0)  # 打开工作表
        self.stu_num = self.worksheet.col_values(1)  # 提取工作表第1列，第1列为学生学号
        self.stu_name = self.worksheet.col_values(2)  # 提取工作表第2列，第2列为学生名字

        # 人脸识别参数初始化
        self.classifier = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
        self.recognizer_create = cv2.face.LBPHFaceRecognizer_create()
        self.recognizer_create.read('face_model.yml')  # 读取训练好的模型
        self.ID = 'Unkonw'
        self.flag = 0  # 标记次数
        self.start_time = time.time()  # 系统时间提取
        self.duration = 10  # 人脸识别持续时间

    def sign_in(self):
        # 打开摄像头进行签到
        self.capture = cv2.VideoCapture(0)  # 打开摄像头

        while self.capture.isOpened():  # 当打开摄像头的时候
            kk = cv2.waitKey(1)  # 等待键盘的输入
            _, frame = self.capture.read()  # 读取摄像头内容
            gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)  # 将读取到的RGB图像转换为灰度图像
            faces = self.classifier.detectMultiScale(gray, 1.3, 5)  # 让classifier判断人脸，detectMultiScale函数可以检测出图像中的人脸

            if len(faces) != 0:  # 如果能找到人脸
                # 框选人脸
                for x, y, w, h in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 0), 2)  # 用矩形框框出人脸，xy为左上角的坐标，w为宽，h为高
                    roi_face = gray[y:y + h, x:x + w]
                    label, conf = self.recognizer_create.predict(roi_face)  # 预测出的学号和可信度

                    if conf < 60:
                        index = [list for list, i in enumerate(self.stu_num) if
                                 i == str(label)]  # 得到预测学号在excel表格中所在的行数（注：index的值是从0开始的，index=3表示在excel表格中的第4行）
                        if index != []:
                            self.name = self.stu_name[index[0]]
                            self.ID = self.stu_num[index[0]]
                            self.flag += 1
                        else:
                            self.ID = 'Unknow'

                    cv2.putText(frame, str(self.ID), (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255),
                                2)  # 添加字幕

            cv2.putText(frame, 'please "esc" to quit ', (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255),
                        2)  # 在窗口上添加文字，参数依次表示：图像、要添加的文字、文字的位置、字体、字体大小、颜色、粗细
            cv2.imshow("picture from a cammre", frame)  # 打开窗口的名称

            if self.flag > 5:
                self.sign_name(index[0], self.name)
                self.result_text.set("签到成功，欢迎您，" + self.name)
                break
            if time.time() - self.start_time > self.duration:  # 如果超时，则签到失败
                self.result_text.set("签到失败，请重新签到。")
                break
            if kk == 27:  # 如果退出
                self.result_text.set("签到已终止，请重新签到。")
                break

        # 释放变量
        self.capture.release()
        cv2.destroyAllWindows()

    def sign_name(self, idx, name):
        # 在签到表签字
        workbook1 = xlrd.open_workbook('签到表.xls')  # 读取excel文件
        newbook1 = copy(workbook1)  # 复制文件
        newsheet1 = newbook1.get_sheet(0)  # 在源文件上追加
        newsheet1.write(idx, 4, time.ctime())  # 第idx行，第4列，写入签到时间，样式为style0（注：代码中的行列是从0开始的）
        newsheet1.write(idx, 3, name)  # 第idx行，第3列，写入签到学生的名字，样式为style1（（注：代码中的行列是从0开始的））
        newbook1.save('签到表.xls')

    def check_signin_list(self):
        # 查看签到表
        self.workbook = xlrd.open_workbook('签到表.xls')  # 导入考勤记录表
        self.worksheet = self.workbook.sheet_by_index(0)  # 打开工作表
        rows, cols = self.worksheet.nrows, self.worksheet.ncols
        table = []
        for i in range(rows):
            row_list = []
            for j in range(cols):
                row_list.append(self.worksheet.cell(i, j).value)
            table.append(row_list)
        table_str = '\n'.join([str(row) for row in table])  # 将表格数据转换成字符串类型
        # 在一个新的tkinter窗口中显示表格数据
        list_window = tk.Toplevel(self.root)
        list_window.title("签到表")
        list_window.geometry("500x300")
        scrollbar = tk.Scrollbar(list_window)  # 创建一个Scrollbar位于右侧
        scrollbar.pack(side='right', fill='y')
        text = tk.Text(list_window, wrap='none', yscrollcommand=scrollbar.set)  # 创建一个Text控件
        text.pack(side='left', expand=True, fill='both')
        scrollbar.config(command=text.yview)  # 将Scrollbar绑定至该Text控件
        text.insert('1.0', table_str)  # 在Text控件中插入表格内容

    def run(self):
        self.root.mainloop()


if __name__ == '__main__':
    app = faceRecognitionGUI()
    app.run()
解释这段代码运行过程