每日一小时打卡pc端毕业设计(具有人脸专注度检测和人脸识别的监控功能)

发布时间 2023-04-23 20:52:49作者: 小彭先森

 

 

 

 

 

 

 

 

 

 代码:

# coding=utf-8
import cv2 as cv
import cv2
import datetime
import base64
import time
import imutils
import dlib
from imutils import face_utils
from scipy.spatial import distance as dist
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import requests
from PyQt5.QtCore import Qt, QTimer, QTime
from PyQt5.QtGui import QImage, QPixmap, QFont, QStandardItemModel, QStandardItem
import pymysql
from PyQt5.QtMultimedia import QCamera
from PyQt5.QtMultimediaWidgets import QCameraViewfinder
from PyQt5.QtWidgets import *



# 人脸识别
def getToken():
    ak = 'B7E2OqVuDAyDs7OsuGPuKa4y'
    sk = 'idObOz6jqA2GdU49L2VG4VPVhgmiidvD'
    host = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={ak}&client_secret={sk}'
    response = requests.get(host)
    return response.json().get("access_token")


def img_to_base64(file_path):
    with open(file_path, 'rb') as f:
        base_64_data = base64.b64encode(f.read())
        s = base_64_data.decode()
        return s


# 人脸库对比寻找人脸
def FaceDetect1(token_, base_64_data):
    params = {}
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"
    params["image"] = base_64_data
    params["image_type"] = "BASE64"
    params["group_id_list"] = "face"
    access_token = token_
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        return response.json()["result"]["user_list"][0]["score"]


def FaceDetect2(token_, base_64_data):
    params = {}
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"
    params["image"] = base_64_data
    params["image_type"] = "BASE64"
    params["group_id_list"] = "face"
    access_token = token_
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        return response.json()["result"]["user_list"][0]["user_info"]


def FaceDetect(token_):
    params = {}
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/getusers"

    params["group_id"] = "face"

    access_token = token_
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        array1 = response.json()["result"]["user_id_list"]
        return len(array1)


# 添加人脸信息
def addface(a):
    token_ = getToken()
    num = FaceDetect(token_)
    num += 1
    ak = 'B7E2OqVuDAyDs7OsuGPuKa4y'
    sk = 'idObOz6jqA2GdU49L2VG4VPVhgmiidvD'
    host = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={ak}&client_secret={sk}'
    response = requests.get(host)
    token_ = response.json().get("access_token")
    file_path = "photo.png"
    with open(file_path, 'rb') as f:
        base_64_data = base64.b64encode(f.read())
        base_64_data1 = base_64_data.decode()
    params = {}
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add"
    params["image"] = base_64_data1
    params["image_type"] = "BASE64"
    params["group_id"] = "face"
    params["user_id"] = "user_" + str(num)
    params["user_info"] = a
    access_token = token_
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        print(response.json()["error_msg"])


# 连接数据库,添加数据
def addsjk(a, b, c, d):
    db = pymysql.connect(host="localhost", user="root", password="PENGsuoqun123", db="bb")
    cur = db.cursor()
    sql1 = "insert into information(id,name,classname,pwd) values(%s, %s, %s, %s)"
    val = (a, b, c, d)
    try:
        cur.execute(sql1, val)
        db.commit()
    except Exception as a:
        raise a
    finally:
        db.close()


class Login(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Login")
        self.setFixedSize(1000, 700)

        # 学号输入框
        self.username_label = QLabel("学号:")
        self.username_edit = QLineEdit()
        self.username_layout = QHBoxLayout()
        self.username_layout.addWidget(self.username_label)
        self.username_layout.addWidget(self.username_edit)

        # 设置用户名输入框字体
        username_font = QFont()
        username_font.setPointSize(20)
        self.username_label.setFont(username_font)

        # 密码输入框
        self.password_label = QLabel("密码:")
        self.password_edit = QLineEdit()
        self.password_edit.setEchoMode(QLineEdit.Password)
        self.password_layout = QHBoxLayout()
        self.password_layout.addWidget(self.password_label)
        self.password_layout.addWidget(self.password_edit)

        # 设置密码输入框字体
        password_font = QFont()
        password_font.setPointSize(20)
        self.password_label.setFont(password_font)

        # 登录按钮
        self.login_button = QPushButton("登录")
        self.login_button.clicked.connect(self.login)
        self.login_button.setFixedSize(150, 60)

        # 注册按钮
        self.signup_button = QPushButton("注册")
        self.signup_button.clicked.connect(self.show_signup)
        self.signup_button.setFixedSize(150, 60)

        # 创建水平布局
        self.buttons_layout = QHBoxLayout()

        # 在水平布局中添加两个按钮
        self.buttons_layout.addWidget(self.login_button)
        self.buttons_layout.addStretch(1)
        self.buttons_layout.addWidget(self.signup_button)

        # 页面布局
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.username_layout)
        self.layout.addLayout(self.password_layout)
        self.layout.addLayout(self.buttons_layout)

        # 设置当前窗口的布局
        self.setLayout(self.layout)

    def login(self):
        # 在此处写登录逻辑
        username = self.username_edit.text()
        password = self.password_edit.text()
        # 连接MySQL数据库
        conn = pymysql.connect(host='localhost', user='root', password='PENGsuoqun123', db='bb')
        cursor = conn.cursor()

        # 执行查询语句
        query = "SELECT * FROM information WHERE id=%s AND pwd=%s"
        cursor.execute(query, (username, password))
        # 判断是否查询到结果
        try:
            if cursor.fetchone() is not None:
                QMessageBox.information(self, "登录结果", "请验证人脸")
                self.camera = Camera()
                self.camera.exec_()
                img1 = img_to_base64("photo.png")
                token_ = getToken()
                score = FaceDetect1(token_, img1)
                iid = FaceDetect2(token_, img1)
                if score > 85:
                    if iid == username:
                        QMessageBox.information(self, "登录结果", "登录成功!")
                        self.Main_window = Main(username, password)
                        self.Main_window.show()
                        self.hide()
                    else:
                        QMessageBox.information(self, "登录结果", "人脸不匹配!")
                else:
                    QMessageBox.information(self, "登录结果", "人脸不匹配!")
            else:
                QMessageBox.information(self, "登录结果", "账号或密码错误!")
            # 关闭连接和游标
            cursor.close()
            conn.close()
        except Exception as e:
            QMessageBox.information(self, "登录结果", "人脸不匹配!")
            print(e)

    def show_signup(self):
        self.signup_window = Signup()
        self.signup_window.show()
        self.hide()


class Signup(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Sign up")
        self.setFixedSize(1000, 700)

        # 注册的姓名
        self.name_label = QLabel("姓名:")
        self.name_edit = QLineEdit()
        self.name_layout = QHBoxLayout()
        self.name_layout.addWidget(self.name_label)
        self.name_layout.addWidget(self.name_edit)
        name_font = QFont()
        name_font.setPointSize(20)
        self.name_label.setFont(name_font)

        # 注册的学号
        self.id_label = QLabel("学号:")
        self.id_edit = QLineEdit()
        self.id_layout = QHBoxLayout()
        self.id_layout.addWidget(self.id_label)
        self.id_layout.addWidget(self.id_edit)
        id_font = QFont()
        id_font.setPointSize(20)
        self.id_label.setFont(id_font)

        # 注册的班级
        self.class_label = QLabel("班级:")
        self.class_edit = QLineEdit()
        self.class_layout = QHBoxLayout()
        self.class_layout.addWidget(self.class_label)
        self.class_layout.addWidget(self.class_edit)
        class_font = QFont()
        class_font.setPointSize(20)
        self.class_label.setFont(class_font)

        # 注册的密码
        self.password1_label = QLabel("密码:")
        self.password1_edit = QLineEdit()
        self.password1_layout = QHBoxLayout()
        self.password1_layout.addWidget(self.password1_label)
        self.password1_layout.addWidget(self.password1_edit)
        password1_font = QFont()
        password1_font.setPointSize(20)
        self.password1_label.setFont(password1_font)

        # 注册按钮
        self.signup_button = QPushButton("注册")
        self.signup_button.clicked.connect(self.signup)
        self.signup_button.setFixedSize(150, 60)

        # 返回按钮
        self.back_button = QPushButton("返回登录页面")
        self.back_button.clicked.connect(self.show_login)
        self.back_button.setFixedSize(150, 60)
        # 创建水平布局
        self.button1_layout = QHBoxLayout()

        # 在水平布局中添加两个按钮
        self.button1_layout.addWidget(self.signup_button)
        self.button1_layout.addStretch(1)
        self.button1_layout.addWidget(self.back_button)

        # 页面布局
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.name_layout)
        self.layout.addLayout(self.id_layout)
        self.layout.addLayout(self.class_layout)
        self.layout.addLayout(self.password1_layout)
        self.layout.addLayout(self.button1_layout)
        self.setLayout(self.layout)

    def signup(self):
        # 在此处写注册逻辑
        name = self.name_edit.text()
        id = self.id_edit.text()
        password1 = self.password1_edit.text()
        classname = self.class_edit.text()
        if len(id) != 8:
            QMessageBox.warning(self, "注册失败", "请输入正确长度的学号!!!")
        else:
            addsjk(id, name, classname, password1)
            self.camera = Camera()
            self.camera.exec_()
            # 此处人脸录入代码
            addface(id)
            QMessageBox.information(self, "注册结果", "人脸已录入,注册成功")
            self.show_login()

    def show_login(self):
        self.login_window = Login()
        self.login_window.show()
        self.hide()


class Camera(QDialog):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.setWindowTitle("人脸录入")
        self.setFixedSize(640, 480)

        # 初始化摄像头
        self.cap = cv2.VideoCapture(0)

        # 定时器,每30毫秒更新一次图像
        self.timer = QTimer()
        self.timer.timeout.connect(self.show_camera)
        self.timer.start(10)

    def init_ui(self):
        # 标签控件,用于显示摄像头捕获的图像
        self.label = QLabel(self)
        self.label.setAlignment(Qt.AlignCenter)

        # 拍照按钮
        self.Photo_button = QPushButton('拍照', self)
        self.Photo_button.clicked.connect(self.take_photo)

        # 垂直布局
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        layout.addWidget(self.Photo_button)
        self.setLayout(layout)

    def show_camera(self):
        # 读取摄像头捕获的图像
        ret, frame = self.cap.read()

        # 将图像转换为Qt可显示的格式
        if ret:
            img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            h, w, c = img.shape
            qimg = QImage(img.data, w, h, w * c, QImage.Format_RGB888)
            self.label.setPixmap(QPixmap.fromImage(qimg))

    def take_photo(self):
        # 读取摄像头捕获的图像
        ret, frame = self.cap.read()

        # 将图像保存为文件
        if ret:
            cv2.imwrite('photo.png', frame)
            self.cap.release()  # 关闭摄像头,否则与专注度检测冲突
            self.accept()  # 关闭当前窗口

    def closeEvent(self, event):
        # 释放摄像头资源
        self.cap.release()
        super().closeEvent(event)


class Main(QMainWindow):
    def __init__(self, username, password):
        super().__init__()

        self.setFixedSize(1000, 700)
        self.setWindowTitle('专注度检测')

        self.username = username
        self.password = password

        # 创建左侧部件
        self.btn_1 = QPushButton('专注度检测', self)
        self.btn_2 = QPushButton('每日记录', self)
        self.btn_3 = QPushButton('个人资料查看及修改', self)
        self.btn_4 = QPushButton('修改密码', self)

        left_layout = QVBoxLayout()
        left_layout.addWidget(self.btn_1)
        left_layout.addWidget(self.btn_2)
        left_layout.addWidget(self.btn_3)
        left_layout.addWidget(self.btn_4)
        left_layout.addStretch(5)
        left_layout.setSpacing(20)
        left_widget = QWidget()
        left_widget.setLayout(left_layout)

        # 创建右侧部件
        self.stack_widget = QStackedWidget(self)

        self.EYE_AR_THRESH = 0.2
        self.EYE_AR_CONSEC_FRAMES = 3

        self.detector = dlib.get_frontal_face_detector()
        self.predictor = dlib.shape_predictor(
            'D:/myworkspace/fatigue_detecting-master/fatigue_detecting-master/model/shape_predictor_68_face_landmarks.dat')
        (self.lStart, self.lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
        (self.rStart, self.rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
        self.num1 = 0
        self.num2 = 0
        self.COUNTER = 0
        self.TOTAL = 0
        self.time_sum = 0
        self.fps = 30

        self.timer_camera = QTimer(self)

        page1 = QWidget()
        layout1 = QVBoxLayout(page1)
        label1 = QLabel('专注度检测')
        label1.setAlignment(Qt.AlignHCenter)
        label1.setFont(QFont("宋体", 23))
        layout1.addWidget(label1)
        layout1.addSpacing(20)
        self.button1 = QPushButton('开始学习', self)
        self.button2 = QPushButton('结束学习', self)
        hbox = QHBoxLayout()
        hbox.addWidget(self.button1)
        hbox.addWidget(self.button2)
        layout1.addLayout(hbox)
        self.capp = cv2.VideoCapture(0)
        self.frame = QLabel(page1)
        layout1.setAlignment(Qt.AlignTop)
        layout1.addWidget(self.frame)
        self.code_label = QLabel('代码提交:', page1)
        self.code_edit = QTextEdit(page1)
        self.code_edit.setLineWrapMode(QTextEdit.NoWrap)  # 关闭自动换行
        code_layout= QHBoxLayout()
        code_layout.addWidget(self.code_label)
        code_layout.addWidget(self.code_edit)
        layout1.addLayout(code_layout)


        #label2用于更换摄像头照片

        page1.setStyleSheet("background-color: #fff;")

        self.stack_widget.addWidget(page1)
        self.button1.clicked.connect(self.start_camera)
        self.button2.clicked.connect(self.stop_camera)

        page2 = QWidget()
        layout2 = QHBoxLayout(page2)

        # 连接到 MySQL 数据库
        conn = pymysql.connect(
            host='localhost',
            user='root',
            password='PENGsuoqun123',
            db='bb'
        )

        # 执行查询语句
        with conn.cursor() as cursor:
            sql = 'SELECT time,totaltime,focustime,focus,codelen FROM learn_record WHERE id=%s'
            cursor.execute(sql, (self.username))
            results = cursor.fetchall()

        # 创建 QStandardItemModel 模型
        self.model = QStandardItemModel()

        # 设置表头
        self.model.setHorizontalHeaderLabels(['提交时间', '学习总时间(秒)', '专注时间(秒)', '专注度(%)', '代码行数'])

        # 将查询结果添加到模型中
        for row_data in results:
            row_items = []
            for col_data in row_data:
                item = QStandardItem(str(col_data))
                item.setTextAlignment(Qt.AlignCenter)  # 居中显示
                row_items.append(item)
            self.model.appendRow(row_items)

        # 创建 QTableView 控件并设置模型
        table_view = QTableView()
        table_view.setModel(self.model)

        # 设置列宽
        table_view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        table_view.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeToContents)
        table_view.horizontalHeader().setSectionResizeMode(4, QHeaderView.ResizeToContents)
        table_view.horizontalHeader().setStretchLastSection(True)

        # 关闭数据库连接
        conn.close()

        # 将表格添加到布局中
        layout2.addWidget(table_view)
        self.stack_widget.addWidget(page2)
        page2.setStyleSheet("background-color: #fff;")

        # 个人资料显示以及修改
        conn = pymysql.connect(host='localhost', user='root', password='PENGsuoqun123', db='bb')
        cursor = conn.cursor()
        query = "SELECT * FROM information WHERE id=%s AND pwd=%s"
        cursor.execute(query, (username, password))
        result = cursor.fetchone()
        name = result[1]
        classname = result[2]
        page3 = QWidget()
        layout3 = QVBoxLayout(page3)
        label31 = QLabel('个人资料查看及修改')
        label31.setAlignment(Qt.AlignHCenter)
        label31.setFont(QFont("宋体", 23))
        layout32 = QHBoxLayout()
        label32 = QLabel('姓名:')
        label32.setFont(QFont("宋体", 20))
        label32.setAlignment(Qt.AlignHCenter)
        self.label32x = QLineEdit(name)
        self.label32x.setAlignment(Qt.AlignLeft)
        layout32.addWidget(label32)
        layout32.addWidget(self.label32x)

        layout34 = QHBoxLayout()
        label34 = QLabel('班级:')
        label34.setFont(QFont("宋体", 20))
        label34.setAlignment(Qt.AlignHCenter)
        self.label34x = QLineEdit(classname)
        layout34.addWidget(label34)
        layout34.addWidget(self.label34x)

        layout33 = QHBoxLayout()
        label331 = QLabel('学号:' + username + '(学号不可修改)')
        label331.setAlignment(Qt.AlignHCenter)
        label331.setFont(QFont("宋体", 15))
        layout33.addWidget(label331)

        button = QPushButton('确认')
        button.clicked.connect(self.reviseinf)
        button.setFixedSize(120, 40)
        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        # 再将整个子布局添加到主布局中
        layout3.addWidget(label31)
        layout3.addStretch(1)
        layout3.addLayout(layout33)
        layout3.addStretch(1)
        layout3.addLayout(layout32)
        layout3.addStretch(1)
        layout3.addLayout(layout34)
        layout3.addStretch(1)
        layout3.addWidget(button, alignment=Qt.AlignHCenter)

        page3.setStyleSheet("background-color: #fff;")
        self.stack_widget.addWidget(page3)

        page4 = QWidget()
        layout4 = QVBoxLayout(page4)
        layout4.setAlignment(Qt.AlignTop)
        label41 = QLabel('修改密码')
        label41.setAlignment(Qt.AlignHCenter)
        label41.setFont(QFont("宋体", 23))
        old_password_layout = QHBoxLayout()
        old_password_label = QLabel('旧密码:')
        old_password_label.setFont(QFont("宋体", 20))
        self.old_password_edit = QLineEdit()
        old_password_layout.addWidget(old_password_label)
        old_password_layout.addWidget(self.old_password_edit)
        new_password_layout = QHBoxLayout()
        new_password_label = QLabel('新密码:')
        new_password_label.setFont(QFont("宋体", 20))
        self.new_password_edit = QLineEdit()
        new_password_layout.addWidget(new_password_label)
        new_password_layout.addWidget(self.new_password_edit)
        confirm_password_layout = QHBoxLayout()
        confirm_password_label = QLabel('确认密码:')
        confirm_password_label.setFont(QFont("宋体", 20))
        self.confirm_password_edit = QLineEdit()
        confirm_password_layout.addWidget(confirm_password_label)
        confirm_password_layout.addWidget(self.confirm_password_edit)
        confirm_button = QPushButton('确认')
        confirm_button.clicked.connect(self.revise)
        confirm_button.setFixedSize(120, 40)
        confirm_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        layout4.addWidget(label41)
        layout4.setSpacing(90)
        layout4.addLayout(old_password_layout)
        layout4.addLayout(new_password_layout)
        layout4.addLayout(confirm_password_layout)
        layout4.addWidget(confirm_button, alignment=Qt.AlignHCenter)
        page4.setStyleSheet("background-color: #fff;")
        self.stack_widget.addWidget(page4)

        # 将左侧和右侧部件添加到主布局中
        main_layout = QHBoxLayout()
        main_layout.addWidget(left_widget)
        main_layout.addWidget(self.stack_widget)
        main_layout.setStretch(0, 1)
        main_layout.setStretch(1, 4)

        main_widget = QWidget()
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

        # 连接按钮的单击信号到相应的页面
        self.btn_1.clicked.connect(lambda: self.stack_widget.setCurrentIndex(0))
        self.btn_2.clicked.connect(lambda: self.stack_widget.setCurrentIndex(1))
        self.btn_3.clicked.connect(lambda: self.stack_widget.setCurrentIndex(2))
        self.btn_4.clicked.connect(lambda: self.stack_widget.setCurrentIndex(3))


    def revise(self):
        old = self.old_password_edit.text()
        new = self.new_password_edit.text()
        confirm = self.confirm_password_edit.text()
        if new != confirm:
            QMessageBox.information(self, " 修改密码", "新密码与确定密码不一样!!!")
        else:
            if old != self.password:
                QMessageBox.information(self, " 修改密码", "原密码错误!!!")
            else:
                self.password = new
                conn = pymysql.connect(host='localhost', user='root', password='PENGsuoqun123', db='bb')
                cursor = conn.cursor()

                # 根据id和pwd更新信息表中的记录
                query = "UPDATE information SET pwd=%s WHERE id=%s"
                cursor.execute(query, (new, self.username))

                # 提交更改
                conn.commit()

                # 关闭连接
                cursor.close()
                conn.close()
                QMessageBox.information(self, " 修改密码", "修改成功!!!")


    # 修改资料代码
    def reviseinf(self):
        name = self.label32x.text()
        classname = self.label34x.text()
        conn = pymysql.connect(host='localhost', user='root', password='PENGsuoqun123', db='bb')
        cursor = conn.cursor()

        # 根据id和pwd更新信息表中的记录
        query = "UPDATE information SET name=%s , classname=%s WHERE id=%s"
        cursor.execute(query, (name, classname, self.username))

        # 提交更改
        conn.commit()

        # 关闭连接
        cursor.close()
        conn.close()
        QMessageBox.information(self, " 修改信息", "修改成功!!!")

    def start_camera(self):
        self.time_start = time.time()
        global shifou
        shifou=1
        self.timer_camera.timeout.connect(self.show_cameraa)
        self.timer_camera.start(1000 // self.fps)
        self.button1.setDisabled(True)

    def eye_aspect_ratio(self, eye):
        A = dist.euclidean(eye[1], eye[5])
        B = dist.euclidean(eye[2], eye[4])
        C = dist.euclidean(eye[0], eye[3])
        ear = (A + B) / (2.0 * C)
        return ear

    def show_cameraa(self):
        ret, image = self.capp.read()
        frame = imutils.resize(image, width=720)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        rects = self.detector(gray, 0)
        self.num2 = len(rects)
        self.num1 += 1
        if (self.num2 == 0):
            self.TOTAL += 1

        for rect in rects:
            shape = self.predictor(gray, rect)
            shape = face_utils.shape_to_np(shape)
            leftEye = shape[self.lStart:self.lEnd]
            rightEye = shape[self.rStart:self.rEnd]
            leftEAR = self.eye_aspect_ratio(leftEye)
            rightEAR = self.eye_aspect_ratio(rightEye)
            ear = (leftEAR + rightEAR) / 2.0
            leftEyeHull = cv2.convexHull(leftEye)
            rightEyeHull = cv2.convexHull(rightEye)
            cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
            cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)
            left = rect.left()
            top = rect.top()
            right = rect.right()
            bottom = rect.bottom()
            cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 3)
            if ear < self.EYE_AR_THRESH:
                self.COUNTER += 1
            else:
                if self.COUNTER >= self.EYE_AR_CONSEC_FRAMES:
                    self.TOTAL += 5
                self.COUNTER = 0

            for (x, y) in shape:
                cv2.circle(frame, (x, y), 1, (0, 0, 255), -1)

            cv2.putText(frame, "Faces: {}".format(len(rects)), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(frame, "Blinks: {}".format(self.TOTAL), (150, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(frame, "COUNTER: {}".format(self.COUNTER), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(frame, "EAR: {:.2f}".format(ear), (450, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(frame, "Total time:" + str(int(self.time_sum)) + "s", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            cv2.putText(frame, "Focus on time:" + str(int(self.time_sum * (self.num1 - self.TOTAL) / self.num1)) + "s", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

        self.time_end = time.time()
        self.time_sum = self.time_end - self.time_start
        self.show_imagee(frame)
        # 等待20ms,进入下一次循环
        cv2.waitKey(20)

    def show_imagee(self, image):
        show_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        height, width, bytesPerComponent = show_image.shape
        bytesPerLine = bytesPerComponent * width
        q_image = QImage(show_image.data, width, height, bytesPerLine, QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(q_image)
        self.frame.setPixmap(pixmap)

    def closeEvent(self, event):
        self.capp.release()
        self.timer_camera.stop()
        cv2.destroyAllWindows()
        self.button1.setDisabled(False)

    def stop_camera(self):
        if shifou==0:
            QMessageBox.information(self, "警告", "您还没有开始学习")
        if shifou==1:
            now = datetime.datetime.now()
            self.capp.release()
            self.timer_camera.stop()
            cv2.destroyAllWindows()
            self.button1.setDisabled(False)
            text = self.code_edit.toPlainText()  # 获取文本内容
            lines = text.splitlines()  # 分隔每一行
            line_count = len(lines)  # 计算行数
            focust = int(100 * (int(self.time_sum * (self.num1 - self.TOTAL) / self.num1)) / int(self.time_sum))
            QMessageBox.information(self, "学习结果", "您一共学习了" + str(int(self.time_sum)) + "s  专注度为" +
                                    str(focust) + "%")
            # 把数据存入数据库里面
            db = pymysql.connect(host="localhost", user="root", password="PENGsuoqun123", db="bb")
            cur = db.cursor()
            sql1 = "insert into learn_record(id,time,totaltime,focustime,focus,codelen) values(%s, %s, %s, %s,%s,%s)"
            val = (
            self.username, now, int(self.time_sum), int(self.time_sum * (self.num1 - self.TOTAL) / self.num1), focust,
            line_count)
            try:
                cur.execute(sql1, val)
                db.commit()
            except Exception as a:
                raise a
            finally:
                db.close()
            self.model.removeRows(0, self.model.rowCount())
            conn = pymysql.connect(
                host='localhost',
                user='root',
                password='PENGsuoqun123',
                db='bb'
            )

            # 执行查询语句
            with conn.cursor() as cursor:
                sql = 'SELECT time,totaltime,focustime,focus,codelen FROM learn_record WHERE id=%s'
                cursor.execute(sql, (self.username))
                results = cursor.fetchall()

            # 将查询结果添加到模型中
            for row_data in results:
                row_items = []
                for col_data in row_data:
                    item = QStandardItem(str(col_data))
                    item.setTextAlignment(Qt.AlignCenter)  # 居中显示
                    row_items.append(item)
                self.model.appendRow(row_items)




if __name__ == "__main__":
    shifou = 0
    app = QApplication([])
    login_window = Login()
    login_window.show()
    app.exec_()