当前位置: 首页 > article >正文

人工智能之图像预处理、数据库、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知识的运用,完成了人工智能项目的运用,无论是智能人脸识别还是智能车牌识别项目,还是更多相关的项目,在成果掌握知识点以后都能够有完整的运用,做出一个小白的“设计项目”。下篇笔记开始更新学习的机器学习的内容,正式进入人工智能领域的基础。


http://www.kler.cn/a/398846.html

相关文章:

  • STL序列式容器之stack
  • 如何使用 XML Schema
  • 丹摩征文活动|丹摩助力selenium实现大麦网抢票
  • ARM(安谋) China处理器
  • RedHat7—Linux中kickstart自动安装脚本制作
  • LlamaIndex+本地部署InternLM实践
  • 微知-DOCA ARGP参数模块的相关接口和用法(config单元、params单元,argp pipe line,回调)
  • Nginx负载均衡示例
  • install与cp库文件和头文件差异
  • 用 React18 构建Tic-Tac-Toe(井字棋)游戏
  • 数据处理与统计分析——04-Pandas中Series的常用方法、属性、布尔索引、运算操作
  • 阿里斑马智行 2025届秋招 NLP算法工程师
  • The Internals of PostgreSQL 翻译版 持续更新...
  • Java语言在医疗健康小程序开发中的应用研究
  • 机器学习周报(11.11-11.17)
  • 力扣-2175、世界排名的变化
  • mybatis 动态SQL语句
  • CSS预编译器:让样式编写更高效的秘密武器(6)
  • 何为Jenkins
  • React中组件通信的几种方式
  • 微软推出的AI无代码编程微应用平台GitHub Spark和国产AI原生无代码工具CodeFlying比到底咋样?
  • 华为云stack网络服务流量走向
  • 基于Hadoop、hive的数仓搭建实践
  • VUE+SPRINGBOOT实现邮箱注册、重置密码、登录功能
  • react17安装html-react-parser运行报错记录
  • Android Framework PMS面试题及参考答案