人工智能之图像预处理、数据库、GUI布局的综合应用(数据库部分、GUI布局设计)
文章目录
- 前言
- 一、数据库
- 创建数据表
- 查询:
- 修改、删除
- GUI布局
- 成果展示
- 进行图像处理和车牌识别:
- 查询记录:
- 总结
前言
之前进行opencv项目的编写,我们成功写出了智能车牌识别系统(初学版)
以下对数据库和GUI布局设计部分进行补充,对于知识点和基本补充部分可以翻看我之前的笔记,重点是在我自己项目的纠错和遇到的问题上。
一、数据库
在完整的一个项目中,存在前端、后端、数据库、API接口、服务器等。
在我所编写的智能车牌识别项目中,基于python的应用中,数据库联动是一个重要的部分
在前面的笔记中,已经通过图像预处理、掩模和ocr文字识别模型对车牌号码识别有个初步的提取,接下来需要与数据库进行联动,在提取车牌数据中,车牌号码能够被准确的读取到数据库中。
创建数据表
首先我们要在数据库中创建一个存储数据的表,可以是手动创建也可以是通过代码将创建到自己的收据库中。
在这里我采用Navicat进行连接数据表和管理数据库中的数据,创建的主表内容有car_id、car_number、recognition_time
其中以car_id作为主键,通过自动的排序来依次增加数据增加后。
直接在python中创建的代码为
CREATE TABLE car_records (
car_id INT AUTO_INCREMENT PRIMARY KEY,
car_number VARCHAR(20) NOT NULL,
recognition_time DATETIME NOT NULL
);
做好初步的准备后进行在python中数据库代码的编写。
def add(car_number, recognition_time):
# 连接到 MySQL 数据库
con = pymysql.connect(
host="localhost", # 数据库主机地址
user="xxx", # 数据库用户名
passwd="xxxxxx", # 数据库密码
port=3306, # 数据库端口号
database="demo91", # 数据库名称
charset="utf8" # 字符编码
)
# 创建游标对象,用于执行 SQL 语句
cur = con.cursor()
# 检查是否存在相同的记录
check_sql = "SELECT * FROM car_records WHERE car_number=%s AND recognition_time=%s"
cur.execute(check_sql, (car_number, recognition_time))
# 如果记录已存在,打印提示信息并关闭连接
if cur.fetchone():
print(f"记录已存在,车牌号码: {car_number}, 识别时间: {recognition_time}")
cur.close()
con.close()
return False
# 插入新的记录
sql = "INSERT INTO car_records (car_number, recognition_time) VALUES (%s, %s)"
cur.execute(sql, (str(car_number), recognition_time))
# 获取插入的记录数
num = cur.rowcount
# 提交事务,确保数据写入数据库
con.commit()
# 关闭游标和连接
cur.close()
con.close()
# 根据插入的记录数判断是否成功
if num > 0:
print(f"新增成功,车牌号码: {car_number}, 识别时间: {recognition_time}")
return True
else:
print(f"新增失败,车牌号码: {car_number}, 识别时间: {recognition_time}")
return False
在文中我添加了注释关于数据库编写的作用
查询:
def show_records(car_number):
con_info = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'demo91'
}
con = pymysql.connect(**con_info)
cur = con.cursor()
sql = "SELECT * FROM car_records WHERE car_number=%s"
cur.execute(sql, (car_number,))
records = cur.fetchall()
cur.close()
con.close()
if records:
if all(isinstance(record, tuple) and len(record) >= 2 for record in records):
record_str = "\n".join(
[f"ID: {record[0]}, 车牌号码: {record[1]}, 识别时间: {record[2].strftime('%Y-%m-%d %H:%M:%S')}" for
record in records])
sg.popup(record_str, title="历史记录")
else:
sg.popup("数据结构错误", title="历史记录")
else:
sg.popup("未找到相关记录", title="历史记录")
这里是数据库中查询功能的编写。在这个地方对cur.execute中,由于是对car_number进行查询,在这个地方不进行其他代码的查询,采用“,”进行占位。
修改、删除
# 修改记录
def update_record(car_number, new_car_number, recognition_time):
con = pymysql.connect(
host="localhost",
user="root",
passwd="123456",
port=3306,
database="demo91",
charset="utf8"
)
cur = con.cursor()
sql = "UPDATE car_records SET car_number=%s WHERE car_number=%s AND recognition_time=%s"
cur.execute(sql, (new_car_number, car_number, recognition_time))
num = cur.rowcount
print(f"更新了{num}条记录")
con.commit()
cur.close()
con.close()
if num > 0:
print(f"更新成功,原车牌号码: {car_number}, 新车牌号码: {new_car_number}, 识别时间: {recognition_time}")
return True
else:
print(f"更新失败,原车牌号码: {car_number}, 新车牌号码: {new_car_number}, 识别时间: {recognition_time}")
return False
# 删除记录
def delete_record(car_number, recognition_time):
con = pymysql.connect(
host="localhost",
user="root",
passwd="123456",
port=3306,
database="demo91",
charset="utf8"
)
cur = con.cursor()
sql = "DELETE FROM car_records WHERE car_number=%s AND recognition_time=%s"
cur.execute(sql, (car_number, recognition_time))
num = cur.rowcount
print(f"删除了{num}条记录")
con.commit()
cur.close()
con.close()
if num > 0:
print(f"删除成功,车牌号码: {car_number}, 识别时间: {recognition_time}")
return True
else:
print(f"删除失败,车牌号码: {car_number}, 识别时间: {recognition_time}")
return False
相关的代码逻辑也有类似,在这边中较为好理解,所以不单独作注释。
GUI布局
在布局中分为按钮和功能实现部分。按钮中根据自己想布置的格局进行创作、功能实现则与图像预处理和数据库进行联动。
import PySimpleGUI as sg
import os
from PIL import Image
import io
import pymysql
# 主函数
def main():
# 定义 GUI 布局
layout = [
[sg.Text('选择图像文件')], # 文本标签,提示用户选择图像文件
[sg.Input(key='-FILE-'), sg.FileBrowse()], # 输入框用于选择文件路径,FileBrowse 按钮用于打开文件选择对话框
[sg.Text(key="msg")], # 动态文本标签,用于显示消息
[sg.Button('开始检测'), sg.Button('查看记录'), sg.Button('修改记录'), sg.Button('删除记录'), sg.Button('退出')], # 按钮,用于触发不同功能
[sg.Image(key='-IMAGE-')], # 图像显示区域
[sg.Text('识别结果:', key='-RESULT-')] # 文本标签,用于显示识别结果
]
# 创建窗口
window = sg.Window("车牌识别系统", layout)
# 主循环
while True:
event, values = window.read() # 读取事件和输入值
if event in (None, "退出"): # 如果用户关闭窗口或点击退出按钮
break # 结束循环
if event == '开始检测': # 如果用户点击“开始检测”按钮
file_path = values['-FILE-'] # 获取用户选择的文件路径
if file_path: # 如果文件路径不为空
file_path = os.path.normpath(file_path) # 规范化文件路径
print(f"规范化后的文件路径: {file_path}") # 打印规范化后的文件路径
if not os.path.exists(file_path): # 检查文件是否存在
sg.popup_error(f"文件不存在: {file_path}") # 文件不存在时显示错误信息
continue # 跳过后续操作
car_number, recognition_time = process_image(file_path) # 调用图像处理函数,获取车牌号码和识别时间
if car_number and recognition_time: # 如果成功获取车牌号码和识别时间
success = add(car_number, recognition_time) # 将数据添加到数据库
if success: # 如果添加成功
window['-RESULT-'].update(f'车牌号码: {car_number}, 识别时间: {recognition_time}') # 更新识别结果文本
window['msg'].update('图片处理和车牌识别已完成!') # 更新消息文本
print(f"GUI更新: 车牌号码: {car_number}, 识别时间: {recognition_time}") # 打印更新信息
try:
img = Image.open(file_path) # 打开图像文件
img.thumbnail((300, 300)) # 缩放图像大小
bio = io.BytesIO() # 创建字节流对象
img.save(bio, format='PNG') # 将图像保存为 PNG 格式到字节流中
window['-IMAGE-'].update(data=bio.getvalue()) # 更新图像显示区域
except FileNotFoundError:
sg.popup_error(f"文件打开失败: {file_path}") # 文件打开失败时显示错误信息
if event == '查看记录': # 如果用户点击“查看记录”按钮
car_number = sg.popup_get_text("请输入车牌号码") # 弹出输入框,要求用户输入车牌号码
if not car_number or not car_number.strip(): # 检查车牌号码是否为空
sg.popup_error("车牌号码不能为空") # 车牌号码为空时显示错误信息
continue # 跳过后续操作
try:
show_records(car_number) # 调用函数显示记录
except Exception as e: # 捕获异常
sg.popup_error(f"发生错误: {str(e)}", title="历史记录") # 显示异常信息
if event == '修改记录': # 如果用户点击“修改记录”按钮
car_number = sg.popup_get_text("请输入要修改的车牌号码") # 弹出输入框,要求用户输入要修改的车牌号码
if not car_number or not car_number.strip(): # 检查车牌号码是否为空
sg.popup_error("车牌号码不能为空") # 车牌号码为空时显示错误信息
continue # 跳过后续操作
new_car_number = sg.popup_get_text("请输入新的车牌号码") # 弹出输入框,要求用户输入新的车牌号码
if not new_car_number or not new_car_number.strip(): # 检查新的车牌号码是否为空
sg.popup_error("新的车牌号码不能为空") # 新的车牌号码为空时显示错误信息
continue # 跳过后续操作
recognition_time = sg.popup_get_text("请输入识别时间(格式:YYYY-MM-DD HH:MM:SS)") # 弹出输入框,要求用户输入识别时间
if not recognition_time or not recognition_time.strip(): # 检查识别时间是否为空
sg.popup_error("识别时间不能为空") # 识别时间为空时显示错误信息
continue # 跳过后续操作
try:
success = update_record(car_number.strip(), new_car_number.strip(), recognition_time.strip()) # 调用函数修改记录
if success: # 如果修改成功
sg.popup(f"修改成功,原车牌号码: {car_number}, 新车牌号码: {new_car_number}, 识别时间: {recognition_time}") # 显示成功信息
else: # 如果修改失败
sg.popup(f"修改失败,原车牌号码: {car_number}, 新车牌号码: {new_car_number}, 识别时间: {recognition_time}") # 显示失败信息
except Exception as e: # 捕获异常
sg.popup_error(f"发生错误: {str(e)}", title="修改记录") # 显示异常信息
if event == '删除记录': # 如果用户点击“删除记录”按钮
car_number = sg.popup_get_text("请输入要删除的车牌号码") # 弹出输入框,要求用户输入要删除的车牌号码
if not car_number or not car_number.strip(): # 检查车牌号码是否为空
sg.popup_error("车牌号码不能为空") # 车牌号码为空时显示错误信息
continue # 跳过后续操作
recognition_time = sg.popup_get_text("请输入识别时间(格式:YYYY-MM-DD HH:MM:SS)") # 弹出输入框,要求用户输入识别时间
if not recognition_time or not recognition_time.strip(): # 检查识别时间是否为空
sg.popup_error("识别时间不能为空") # 识别时间为空时显示错误信息
continue # 跳过后续操作
try:
success = delete_record(car_number.strip(), recognition_time.strip()) # 调用函数删除记录
if success: # 如果删除成功
sg.popup(f"删除成功,车牌号码: {car_number}, 识别时间: {recognition_time}") # 显示成功信息
else: # 如果删除失败
sg.popup(f"删除失败,车牌号码: {car_number}, 识别时间: {recognition_time}") # 显示失败信息
except Exception as e: # 捕获异常
sg.popup_error(f"发生错误: {str(e)}", title="删除记录") # 显示异常信息
window.close() # 关闭窗口
相关的代码注释经过自己的备注较为好理解,可以从中与自身遇到的问题进行查找
成果展示
进行图像处理和车牌识别:
查询记录:
可以通过识别中找到符合的要求
修改和删除方面也能运行成果也不进行相关运行。
总结
通过opencv知识的运用,完成了人工智能项目的运用,无论是智能人脸识别还是智能车牌识别项目,还是更多相关的项目,在成果掌握知识点以后都能够有完整的运用,做出一个小白的“设计项目”。下篇笔记开始更新学习的机器学习的内容,正式进入人工智能领域的基础。