基于深度学习的手写汉字识别系统(含PyQt+代码+训练数据集)

基于深度学习的手写汉字识别系统(含PyQt+代码+训练数据集)

  • 前言
  • 一、数据集
    • 1.1 数据集介绍
    • 1.2 数据预处理
  • 二、模型搭建
  • 三、训练与测试
    • 3.1 模型训练
    • 3.2 模型测试
  • 四、PyQt界面实现
  • 参考资料

前言

本项目是基于深度学习网络模型的人脸表情识别系统,核心采用CNN卷积神经网络搭建,详述了数据集处理、模型构建、训练代码、以及基于PyQt5的应用界面设计。在应用中可以支持手写汉字图像的识别。本文附带了完整的应用界面设计、深度学习模型代码和训练数据集的下载链接。

完整资源下载链接:博主在面包多网站上的完整资源下载页

项目演示视频:

【项目分享】基于深度学习的手写汉字识别系统(含PyQt+代码+训练数据集)

一、数据集

1.1 数据集介绍

本项目的数据集在下载后的data文件夹下,主要分为训练数据集train和测试数据集test,如下图所示。
在这里插入图片描述

以训练集为例,如下图所示。其中训练集包含零、一、计、算、机等20个中文手写汉字,图像共计4757张。可以自己添加相应的手写汉字,可获取的 手写中文数据集链接。
在这里插入图片描述

1.2 数据预处理

首先,加载数据集中的图像文件,并将它们调整为相同的大小(64x64)。然后,根据文件所在的目录结构,为每个图像文件分配一个标签(label),标签是根据文件所在的子目录来确定的。最后,使用 train_test_split 函数将数据集划分为训练集和验证集,以便后续模型训练和评估。

def load_data(filepath):
    # 遍历filepath下所有文件,包括子目录
    files = os.listdir(filepath)
    for fi in files:
        fi_d = os.path.join(filepath, fi+'/')
        if os.path.isdir(fi_d):
            global label
            load_data(fi_d)
            label += 1
        else:
            labels.append(label)
            img = mi.imread(fi_d[:-1])
            img2 = cv2.resize(img, (64, 64))
            dataset.append(img2)

    # 在训练集中取一部分作为验证集
    train_image, val_image, train_label, val_label = train_test_split(
        np.array(dataset), np.array(labels), random_state=7)

    return train_image, val_image, train_label, val_label

二、模型搭建

CNN(卷积神经网络)主要包括卷积层、池化层和全连接层。输入数据经过多个卷积层和池化层提取图片信息后,最后经过若干个全连接层获得最终的输出。CNN的实现主要包括以下步骤:数据加载与预处理、模型搭建、定义损失函数和优化器、模型训练、模型测试。想了解更多关于CNN卷积神经网络的请自行百度。本项目基于tensorflow实现的,并搭建如下图所示的CNN网络模型。
请添加图片描述
具体代码:

def get_model():

    k.clear_session()

    # 创建一个新模型
    model = Sequential()

    model.add(Conv2D(32, 3, padding='same', activation='relu', input_shape=(64, 64, 3)))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(64, 3, padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(128, 3, padding='same', activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Flatten())
    model.add(Dropout(0.2))
    model.add(Dense(512, activation='relu'))

    model.add(Dropout(0.2))
    model.add(Dense(20, activation='softmax'))

    model.summary()

    # 选择优化器和损失函数
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

    return model

三、训练与测试

3.1 模型训练

使用Keras库和自定义的CNN模型进行手写汉字识别的训练。首先,设置了一些关键的训练参数,如训练周期、选择模型、迭代器等参数。

epochs = 8  # 选择批次

model = get_model.get_model()  # 选择模型

# 加载训练数据和测试数据
(train_image, val_image, train_label, val_label) = get_array_1.load_data('data/train/')
(test_image, test_label) = get_array_2.load_data('data/test/')

# 训练, fit方法自带shuffle随机读取
history = model.fit(
    train_image, train_label, epochs=epochs, validation_data=(val_image, val_label))

# 测试, 单用evaluate方法不会自动输出数值,需要手动输出他返回的两个数值
test_scores = model.evaluate(test_image, test_label)

epochs_range = range(1, epochs+1)
train_loss = history.history['loss']
val_loss = history.history['val_loss']
test_loss = test_scores[0]
train_accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']
test_accuracy = test_scores[1]

# 将模型保存为 HDF5 文件
model.save('Chinese_recognition_model.h5')
print("save model: Chinese_recognition_model.h5")

# 绘制图表
get_pyplot.show(epochs_range, train_loss, val_loss, train_accuracy, val_accuracy)

#  打印得分
print('')
print('train loss:', train_loss[-1], '   ', 'train accuracy:', train_accuracy[-1])
print('val loss:', val_loss[-1], '   ', 'val accuracy:', val_accuracy[-1])
print('test loss:', test_loss, '   ', 'test accuracy:', test_accuracy)
print('')

然后使用fit.py文件进行训练,整个训练过程的损失、准确率如下图所示。
在这里插入图片描述

3.2 模型测试

使用predict.py对手写汉字图像进行识别测试,具体代码实现如下:

import cv2
import numpy as np
import tensorflow as tf
import matplotlib.image as mpimg


class_names = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '肇', '庆', '学', '院',
               '计', '算', '机', '杨', '先', '生']
model = tf.keras.models.load_model('Chinese_recognition_model.h5')

img = mpimg.imread('data/test/r/29.png')
img2 = cv2.resize(img, (64, 64))
img3 = np.zeros((1, img2.shape[0], img2.shape[1], img2.shape[2]))
img3[0, :] = img2
pre = model.predict(img3)  # 预测
pre = np.argmax(pre, axis=1)
result = class_names[pre[0]]
print('预测结果:', result)

测试结果:
在这里插入图片描述

四、PyQt界面实现

当整个项目构建完成后,使用PyQt5编写可视化界面,可以支持输入手写汉字图像进行识别。

整个界面显示代码如下:

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(745, 590)
        MainWindow.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(200, 30, 411, 81))
        self.label.setStyleSheet("font: 28pt \"黑体\";")
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(80, 180, 271, 261))
        self.label_2.setStyleSheet("background-color: rgb(234, 234, 234);")
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(160, 470, 101, 51))
        self.pushButton.setStyleSheet("background-color: rgb(226, 226, 226);\n"
"font: 12pt \"黑体\";")
        self.pushButton.setObjectName("pushButton")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(410, 170, 191, 81))
        self.label_3.setStyleSheet("font: 22pt \"黑体\";\n"
"background-color: transparent;")
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(540, 290, 81, 71))
        self.label_4.setStyleSheet("font: 40pt \"黑体\";\n"
"background-color: rgb(234, 234, 234);\n"
"background-color: transparent;")
        self.label_4.setObjectName("label_4")
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(520, 470, 101, 51))
        self.pushButton_2.setStyleSheet("background-color: rgb(226, 226, 226);\n"
"font: 12pt \"黑体\";")
        self.pushButton_2.setObjectName("pushButton_2")
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(490, 260, 151, 141))
        self.label_5.setStyleSheet("background-color: rgb(234, 234, 234);")
        self.label_5.setText("")
        self.label_5.setObjectName("label_5")
        self.label_5.raise_()
        self.label.raise_()
        self.label_2.raise_()
        self.pushButton.raise_()
        self.label_3.raise_()
        self.label_4.raise_()
        self.pushButton_2.raise_()
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        self.pushButton.clicked.connect(self.open_img)  # 图片选择按钮  连接open_img函数
        self.pushButton_2.clicked.connect(self.detect)
    def open_img(self):
        self.fname, _ = QFileDialog.getOpenFileName(None, 'open file', '', "*.jpg;*.png;;All Files(*)")
        print(self.fname)
        img = cv2.imdecode(np.fromfile(self.fname, dtype=np.uint8), -1)
        # img = cv2.imread(self.fname)
        show = cv2.resize(img, (271, 261))
        cv2.imwrite('./linshi.png', show)
        self.label_2.setStyleSheet("image: url(./linshi.png)")
    def detect(self):
        class_names = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '肇', '庆', '学', '院',
                       '计', '算', '机', '杨', '先', '生']
        model = tf.keras.models.load_model('Chinese_recognition_model.h5')
        img = mpimg.imread(self.fname)
        img2 = cv2.resize(img, (64, 64))
        img3 = np.zeros((1, img2.shape[0], img2.shape[1], img2.shape[2]))
        img3[0, :] = img2
        pre = model.predict(img3)  # 预测
        pre = np.argmax(pre,axis=1)
        result = class_names[pre[0]]
        print('预测结果:', result)
        self.label_4.setText(result)
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "手写汉字识别系统"))
        self.pushButton.setText(_translate("MainWindow", "选择图像"))
        self.label_3.setText(_translate("MainWindow", "识别结果:"))
        self.label_4.setText(_translate("MainWindow", ""))
        self.pushButton_2.setText(_translate("MainWindow", "开始检测"))

界面显示效果:
在这里插入图片描述

参考资料

  1. 手写中文数据集
  2. CNN实现手写数字识别(Pytorch)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/555616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++编程(6)——类与对象(4)运算符重载、赋值重载函数

欢迎来到博主的专栏——C编程 博主ID:代码小豪 文章目录 运算符重载赋值重载函数默认赋值重载函数其他运算符重载函数 运算符重载 重载这个概念在c中已经出现两次了,在前面的文章中,函数重载指的是可以用相同名字的函数实现不同的功能。而运…

【WebSocket连接异常】前端使用WebSocket子协议传递token时,Java后端的正确打开方式!!!

文章目录 1. 背景2. 代码实现和异常发现3. 解决异常3.1 从 URL入手3.2 从 WebSocket子协议的使用方式入手(真正原因) 4. 总结(仍然存在的问题) 前言: 本篇文章记录的是使用WebSocket进行双向通信时踩过的坑&#xff0c…

将gdip-yolo集成到yolov9模型项目中(支持预训练的yolov9模型)

1、yolov9模型概述 1.1 yolov9 YOLOv9意味着实时目标检测的重大进步,引入了可编程梯度信息(PGI)和通用高效层聚合网络(GELAN)等开创性技术。该模型在效率、准确性和适应性方面取得了显著改进,在MS COCO数…

「 安全工具介绍 」软件成分分析工具Black Duck,业界排名TOP 1的SCA工具

在现代的 DevOps 或 DevSecOps 环境中,SCA 激发了“左移”范式的采用。提早进行持续的 SCA 测试,使开发人员和安全团队能够在不影响安全性和质量的情况下提高生产力。前期在博文《「 网络安全常用术语解读 」软件成分分析SCA详解:从发展背景到…

Qt-饼图示范

1.效果图 2.代码如下 2.1 .h文件 #ifndef PIECHARTWIDGET_H #define PIECHARTWIDGET_H#include <QWidget> #include <QChartView> #include <QPieSeries>#include<QVBoxLayout> #include<QMessageBox> #include <QtCharts>struct PieDat…

FastAPI - uvicorn设置 logger 日志格式

怎么将日志打印到文件 在main.py加入log_config“./uvicorn_config.json” import uvicornif __name__ "__main__":uvicorn.run("app:app", host"0.0.0.0", port8000, log_config"./uvicorn_config.json")uvicorn_config.json {&qu…

“互联网+”创意创业大赛活动方案

大赛历时6个月&#xff0c;总体分两个赛程&#xff1a;一是策划创意阶段。评审的是方案。二是组织实施阶段。通过阶段一立项的项目由公司协助实施&#xff0c;最终评审的是项目落实情况。学生可两个赛程单独参加&#xff0c;也可连续参加。 具体流程及时间安排如下&#xff1a;…

ansible-tower连接git实现简单执行playbook

前提&#xff1a;安装好ansible-tower和git&#xff0c;其中git存放ansible得剧本 其中git中得内容为&#xff1a; --- - name: yjxtesthosts: yinremote_user: rootgather_facts: noroles:- testroles/test/tasks/main.yml #文件内容 --- #- name: Perform Test Task # tas…

单链表-通讯录

目录 单链表实现 通讯录代码实现 初始化 初始化函数 添加 删除 展示 查找 修改 销毁 代码展示 main.c text.c text.h list.c list.h 和前面的通讯录实现差不多这次就是实现一个以单链表为底层的通讯录 单链表实现 数据结构&#xff1a;单链表-CSDN博客 通讯…

OpenHarmony多媒体-video_trimmer

简介 videotrimmer是在OpenHarmony环境下&#xff0c;提供视频剪辑能力的三方库。 效果展示&#xff1a; 安装教程 ohpm install ohos/videotrimmerOpenHarmony ohpm环境配置等更多内容&#xff0c;请参考 如何安装OpenHarmony ohpm包 。 使用说明 目前支持MP4格式。 视频…

docker部署的nginx配置ssl证书https

申请ssl证书&#xff0c;已腾讯的免费证书为例 2.上传证书到linux服务器 2.1 映射ssql目录 首先确保容器命令已映射宿主机目录&#xff0c;不一定是ssl&#xff0c;也可以是其他路径。 2.2 上传文件到指定路径 以我映射的ssl路径为例&#xff0c;我上传到宿主机的 /usr/local…

【GEE实践应用】使用MODIS NDVI数据集绘制研究区域每日NDVI序列曲线

// 设置研究区域 var geometry table;// 选择MODIS NDVI 数据集 var modisNDVI ee.ImageCollection(MODIS/006/MOD13A2).filterBounds(geometry).filterDate(2000-01-01, 2023-12-31);// 计算每天的平均 NDVI var dailyMeanNDVI modisNDVI.map(function(image) {var date e…

(最详细)关于List和Set的区别与应用

关于List与Set的区别 List和Set都继承自Collection接口&#xff1b; List接口的实现类有三个&#xff1a;LinkedList、ArrayList、Vector。Set接口的实现类有两个&#xff1a;HashSet(底层由HashMap实现)、LinkedHashSet。 在List中&#xff0c;List.add()是基于数组的形式来添…

OpenHarmony网络组件-Mars

项目简介 Mars 是一个跨平台的网络组件&#xff0c;包括主要用于网络请求中的长连接&#xff0c;短连接&#xff0c;是基于 socket 层的解决方案&#xff0c;在网络调优方面有更好的可控性&#xff0c;暂不支持HTTP协议。 Mars 极大的方便了开发者的开发效率。 效果演示 编译…

简述Kafka的高可靠性

什么叫可靠性&#xff1f; 大家都知道&#xff0c;系统架构有三高&#xff1a;「高性能、高并发和高可用」&#xff0c;三者的重要性不言而喻。 对于任意系统&#xff0c;想要同时满足三高都是一件非常困难的事情&#xff0c;大型业务系统或者传统中间件都会搭建复杂的架构来…

万字长文带你APK反编译重签名aabapks转换

Android反编译 反编译&#xff08;Decompilation&#xff09;是将已编译的程序&#xff08;比如二进制代码&#xff09;转换回更高级别的编程语言代码的过程。这通常用于理解程序的工作原理&#xff0c;进行软件审计&#xff0c;恢复丢失的源代码&#xff0c;或者进行教学研究…

提升数据质量的三大要素:清洗prompt、数据溯源、数据增强(含Reviewer2和PeerRead)​

前言 我带队的整个大模型项目团队超过40人了&#xff0c;分六个项目组 每个项目组都是全职带兼职&#xff0c;且都会每周确定任务/目标/计划然后各项目组各自做任务拆解&#xff0c;有时同组内任务多时 则2-4人一组 方便并行和讨论&#xff0c;每周文档记录当周工作内容&…

Leetcode 4.18

Leetcode 1.无重复字符的最长子串2.最长回文子串3.整数反转4.字符串转换整数 (atoi)5.正则表达式匹配 1.无重复字符的最长子串 无重复字符的最长子串 滑动窗口&#xff0c;先让右指针右移&#xff0c;如果发现这个子串有元素和右指针当前元素重复。 则&#xff1a; 左指针右移…

HackmyVM-----Boxing靶机

文章目录 正常打靶流程1.获取靶机IP地址2.获取靶机端口服务3.访问网页4.添加域名WindowsLinux 5.访问域名6.nc反弹shell 7.结束 正常打靶流程 1.获取靶机IP地址 ┌──(root㉿kali)-[/home/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:10:3c:9b, …

Stable Diffusion XL优化终极指南

如何在自己的显卡上获得SDXL的最佳质量和性能&#xff0c;以及如何选择适当的优化方法和工具&#xff0c;这一让GenAI用户倍感困惑的问题&#xff0c;业内一直没有一份清晰而详尽的评测报告可供参考。直到全栈开发者Flix San出手。 在本文中&#xff0c;Flix介绍了相关SDXL优化…
最新文章