python 点名随机+人脸识别

基于tkinter写的随机点名窗口程序

运行截图:
在这里插入图片描述
主窗口
在这里插入图片描述
点名操作
在这里插入图片描述

人脸识别操作

具体代码如下:
主窗口:

import random
import tkinter
import tkinter as tk
import threading
import time
from tkinter.filedialog import askopenfilename
import tkinter.messagebox as mb
from ttkbootstrap import Style
import imageCode
import utils.photographUtils as photograph
import os
import utils.requestsUtils as request
import utils.redisUtils as redis
import base64


class RollName:

    def __init__(self):
        self.b_face_reg = None
        self.var_name_msg = None
        self.l_show_message = None
        self.var_name = None
        self.rd_random = None
        self.rd_order = None
        self.lf1 = None
        self.b_add_names = None
        self._img = None
        self.T = None
        self.b_startRoll = None
        self.var = None
        self.l_show_name = None
        self.flag = True
        self.default_name = None
        self.imageName = None
        style = Style(theme='journal')
        self.root = style.master

        self.root.title('点名系统')
        self.width, self.height = 800, 500  # 获取屏幕最大宽高
        width_max, height_max = self.root.maxsize()
        s_center = '%dx%d+%d+%d' % (self.width, self.height,
                                    (width_max - self.width) / 2, (height_max - self.height) / 2)  # 设置位置居中
        self.root.geometry(s_center)  # 设置窗口位置
        self.root.resizable(width=False, height=False)  # 设置窗口不可拉动
        self.set_element()
        self.place_element()
        self.redis_conn = redis.getRedis()

    # 窗口组件位置
    def set_element(self):
        self.var_name = tkinter.StringVar()  # Lable显示文字
        self.var_name.set("会是谁呢?")
        self.l_show_name = tk.Label(self.root, textvariable=self.var_name, font=('黑体', 100), fg='blue')
        self.b_startRoll = tk.Button(self.root, text='开始', bg='Tan', command=self.start, width=10)  # 按钮选项
        paned = tk.PanedWindow(self.root)
        paned.image = tk.PhotoImage(data=imageCode.base_64_to_img())  # 向窗口插入图片
        self._img = tk.Label(self.root, image=paned.image, background='black')
        self.b_add_names = tk.Button(self.root, text='手动加载人员名单', bg='Tan', command=self.load_file,
                                     width=18)  # 加载名字按钮
        self.lf1 = tk.LabelFrame(self.root, text="点名方式")  # 嵌套
        self.var = tkinter.IntVar()
        self.var.set(1)
        self.rd_order = tk.Radiobutton(self.lf1, text='顺序点名', variable=self.var, value=1)  # 嵌套框里的radiobutton
        self.rd_random = tk.Radiobutton(self.lf1, text='随机点名', variable=self.var, value=2)
        self.var_name_msg = tkinter.StringVar()  # 提示lable
        self.var_name_msg.set("请先导入数据!")  # Lable显示文字
        self.l_show_message = tk.Label(self.root, textvariable=self.var_name_msg, fg='orange', font=('宋体', 30))
        self.b_face_reg = tk.Button(self.root, text='点击拍照识别', bg='Tan', command=self.checkFace)  # 人脸识别按钮
        self.b_face_reg.config(state='disabled')

    def place_element(self):
        self.l_show_name.place(x=100, y=50)
        self.b_startRoll.place(x=400, y=350)
        self._img.place(x=100, y=350)
        self.b_add_names.place(x=550, y=350)
        self.lf1.place(x=350, y=250, width=350, height=70)
        self.rd_order.place(x=20, y=10)
        self.rd_random.place(x=150, y=10)
        self.l_show_message.place(x=350, y=400)
        self.b_face_reg.place(x=150, y=280)

    # 读取文件
    def load_file(self):
        self.default_name = []
        try:
            filename = askopenfilename(  # askopenfilename文件选择对话框
                filetypes=[('文本文件', '.TXT'), ],
                title="选择一个文本文件",
                initialdir="./"
            )
            if filename:
                with open(filename, 'r', encoding='utf-8') as f:
                    names = [name.strip() for name in f.readlines()]
                    if names:
                        self.default_name = names
                        self.var_name_msg.set('共有个%d学生数据' % len(names))
                        self.b_face_reg.config(state='normal')
        except Exception:
            mb.showwarning("警告", "导入失败,请重试")

    # 点名的方法
    def event_Roll(self):

        if self.b_startRoll["text"] == "开始":
            if self.default_name is None:
                mb.showerror('错误提示', '请先导入名字哦!')
            else:
                self.b_add_names.config(state='disabled')
                self.b_startRoll.config(text="就你了")
                self.flag = True
                if self.var.get() == 1:
                    while self.flag:
                        for name in self.default_name:
                            self.var_name.set(name)
                            self.l_show_name.config(textvariable=self.var_name)  # 刷新label内容
                            time.sleep(0.05)
                            if self.flag is False:
                                break

                if self.var.get() == 2:
                    while self.flag:
                        self.var_name.set(random.choice(self.default_name))
                        self.l_show_name.config(textvariable=self.var_name)  # 刷新label内容
                        time.sleep(0.05)
        else:
            self.flag = False
            self.b_add_names.config(state='normal')
            self.b_startRoll.config(text="开始")

    # 守护线程
    def start(self):
        self.T = threading.Thread(target=self.event_Roll)  # 多线程
        self.T.setDaemon(True)  # 线程守护,即主进程结束后,此线程也结束。否则主进程结束子进程不结束
        self.T.start()  # 启动

    # 人脸识别
    def checkFace(self):
        # 设置图片名称
        self.imageName = str(time.time()) + ".png"
        # 设置图片路径
        images_path = "images/" + self.imageName
        # 调用opencv 打开摄像头
        photograph.take_a_Picture(images_path)
        # 设置人脸识别按钮不可点击
        self.b_face_reg.config(state='disabled')
        # 循环找查文件是否以及存入
        while True:
            if os.path.exists(images_path):
                break
            time.sleep(1)
        # 获取token
        token = request.getAccessToken()
        # 检测是否是人脸
        request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"
        # 将图片转为base64编码
        encoded = base64.b64encode(open(images_path, 'rb').read())
        # 设置参数
        params = {"image": encoded, "image_type": "BASE64"}
        # 调用post请求,获取返回值
        req_data = request.getPost(token, request_url, params)
        try:
            # redis连接,通过抽到的学生名字去访问redis缓存,取出学生的学号
            number = self.redis_conn.get(self.var_name.get()).decode()
        except AttributeError:
            mb.showerror("错误", "找不到这位同学呐!")
            self.b_face_reg.config(state='normal')
        # 如果返回值为SUCCESS表示成功,进入下一步操作
        if req_data == "SUCCESS":
            if number is None:
                # 如果number为空,防止没赋值
                mb.showerror("错误", "找不到这位同学呐!")
            else:
                try:
                    # 设置参数
                    faceCheckParams = {"image": encoded, "image_type": "BASE64", "group_id_list": "taritari_506216",
                                       "user_id": number}
                    # 调用人脸识别api
                    res_face = request.getFaceSearch(token, faceCheckParams)
                except Exception:
                    mb.showerror("错误", "没有录入系统,请联系 工号:202251582185")
            # 获取人脸匹配度score字段
            if float(res_face["result"]["user_list"][0]["score"]) > float(85.0):
                mb.showinfo("提示", "验证成功")
            else:
                mb.showerror("错误", "验证失败")
        # 错误输出
        else:
            mb.showerror("错误", "请移至摄像头内")

        self.b_face_reg.config(state='normal')


if __name__ == '__main__':
    a = RollName()
    a.root.mainloop()

读取base64图片:

from base64 import b64decode


def base_64_to_img():
    # 读取b64数据
    with open("./src/img_base64.txt", 'rb') as f:
        img_ = f.read()

    the_img = b64decode(img_)  # 将图片硬编码到GUI 解码
    with open("src/temp.jpg", 'wb') as f:
        f.write(the_img)
    return the_img

request:

import requests
import json


'''
post请求
access_token :OAuth2.0认证的token
request_url : 接口地址
params:数据
'''


def getPost(access_token, request_url, params):
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        try:
            dict_req = json.loads(str(response.json()).replace('\'', '\"'))
            res = dict_req["error_msg"]
        except Exception:
            res = "error"
    return res


def getAccessToken():
    # client_id 为官网获取的AK, client_secret 为官网获取的SK
    host = ''
    response = requests.post(host)
    req_str = str(response.json())
    req_str = req_str.replace('\'', '\"')
    if response:
        dict_req = json.loads(req_str)
    token = dict_req["access_token"]
    return token


'''
{'error_code': 0, 'error_msg': 'SUCCESS', 'log_id': 951284706, 'timestamp': 1665710151, 'cached': 0, 'result': {'face_token': '537c5e4450c731862c99cf193caea1b4', 'user_list': [
            {'group_id': 'taritari_506216', 'user_id': 'rzw_', 'user_info': '', 'score': 96.620323181152
            }
        ]
    }
}
'''


# 人脸识别
def getFaceSearch(token, params):
    """
    人脸搜索
    """
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"
    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:
        dict_req = json.loads(str(response.json()).replace('\'', '\"'))
    return dict_req

连接redis:

import redis


def getRedis():
    redis_conn = redis.Redis(host='', port="6379", password='', db=0)
    return redis_conn

opencv打开摄像头:

import cv2
'''
打开摄像头获取照片
'''


def take_a_Picture(images_path):
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)  # 打开摄像头
    cap.set(3, 640)
    cap.set(4, 480)
    while True:

        # get a frame
        ret, frame = cap.read()
        frame = cv2.flip(frame, 1)  # 摄像头是和人对立的,将图像左右调换回来正常显示
        # show a frame
        cv2.imshow("frame", frame)  # 生成摄像头窗口
        if cv2.waitKey(1) & 0xFF == ord('q'):  # 如果按下q 就截图保存并退出
            cv2.imwrite(images_path, frame)  # 保存路径
            break
        # 判断是否点击窗口关闭按钮
        if cv2.getWindowProperty('frame', cv2.WND_PROP_VISIBLE) < 1:
            break

    cap.release()
    cv2.destroyAllWindows()

代码主要提供参考:
人脸识别部分参考的是百度智能云:https://login.bce.baidu.com
里面的人脸识别api
具体操作请登录看具体文档
百度智能云-人脸识别接口文档:https://cloud.baidu.com/doc/FACE/s/Gk37c1uzc#%E4%BA%BA%E8%84%B8%E6%90%9C%E7%B4%A2-1n-%E8%AF%86%E5%88%AB

注意:vscode 路径问题:在设置里面搜索Execute in File Dir

【项目介绍】 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到94.5分,放心下载使用! 该资源适合计算机相关专业(如人工智能、通信工程、自动化、软件工程等)的在校学生、老师或者企业员工下载,适合小白学习或者实际项目借鉴参考! 当然也可作为毕业设计、课程设计、课程作业、项目初期立项演示等。如果基础还行,可以在此代码基础之上做改动以实现更多功能。 人脸识别考勤系统 本项目是一个基于 Python人脸识别考勤系统,主要使用了 `dlib`、`opencv`、`tkinter`、`PIL`、`pymysql` 等库,并使用了 KNN 算法进行人脸识别。 环境安装 在运行本项目之前,请确保已经安装了以下环境和库: - Python - PyCharm - dlib(需要 Cmake、Visual Basic、C++ 依赖环境) - opencv 库 - tkinter 库 - pymysql - PIL - threading - time 功能介绍 本项目具有以下功能: - 打开系统按钮:打开摄像头捕获人脸。 - 注册按钮:将人脸、学号、姓名信息存储到数据库中。 - 查看缺勤名单:将没有识别签到的学生学号和姓名导出到打开的名单界面。 - 是否开始训练:点击“是”按钮进行人脸模型的训练。 - 帮助按钮:查看使用软件的注意事项。 注意事项 在使用本项目之前,请注意以下事项: 1. 请先打开系统。 2. 注册时请对准人脸,光线充足。 3. 训练时禁止进行其他操作。 文件说明 本项目包含以下文件: - `recognition.py`:主文件。 - `db.py`:数据库文件。 - `help_tip.py`:帮助窗口文件。 - `precamera.py`:预处理文件。 - `late_name.py`:缺勤名单文件。 - `trained_knn_model.clf`:KNN 算法模型文件。 - `knn_examples` 文件夹:包含了训练集和测试集,仅供学习交流探讨使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lanlnan抱抱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值