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

运行截图:

python tinker随机点名_redis


主窗口

python tinker随机点名_python tinker随机点名_02


点名操作

python tinker随机点名_json_03

人脸识别操作

具体代码如下:
主窗口:

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