一、利用PySimpleGUI构建窗口界面
1.1、 PySimpleGUI 的安装
python
复制代码
pip install pysimplegui
1.2、构建主界面
python
复制代码
import PySimpleGUI as psg
from face_gui.face_gather import face_gather
from face_gui.face_videos import face_video
from face_gui.face_tuopens import face_tuopen
def face_gui():
# 创建一个布局组件
layout = [
[psg.Text('员工编号', size=(6, 1), font=('微软雅黑', 12)), psg.InputText(key='num', size=(20, 1))],
[psg.Text('员工姓名', size=(6, 1), font=('微软雅黑', 12)), psg.InputText(key='name', size=(20, 1))],
[psg.Text(key='nsg')],
[psg.Text(key='msg')],
[psg.Button('人脸采集'), psg.Button('打卡'), psg.Button('选择图片'), psg.Button('退出')],
[psg.Image(key='video', size=(640, 480))] # 添加摄像头显示区域
]
# 创建一个窗口
window = psg.Window('人脸识别系统', layout, icon='../images/hq.ico')
while True:
# 读取窗口信息,返回窗口数据和事件
event, values = window.read()
if event == psg.WIN_CLOSED or event == '退出':
break
if event == "人脸采集":
# 获取编号和姓名
ygid = values['num']
name = values['name']
window['msg'].update(f'编号:{ygid},姓名:{name}')
face_video(values) # 传递 values 字典
# psg.popup('人脸采集成功')
if event == "打卡":
# 获取编号和姓名
# ygid = values['num']
# name = values['name']
# window['nsg'].update("正在验证身份信息")
# window['msg'].update(f'编号:{ygid},姓名:{name}')
face_gather()
# psg.popup('打卡成功')
if event == "选择图片":
# 调用图片选择功能
face_tuopen()
# 关闭窗口,释放资源
window.close()
1.3、实现人脸信息采集
python
复制代码
import cv2
import PySimpleGUI as psg
from face_gui.face_mysql import add
def face_video(values):
# 开启摄像头
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not cap.isOpened():
print("摄像头打开失败")
return
# 创建摄像头窗口的布局
camera_layout = [
[psg.Image(key='video', size=(640, 480))],
[psg.Button('识别'), psg.Button('关闭摄像头')]
]
# 创建摄像头窗口
camera_window = psg.Window('信息采集', camera_layout, icon='../images/hq.ico')
while True:
# 读取摄像头窗口信息,返回窗口数据和事件
event, _ = camera_window.read(timeout=10)
if event == psg.WIN_CLOSED or event == '关闭摄像头':
break
# 读取数据帧
ret, frame = cap.read()
if ret:
# 把数据帧转换成btepy数据类型
imgbytes = cv2.imencode('.png', frame)[1].tobytes()
camera_window['video'].update(data=imgbytes)
if event == '识别':
# 获取编号和姓名
num = values['num']
name = values['name']
iss = cv2.imwrite(f"../face_train_images/{num}.png", frame)
if iss:
isadd = add(name, num)
if isadd:
psg.popup('添加成功')
else:
psg.popup('添加失败')
# psg.popup('识别完成')
# 关闭摄像头窗口,释放资源
camera_window.close()
cap.release()
1.4、实现人脸识别
python
复制代码
import os
import cv2
import PySimpleGUI as psg
import face_recognition
import numpy as np
from face_gui.face_mysql import select
def face_gather():
# 开启摄像头像
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
if not cap.isOpened():
print("摄像头没有开启")
return
# 创建布局
layout = [
[psg.Image(key="video")],
[psg.Button("验证"), psg.Button("关闭")]
]
# 创建窗口
camera_window = psg.Window("验证", layout)
# 循环
while True:
event, value = camera_window.read(timeout=10)
# 读取视频
ret, frame = cap.read()
if event in (None, "关闭"):
# 终止循环
break
if ret:
imttype = cv2.imencode(".png", frame)[1].tobytes()
camera_window["video"].update(imttype)
if event == "验证":
# 查找人脸库
list_dir = os.listdir("../face_train_images")
if len(list_dir) > 0:
for i in list_dir:
print(i)
# 读取一个图片对象
img = cv2.imread(f"../face_train_images/{i}")
if img is None:
print("没有读取图片")
break
else:
# 获取已知图片的特征变量
en1 = face_recognition.face_encodings(img)[0]
# 获取需要检测图片的特征变量
en2 = face_recognition.face_encodings(frame)[0]
# 计算欧几里得距离
rs = np.linalg.norm(en1 - en2)
print(rs)
if rs < 0.6:
b = i.split(".")[0]
select(b)
psg.popup("打卡成功")
# 查到此人,终止循环
break
else:
psg.popup("人脸库没有此人")
break
cap.release()
camera_window.close()
1.5、文件上传
python
复制代码
import io
import PySimpleGUI as psg
from PIL import Image
def face_tuopen():
# 创建layout
layout = [
[psg.Text('请选择一张图片或视频:')],
[psg.Input(key='-FILE-', enable_events=True),
psg.FileBrowse(
file_types=(("Image and Video Files", "*.png;*.jpg;*.jpeg;*.gif;*.bmp;*.mp4;*.avi;*.mov;*.mkv"),))],
[psg.Button('退出')],
[psg.Image(key='-IMAGE-', size=(640, 480))]
]
# 创建窗口
window = psg.Window('文件处理', layout, size=(640, 480))
while True:
event, values = window.read()
# 处理事件
if event in (psg.WINDOW_CLOSED, '退出'):
break
elif event == '-FILE-':
# 更新图片
image_path = values['-FILE-']
print(image_path)
if image_path:
try:
# 使用 Pillow 打开图像
image = Image.open(image_path)
# 调整图像大小以适应窗口
image.thumbnail((640, 480))
# 将图像转换为 Tkinter 可以使用的格式
bio = io.BytesIO()
image.save(bio, format='PNG')
window['-IMAGE-'].update(data=bio.getvalue())
except Exception as e:
print(f"Error loading image: {e}")
psg.popup_error(f"无法加载图像: {e}")
window.close()
1.6、数据库操作
python
复制代码
import pymysql
# 新增数据
def add(name, num):
# 创建数据库连接
con = pymysql.connect(
host='localhost', # 数据库地址
port=3306, # 数据库端口
user='root', # 用户名
password='123456', # 密码
database='face', # 数据库名称
charset='utf8'
)
# 创建游标对象,包含了增删改查的函数
cur = con.cursor()
# 定义sql
sql = "insert into user(user_name,user_num) value (%s,%s)"
# 运行sql(增删改查sql的函数)
cur.execute(sql, (name, num))
# 执行增删改sql的函数,返回一个受影响行数的数值
num = cur.rowcount
# 提交
con.commit()
# 释放资源
cur.close()
con.close()
if num > 0:
print("新增成功")
return True
else:
print("新增失败")
return False
# 查询数据
def select(num):
with pymysql.connect(
host='localhost', # 数据库地址
port=3306, # 数据库端口
user='root', # 用户名
password='123456', # 密码
database='face', # 数据库名称
charset='utf8' # 编码格式
) as db:
with db.cursor() as cursor:
sql = "select * from user where user_num=%s"
try:
cursor.execute(sql, (num,))
# 获取所有记录列表
results = cursor.fetchall()
if results:
for row in results:
uesr_id = row[0]
uesr_name = row[1]
uesr_num = row[2]
print(f"uesr_id:{uesr_id}, uesr_name:{uesr_name}, uesr_num:{uesr_num}")
else:
print("未找到匹配的记录")
except Exception as e:
print(f"Error: {e}")
# 删除数据
def delete(num):
with pymysql.connect(
host='localhost', # 数据库地址
port=3306, # 数据库端口
user='root', # 用户名
password='123456', # 密码
database='face', # 数据库名称
charset='utf8'
) as db:
with db.cursor() as cursor:
sql = "DELETE FROM user WHERE uesr_num=%s"
try:
cursor.execute(sql, (num,))
# 提交数据
db.commit()
print("删除成功")
except Exception as e:
print(f"Error: {e}")
db.rollback()
print("删除失败")
# 修改数据
def update(name, num, new_name=None, new_num=None):
with pymysql.connect(
host='localhost', # 数据库地址
port=3306, # 数据库端口
user='root', # 用户名
password='123456', # 密码
database='face', # 数据库名称
charset='utf8'
) as db:
with db.cursor() as cursor:
# 动态生成 SQL 语句
updates = []
params = []
if new_name is not None:
updates.append("uesr_name=%s")
params.append(new_name)
if new_num is not None:
updates.append("uesr_num=%s")
params.append(new_num)
if not updates:
print("未提供任何更新内容")
return
sql = f"UPDATE user SET {', '.join(updates)} WHERE user_name=%s AND user_num=%s"
params.extend([name, num])
try:
cursor.execute(sql, params)
# 提交数据
db.commit()
print("更新成功")
except Exception as e:
print(f"Error: {e}")
db.rollback()
print("更新失败")
1.7、主函数调用
python
复制代码
from face_gui.face_gui_windows import face_gui
if __name__ == '__main__':
face_gui()