文章目录
- 前言
- PySimpleGUI 库
- 1-布局和窗口
- 2 文本框组件
- 3-视频处理
- 图片处理
- 数据库操作
- 数据采集(重要部分)
- 人脸识别(综合部分)
前言
例如:随着人工智能的不断发展,本文主要介绍关于人工智能中GUI和PyMysql相应用。
本文采用代码+逻辑思路分析的方式有助于理解代码。
PySimpleGUI 库
PySimpleGUI 是一个用于简化 GUI 编程的 Python 包,它封装了多种底层 GUI 框架(如 tkinter、Qt、WxPython 等),提供了简单易用的 API。PySimpleGUI 包含了大量的控件(也称为小部件或组件),这些控件可以帮助你快速构建用户界面。
首先在要在电脑中下载mysql,然后针对于我们要下载的环境进入虚拟环境:
conda activate “虚拟环境的位置"
安装:
```python
pip install pysimplegui
进行安装
1-布局和窗口
import PySimpleGUI as sg
#创建一个布局组件
layout =[
[sg.Button("关闭"),sg.Button("人脸采集")]
]
#创建窗口
window = sg.Window("我的第一个窗口",layout)
while True:
#读取窗口信息 ,返回窗口的数据和鼠标事件
event,value = window.read()
if event in (None,"关闭"):
#提示
print("你点了关闭按钮")
# 提示
sg.popup("你点击了关闭按钮")
#跳出循环
break
if event in ("人脸采集",):
print("你点了人脸采集按钮")
#提示
sg.popup("你点了人脸采集按钮")
#资源释放,关闭窗口
window.close()
代码讲解:
这里导入PySimPleGUI库 ,并将其重命名为“sg”
通过sg.window创建一个window类的一个实例,实例被赋值给变量window,用于后续的操作,传入窗口标题和布局。
window.read()方法会阻塞程序,等待用户与窗口进行交互,并返回事件名称
这一段是一个无限循环,用于监听窗口中的事件(按钮点击)。而window.read()作为一个类方法,读取窗口中事件和值,会阻塞程序运行用户点击了按钮,然后返回事件名称和值。
这里着重提到event作为用户触发事件名称的按钮标签或者键名。如果用户关闭了窗口而没有触发任何特定事件,则event可能为none。
values字典: 包含了窗口中所有输入元素的值。字典的键通常是输入元素的键名,值则是用户输入的内容。
示例:如果你在布局中有一个输入框 sg.InputText(key=‘-NAME-’),用户在该输入框中输入了 “John”,那么 values 字典中将包含 {‘-NAME-’: ‘John’}。
遇到的问题:
此图调用会出现关闭窗口的问题,来单独说明一下:
最开始if event =="关闭"会出现打印运行结果(关闭)的情况,但是却关闭出了窗口,会出现循环一直调用的情况,在这种情况下if event in (None,“关闭”),更符合我们平时对代码的实际运用,当用户点击了标签为 “关闭” 的按钮,或者用户通过其他方式(如点击窗口右上角的关闭按钮)关闭了窗口时,条件都会为真。
1、
2、
3
这是运行的过程和结果。
2 文本框组件
import PySimpleGUI as sg
#创建一个布局组件
layout =[
[sg.Text("编号",size=(10,1)),sg.InputText(key="id")],
[sg.Text("姓名",size=(10,1)),sg.InputText(key="name")],
[sg.Text(key="msg")],
[sg.Button("关闭"),sg.Button("保存")]
]
#创建窗口
window = sg.Window("我的第一个窗口",layout)
while True:
#读取窗口信息 ,返回窗口的数据和鼠标事件
event,value = window.read()
print(value)
print(event)
if event in (None,"关闭"):
#提示
print("你点了关闭按钮")
# 提示
sg.popup("你点击了关闭按钮")
#跳出循环
break
if event in ("保存",):
#获取编号
id = value["id"]
name = value["name"]
window["msg"].update(f"id:{id},name:{name}")
#提示
sg.popup(f"id:{id},name:{name}")
#资源释放,关闭窗口
window.close()
注意事项:
1、这里有我自己学习过程中的疑惑,对于sg.popup作为PySimpleGUI中的函数,用于显示一个弹出的窗口,如果不加入sg.popup也不会有太大的影响,但是对于用户真实使用中有确定的作用。
2、关于value的重要意义中的作用: 存储所有带有 key 属性的输入组件的当前值。字典的键是组件的 key,值是该组件的当前值。无法获取输入值:
你将无法获取用户在输入框中输入的值。
例如,如果你有一个输入框 sg.InputText(key=“id”),不写入 values 会导致你无法获取用户输入的编号。
无法更新动态组件:
你将无法更新带有 key 属性的动态组件,如 sg.Text。
例如,如果你有一个动态文本标签 `sg
3-视频处理
import PySimpleGUI as sg
import cv2
#开启摄像头
def demo():
cap = cv2.VideoCapture(0)
if cap.isOpened() ==False:
print("没有开启摄像头")
return
#创建layout
layout = [
[sg.Button("关闭")],
[sg.Image(key="video")]
]
#创建窗口
window = sg.Window("视频处理",layout)
while True:
#读取数据和事件
event,value = window.read(timeout=10)
#读取数据帧
ret,frame = cap.read()
print(event)
if event in (None, "关闭"):
break
if ret:
imgType = cv2.imencode(".png", frame)[1].tobytes()
window["video"].update(imgType)
#释放资源3
cap.release()
window.close()
demo()
注意事项: 1、首先要明白要返回是在调用函数中,则查看是否开启摄像头的检查中采用“return”,则需要先对函数进行定义,def demo() 最后进行调用。
2、在最开始使用layout创建一个布局组件和创建窗口时候运用的是排列组件,定义组件:layout 列表中包含了所有要在窗口中显示的组件(如按钮、输入框、文本标签等)。每个组件由 PySimpleGUI 提供的各种类(如 sg.Button, sg.InputText, sg.Text 等)实例化。排列组件:layout 列表中的每个子列表表示一行组件。每个子列表中的元素表示该行中的各个组件。通过这种方式,你可以灵活地安排组件的布局,使其符合你的用户界面设计需求。
3、
单独对代码进行解释:
cv2.imencode(“.png”, frame)
cv2.imencode: 这是 OpenCV 库中的一个函数,用于将图像数据编码为指定格式的字节流。
参数:
“.png”: 指定编码格式为 PNG。
frame: 这是一个 NumPy 数组,表示一帧图像数据。
返回值: cv2.imencode 返回一个元组 (retval, buffer),其中:
retval 是一个布尔值,表示编码是否成功。
buffer 是一个 NumPy 数组,包含编码后的图像数据。
2. [1]
[1]: 从 cv2.imencode 返回的元组中提取第二个元素,即编码后的图像数据(buffer)。
3. .tobytes()
.tobytes(): 将 NumPy 数组转换为字节流(bytes 类型)。这是 PySimpleGUI 更新图像时所需的格式。
4. window[“video”].update(imgType)
window[“video”]: 通过键值 “video” 访问窗口中的某个组件。假设你在布局中定义了一个带有 key=“video” 的图像组件。
.update(imgType): 更新该图像组件的内容,将其设置为 imgType,即编码后的图像字节流。
图片处理
主要对电脑中的图片进行传递,上传成功,在后期关于联动成一个完整项目有所帮助。
def demo():
#创建layout
layout = [
[sg.Button("关闭"),sg.Button("上传")],
[sg.Input(key='-FILE-', enable_events=True),
sg.FileBrowse(file_types=(("Image Files", "*.png;*.jpg;*.jpeg;*.gif"),))],
[sg.Image(key="video")]
]
#创建窗口
window = sg.Window("文件处理",layout)
while True:
event,value = window.read()
if event in (None,"关闭"):
break
if event == "上传":
#图片路径不能用中文
path = value["-FILE-"]
img = cv2.imread(path)
imgType = cv2.imencode(".png", img)[1].tobytes()
print(path)
window["video"].update(imgType)
window.close()
demo()
运行结果:
需要提到的除了按照正常程序导入库,导入layout相关的布局组件、创建窗口、然后就是对功能的编辑、最后释放资源进行运行。 传入图片路径不要用中文命名否则会出现报错的故障。
在这里还要提到一个情况:
“img = cv2.imread(path) imgType = cv2.imencode(".png", img)[1].tobytes()
”如果在上传中即便图片设置的不为中文,出现报错的情况可以通过这个代码进行格式的更改。
数据库操作
首先运行代码:
conda activate "虚拟环境命名"
然后在虚拟环境安装
pip install PyMySQL
关于数据库操作的代码:
import pymysql
#新增
def add(name,num):
#创建数据库连接
con = pymysql.connect(
host = "localhost",#数据库地址
user = "root",#用户名
passwd = "你自己设置的密码",#密码
port = 3306,#端口
database = "your name",#数据库名
charset = "utf8"
)
#创建游标对象,包含了增删改查的函数
cur = con.cursor()
#定义sql
sql = "insert into user_info (user_name,user_num)value(%s,%s)"
#运行sql(增删改查sql的函数)
cur.execute(sql, (name,num))
#执行增删改的sql的函数,返回一个受影响行数的数值
num = cur.rowcount
if num > 0 :
print("新增成功")
else:
print("新增失败")
# 提交
con.commit()
# 释放资源
cur.close()
con.close()
#x修改
if __name__ == '__main__':
add("张三",1)
这是基本的增加的代码,关于增删改查大体是一致的所以搞懂之间的逻辑才是最重要的。
首先我们应该更加注意到数据操作的几个大体逻辑顺序
1、导入import pymysql模块
2、创建数据库连接
3、获取游标对象
4、执行sql查询(增删改查)
5、获取查询结果
6、关闭游标和进行连接(指的是释放资源,因为定义了函数,所以还要加一个调用函数步骤)
需要注意的是在执行插入语句的时候,values中(%s)代表的是占位符,而values关键字用于指定到要插入到表中。
数据采集(重要部分)
关于之前的铺垫都是为了进行数据采集以及视频识别的综合功能的连接
import pymysql
import PySimpleGUI as sg
import cv2
#人脸信息用户记录
#新增
def add(name,num):
#创建数据库连接
con = pymysql.connect(
host = "localhost",#数据库地址
user = "root",#用户名
passwd = "123456",#密码
port = 3306,#端口
database = "demo91",#数据库名
charset = "utf8"
)
#创建游标对象,包含了增删改查的函数
cur = con.cursor()
#定义sql
sql = "insert into user_info (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 dataGet():
#开启摄像头像
cap = cv2.VideoCapture(0)
if cap.isOpened()==False:
print("摄像头没有开启")
return
#创建布局
layout = [
[sg.Text("编号:"),sg.InputText(key="num")],
[sg.Text("姓名:"), sg.InputText(key="name")],
[sg.Image(key="video")],
[sg.Button("关闭"),sg.Button("人脸采集")]
]
#创建窗口
window = sg.Window("人脸信息采集",layout)
while True:
event,value = window.read(timeout=10)
#读取视频
ret ,frame = cap.read()
if event in (None,"关闭"):
#终止循环
break
if ret:
imtType = cv2.imencode(".png",frame)[1].tobytes()
window["video"].update(imtType)
if event =="人脸采集":
#获取编号和姓名
num = value["num"]
name = value["name"]
#写入人脸图片
iss = cv2.imwrite(f"C:\\Users\\LENOVO\\Desktop\\opencv\\faceImages\\{num}.png",frame)
if iss:
isAdd=add(name,num)
if isAdd:
sg.popup("人脸采集成功")
else:
sg.popup("人脸采集失败")
cap.release()
window.close()
if __name__ == '__main__':
dataGet()
人脸存在图片可以自己创建一个文件夹(最好是不带中文的)使用情况中如果"/“或者”“出现问题,使用”\“进行更改。
人脸识别(综合部分)
通过数据库、电脑视频、和数据采集的联动,本文是前面几个内容的综合体,通过前面的学习最后能够独立完成关于人脸识别的项目。
import pymysql
import PySimpleGUI as sg
import cv2
import face_recognition
import os
import numpy as np
#查询
def query(num):
#创建数据库连接
con = pymysql.connect(
host="localhost",#数据库地址
user="root",#用户名
passwd="123456",#密码
port=3306,#端口
database="demo91",#数据库名
charset="utf8" #中文编码
)
#创建游标对象,包含了增删改查的函数
cur = con.cursor()
#定义sql
sql = "select * from user_info where user_num=%s"
#运行sql(增删改查sql的函数)
cur.execute(sql, (num,))
# 查询
rs = cur.fetchall()
print(rs)
cur.close()
con.close()
if len(rs) > 0:
print(rs[0][1])
return rs[0][1]
else:
return "查无此人"
#人脸识别窗口
def dataGet():
#开启摄像头像
cap = cv2.VideoCapture(0)
if cap.isOpened()==False:
print("摄像头没有开启")
return
#创建布局
layout =[
[sg.Image(key="video")],
[sg.Button("关闭"),sg.Button("人脸识别")]
]
#创建窗口
window = sg.Window("人脸识别",layout)
#循环
while True:
event,value = window.read(timeout=10)
#读取视频
ret ,frame = cap.read()
if event in (None,"关闭"):
#终止循环
break
if ret:
imtType = cv2.imencode(".png",frame)[1].tobytes()
window["video"].update(imtType)
if event =="人脸识别":
#查找人脸库
list_dir = os.listdir("C:\\Users\\LENOVO\\Desktop\\opencv\\faceImages")
if len(list_dir)>0:
for i in list_dir:
print(i)
#读取一个图片对象
img = cv2.imread(f"C:\\Users\\LENOVO\\Desktop\\opencv\\faceImages\\{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.3:
b = i.split(".")[0]
a = query(b)
sg.popup(f"用户{a}打卡成功")
#查到此人,终止循环
break
else:
sg.popup("人脸库没有此人")
cap.release()
window.close()
if __name__ == "__main__":
dataGet()
if len(rs) > 0:
print(rs[0][1])
return rs[0][1] 这里提到了之前的python基础中索引知识
这里就是对之前的知识的综合理解,在实际操作中,需要注意拍照的光线、被识别人的表情,可能会造成对识别的误差,当然通过摄像头识别到人脸传入到指定相册,通过识别与指定相册相匹配数据传入数据库,进行识别达到人脸识别的目的。