【物联网树莓派毕设05】给人脸识别门禁做个tkinter可登录可控制界面并显示结果,超详细

一、前期准备

        1、这次是结合前面的做个阶段性总结,在硬件端加个简单的tkinter界面,管理员登录并可以控制人脸识别门禁的开关,以及实时显示视频流,显示人脸识别结果,记忆日志记录。具体如何在树莓派上做的一些准备,可参考前几期:

        【物联网树莓派毕设01】树莓派4B快速实现VNC连接

        【物联网树莓派毕设02】树莓派4B安装Pyhton3及opencv

        【物联网树莓派毕设03】树莓派4B调用百度API快速实现人脸识别

        【物联网树莓派毕设04】Arduino实现电梯及人脸识别门禁

        2、安装必要的库,如已安装可跳过

python -m pip install --upgrade pip //先更新pip
pip install opencv-python //摄像头
pip install pillow //图像控件
pip install baidu-aip //百度api
pip install pyserial //串口

        3、效果展示

 【物联网树莓派毕设05】给人脸识别门禁做个tkinter可登录可控制界面并显示结果,超详细_第1张图片【物联网树莓派毕设05】给人脸识别门禁做个tkinter可登录可控制界面并显示结果,超详细_第2张图片

 二、具体实现

        1、实现tkinter界面跳转,有2个方法

        (1)设置1个根窗口,2个frame,利用destory方法,实现登录frame跳转至首页frame,缺点是跳转之后不可回到登录frame,即只能实现一次跳转,如需继续跳转,需要新建frame,如法炮制

top = tk.Tk()#新建tk根窗口
top.title("人脸识别门禁系统")
top.geometry("300x300+350+180")#设置窗口位置
top.resizable(width=False, height=False) #设置窗口不可改变

login = login(top)#进入login frame
try:
   top.wait_window(window=login)#直到login窗口销毁,login界面跳转index界面
   index(top)#进入index frame
except Exception as e:
   print("erro:",e)#异常捕获处理
   pass

top.mainloop()  #窗口消息循环     

        (2)设置2个根窗口,利用lambda表达式即可,可以实现两个窗口来回切换

def login():
    root1=tk.Tk()
    root1.geometry("300x300+450+200")#设置窗口位置
    bu1=tk.Button(root1,text="登录",command=lambda:[root1.destroy(),index()])
    bu1.pack()
    root1.mainloop()

def index():
    root2=tk.Tk()
    root2.geometry("300x300+450+200")#设置窗口位置
    bu1=tk.Button(root2,text="登陆成功,回到登录",command=lambda:[root2.destroy(),login()])
    bu1.pack()
    root2.mainloop()

login()

        2、放置各组件在容器内的位置的3个方法

        (1)pack():默认先使用的放到上面,然后依次向下排,它会给我们的组件一个自认为合适的位置 和大小,这是默认方式。【进入学习pack】

        (2)grid():类比多维数组,会根据组件自动计算。【进入学习grid】

        (3)place():设置控件在窗体或窗口内的绝对地址或相对地址。【进入学习place】

        3、tk的Frame、Toplevel、Button、Label、Entry、Canvas创建

        (1)Frame:作为一种容器,可以把其他组件放在frame上。

import tkinter as tk #tk界面

master = tk.Tk()#新建tk根窗口
index_frame =tk.Frame(master)
index_frame.grid() #设置参数,可以调整大小,位置等

master.mainloop()  #窗口消息循环

        (2)Toplevel:作为顶级窗口,在原有窗口上弹出的窗口,一般可用于信息确认,密码验证等等

import tkinter as tk #tk界面

check_frame = tk.Toplevel() #新建顶级窗口
#布局
check_frame.title("验证管理员权限")
check_frame.geometry("300x200+580+300")

        (3)Button:按钮控件,不过tk的按钮太丑了,可以引入ttk,好看一点。button的第一个参数是放在的容器,command是绑定按钮处理函数

from tkinter import ttk #tk子部件,更加美观
import tkinter as tk #tk界面

master = tk.Tk()#新建tk根窗口
login_frame = tk.Frame(master)#新建frame
login_frame.grid() #展示frame

def cert():
    #弹出顶级窗口
    check_frame = tk.Toplevel() #新建顶级窗口
    check_frame.title("登录验证")
    check_frame.geometry("300x200+580+300")
    print("登录处理")

button1 = ttk.Button(login_frame, text = '立即登录',width = 28,command = cert)
button1.pack()

master.mainloop()

        (4)  Label及Entry:标签和输入框,标签可以放文字,也可以放图片,输入框获取输入。

给出登录界面代码

import tkinter as tk
import  tkinter.messagebox
import  pickle
from PIL import Image, ImageTk

window = tk.Tk()
window.title('login')
window.geometry('300x200')

# 登陆界面
tk.Label(window, text='账户:').place(x=50,y=60) #标签
tk.Label(window, text='密码:').place(x=50, y=100)

var_usr_name = tk.StringVar() #定义字符串输入变量
enter_usr_name = tk.Entry(window, textvariable=var_usr_name).place(x=100, y=60) #输入框

var_usr_pwd = tk.StringVar()
enter_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*').place(x=100, y=100)

#登陆
def usr_login():
    #输入框内容
    usr_name = var_usr_name.get()
    usr_pwd = var_usr_pwd.get()
    print("用户名:",usr_name)
    print("密码:",usr_pwd)

#退出
def usr_quit():
    window.destroy()

#登录 退出按钮
bt_login = tk.Button(window,text='登录',command=usr_login).place(x=100,y=130)

bt_logquit = tk.Button(window,text='退出',command=usr_quit).place(x=160,y=130)

window.mainloop()

        (5)Canvas:画布,一般用来放图片或者视频,视频就是一帧帧刷新进行显示。【进入学习Canvas】

import tkinter as tk #tk界面

master = tk.Tk()#新建tk根窗口
index_frame =tk.Frame(master)
index_frame.grid() #设置参数,可以调整大小,位置等

#新建画布
canvas = tk.Canvas(index_frame,height = 463, width = 895)
canvas.pack(side = 'top')

master.mainloop()  #窗口消息循环

        4、tk界面插入背景图片

import tkinter as tk #tk界面

master = tk.Tk()#新建tk根窗口
index_frame =tk.Frame(master)
index_frame.grid() #设置参数,可以调整大小,位置等

#新建画布
canvas = tk.Canvas(index_frame,height = 463, width = 895)
canvas.pack(side = 'top')

#创建画布背景图
global photo #设置全局变量,解决图片不显示的问题
photo = tk.PhotoImage(file = 'bg_img.gif') #gif图片的路径,不支持jpg,png
canvas.create_image(449, 233, image=photo)#前面为偏移参数

master.mainloop()  #窗口消息循环

若遇到问题,可参考Python tkinter之PhotoImage图片显示问题

        5、动态更新人脸识别结果

        用label显示人脸识别结果,才用循环创建label覆盖,即可实现动态显示,直接点击右上角关闭会报错,需要处理

import tkinter as tk
import time

index=tk.Tk()
index.wm_title("测试")
index.geometry('500x300+450+200')

var = tk.StringVar()  #设置string类型的变量
var.set("0")        #设置初始值
tk.Label(index, text= "动态显示" , font = ("微软雅黑",24)).grid(row=1,column=0)

while(True):
    var.set(chr(ord(var.get())+ 1))#设置显示的内容,如人脸识别返回的结果
    tk.Label(index, text= var.get() , font = ("微软雅黑",24)).grid(row=1,column=1) #每次显示的位置要一致,覆盖效果
    time.sleep(1)
    index.update()  #不断更新
index.mainloop() 

        6、在画布Canvas实时显示视频流

        跟上面动态显示结果类似,也是采用循环1帧帧更新摄像头获取的图像,实现动态显示视频,直接点击右上角关闭会报错,需要处理

import tkinter as tk
from PIL import Image, ImageTk#图像控件
import cv2

cap = cv2.VideoCapture(0)#创建摄像头对象

top = tk.Tk()
top.title('人脸识别门禁系统')
top.geometry('580x600+450+100')

#绘制视频画布
canvas = tk.Canvas(top,bg = 'white',width = 580,height = 600 )
canvas.pack()

#图像预处理
def tkImage():
    ref,frame=cap.read()
    frame = cv2.flip(frame, 1) #摄像头翻转
    cvimage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    pilImage=Image.fromarray(cvimage)
    pilImage = pilImage.resize((image_width, image_height),Image.ANTIALIAS)
    tkImage =  ImageTk.PhotoImage(image=pilImage)
    return tkImage

#动态显示
while True:
  pic = tkImage()
  canvas.create_image(0,0,anchor = 'nw',image = pic)
  top.update()

cap.release()
top.mainloop()  

        7、日志

        建立一个txt文件,记录下管理员的操作,以及人脸识别结果。

【物联网树莓派毕设05】给人脸识别门禁做个tkinter可登录可控制界面并显示结果,超详细_第3张图片

import time
import datetime

now_time = datetime.datetime.now()
str_time = now_time.strftime("%Y-%m-%d %X")# 格式化时间字符串

log = open("log.txt", "a",encoding='utf-8')#每次打开会接着往下写,若文件不存在则会自己创建
log = open("log.txt", "w",encoding='utf-8')#每次打开会清空日志内容,若文件不存在则会自己创建
log.write(str_time+"  "+"管理员重置人脸识别门禁系统日志!\n")

log.close()# 关闭打开的文件

三、说明

        1、整合

        结合前几期的内容,以及这期的主要内容,进行代码整合,即可实现tkinter界面的人脸识别门禁管理系统,在此基础上,可以继续添加管理员的注册管理,人脸信息登记,对视频流进行图像处理,加一些动态特效啥的,还可以对接数据库等等

        2、tk界面动态显示的时候,直接右上角关闭界面会报错的问题

        因为程序在循环里还在执行,直接关闭会摧毁窗口,但图像还在获取,会报Erro: Too early to create image的错误 。

解决方法:利用protocol("WM_DELETE_WINDOW",quit)#触发点击窗口关闭处理事件。捕获点击右上角关闭事件,然后在quit函数里进行处理,通知界面不要再获取图像了,常见方法就是在获取图像函数里设置信号量,之后该释放的资源释放,该摧毁的摧毁,该关闭的关闭

        3、一些小点

        (1)密码输入框: tk.Entry(login_frame,show='*'),通过参数show='*',隐藏输入的内容

        (2)组件设置后,要设置place或者grid或者pack方法才会显示

        (3)为了弥补tk组件的美观,ttk可以设置style,类似css,具体参考官方文档

        (4)在画布上添加组件:canvas.create_window(210, 50, window=tk.Entry(login_frame, borderwidth=3)),实现在画布的背景图片上添加组件。

        

你可能感兴趣的:(毕设,物联网,iot,python)