深度学习实战 | 卷积神经网络LeNet手写数字识别(带手写板GUI界面)

news2024/11/15 17:21:03

引言

在深度学习领域,卷积神经网络(Convolutional Neural Network, CNN)是一种广泛应用于图像识别任务的神经网络结构。LeNet是一种经典的CNN结构,被广泛应用于基础的图像分类任务。本文将介绍如何使用LeNet卷积神经网络实现手写数字识别,并使用Pytorch实现LeNet手写数字识别,使用PyQt5实现手写板GUI界面,使用户能够通过手写板输入数字并进行识别。

请添加图片描述

完整代码下载:Python手写数字识别带手写板GUI界面 Pytorch代码 含训练模型 (付费资源,如果你觉得这篇博客对你有帮助,欢迎购买支持~)

1. LeNet卷积神经网络

LeNet是由Yann LeCun等人于1998年提出的卷积神经网络结构,主要用于手写字符识别。在本文中,我们将使用LeNet结构构建一个用于手写数字识别的神经网络模型。以下是LeNet的基本结构:

请添加图片描述

Layer 1: Convolutional Layer
    - Input: 28x28x1 (灰度图像)
    - Filter: 5x5, Stride: 1, Depth: 6
    - Activation: Sigmoid
    - Output: 28x28x6

Layer 2: Average Pooling Layer
    - Input: 28x28x6
    - Pooling: 2x2, Stride: 2
    - Output: 14x14x6

Layer 3: Convolutional Layer
    - Input: 14x14x6
    - Filter: 5x5, Stride: 1, Depth: 16
    - Activation: Sigmoid
    - Output: 10x10x16

Layer 4: Average Pooling Layer
    - Input: 10x10x16
    - Pooling: 2x2, Stride: 2
    - Output: 5x5x16

Layer 5: Fully Connected Layer
    - Input: 5x5x16
    - Output: 120
    - Activation: Sigmoid

Layer 6: Fully Connected Layer
    - Input: 120
    - Output: 84
    - Activation: Sigmoid

Layer 7: Output Layer
    - Input: 84
    - Output: 10 (对应0-9的数字)
    - Activation: Softmax

2. 手写数字识别实现

使用深度学习框架(例如Pytorch)构建LeNet模型:

import torch
import torch.nn as nn
import torch.nn.functional as F

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 6, kernel_size=5)
        self.pool1 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(6, 16, kernel_size=5)
        self.pool2 = nn.AvgPool2d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = F.sigmoid(self.conv1(x))
        x = self.pool1(x)
        x = F.sigmoid(self.conv2(x))
        x = self.pool2(x)
        x = x.view(-1, 16 * 5 * 5)
        x = F.sigmoid(self.fc1(x))
        x = F.sigmoid(self.fc2(x))
        x = self.fc3(x)
        return F.log_softmax(x, dim=1)

并使用手写数字数据集MNIST进行训练。确保正确实现数据预处理和模型训练过程:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
from net import Net

if __name__ == "__main__":
    # 设置训练参数
    batch_size = 64
    epochs = 140
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    # 数据集
    transform = transforms.Compose([transforms.ToTensor(),
                                    transforms.Normalize((0.5,), (0.5,))])
    trainset = datasets.MNIST('~/.pytorch/MNIST_data/', download=True, train=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True)

    # 输出提示信息
    print("batch_size:", batch_size)
    print("data_batches:", len(trainloader))
    print("epochs:", epochs)

    # 神经网络
    net = Net().to(device)
    net.load_state_dict(torch.load('model.pth'))

    # 损失函数和优化器
    criterion = nn.NLLLoss()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

    # 训练网络
    for epoch in range(epochs):
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            inputs, labels = data
            inputs, labels = Variable(inputs).to(device), Variable(labels).to(device)

            # 反向传播优化参数
            optimizer.zero_grad()
            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()

            if i % 938 == 937:    # 每轮输出损失值
                print('[epoch: %d, batches: %d] loss: %.5f' %
                      (epoch + 1, i + 1, running_loss / 2000))
                running_loss = 0.0
        torch.save(net.state_dict(), './model.pth')  # 每轮保存模型参数

    print('Finished Training')

3. 手写板GUI界面开发

模型训练完成后,为了让用户通过手写板输入数字,我们将开发一个简单直观的GUI界面。使用GUI库(例如PyQt5),创建一个窗口,包含一个手写板区域,用户可以在上面写数字。添加一个识别按钮,点击后将手写板上的数字送入LeNet模型进行识别,并在界面上显示识别结果。

以下是PyQt5代码示例:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

import torch
from utils import *
from net import Net

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = '手写数字识别'
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setMinimumSize(500, 400)
        self.main_widget = QWidget()
        self.main_layout = QGridLayout()
        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)
        self.canvas = Canvas()
        self.canvas.setFixedSize(300,300)
        self.label = QLabel()
        self.label.setFixedSize(100,100)
        self.label.setText('识别结果')
        self.label.setStyleSheet("font-size:15px;color:red") 
        self.clear_button = QPushButton('清除')
        self.clear_button.setFixedSize(100,50)
        self.clear_button.clicked.connect(self.canvas.clear)
        self.recognize_button = QPushButton('识别')
        self.recognize_button.setFixedSize(100,50)
        self.recognize_button.clicked.connect(self.recognize)
        self.main_layout.addWidget(self.canvas,0,0,3,1)
        self.main_layout.addWidget(self.label,0,1)
        self.main_layout.addWidget(self.clear_button,1,1)
        self.main_layout.addWidget(self.recognize_button,2,1)
    
    def recognize(self):
        self.canvas.recognize()
        self.label.setText('识别结果: ' + str(self.canvas.recognize()))

class Canvas(QLabel):
    x0=-10; y0=-10; x1=-10; y1=-10
    def __init__(self):
        super(Canvas,self).__init__()
        self.pixmap = QPixmap(300, 300)
        self.pixmap.fill(Qt.white)
        self.Color=Qt.blue
        self.penwidth=10

    def paintEvent(self,event):
        painter=QPainter(self.pixmap)
        painter.setPen(QPen(self.Color,self.penwidth,Qt.SolidLine))
        painter.drawLine(self.x0,self.y0,self.x1,self.y1)

        Label_painter=QPainter(self)
        Label_painter.drawPixmap(2,2,self.pixmap)

    def mousePressEvent(self, event):
        self.x1=event.x()
        self.y1=event.y()

    def mouseMoveEvent(self, event):
        self.x0 = self.x1
        self.y0 = self.y1
        self.x1 = event.x()
        self.y1 = event.y()
        self.update()

    def clear(self):
        self.x0=-10; self.y0=-10; self.x1=-10; self.y1=-10
        self.pixmap.fill(Qt.white)
        self.update()
    
    def recognize(self):
        arr = pixmap2np(self.pixmap)
        arr = 255 - arr[:,:,2]
        arr = clip_image(arr)
        arr = resize_image(arr)
        arr = np.expand_dims(arr, axis=0)
        arr_batch = np.expand_dims(arr, axis=0)
        tensor = torch.FloatTensor(arr_batch)
        tensor = (tensor/255 - 0.5) * 2
        possibles = net(tensor).detach().numpy()
        result = np.argmax(possibles)
        return result

if __name__ == '__main__':
    net = Net()
    net.load_state_dict(torch.load('model.pth'))
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

这个例子中,用户可以在手写板上写数字,点击识别按钮后,程序将手写板上的数字送入LeNet模型进行识别,并在界面上显示识别结果。

通过本文的实践,你可以学到如何使用LeNet卷积神经网络实现手写数字识别,以及如何结合GUI开发一个手写板界面,更直观地进行数字识别交互。希望这篇博客对有所帮助。

完整代码下载:Python手写数字识别带手写板GUI界面 Pytorch代码 含训练模型 (付费资源,如果你觉得这篇博客对你有帮助,欢迎购买支持~)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yum命令下载出现Failed to synchronize cache for repo ‘AppStream‘, ignoring this repo.

修改下面的配置文件 问题: cd /etc/yum.repos.d 修改下面四个文件 vim CentOS-Base.repo vim CentOS-AppStream.repo vim CentOS-Extras.repo vim CentOS-PowerTools.repo测试yum是否正常 yum -y install wget

极速搭建幻兽帕鲁私服,叫上好友春节假期一起联机畅玩帕鲁

文章目录 前言幻兽帕鲁私服详细部署教程查看服务器开始游戏自定义游戏参数配置 前言 行业资讯 《幻兽帕鲁》的火爆对开发商 Pocketpair 来说,代价是巨大的。该游戏的成功让首席执行官沟部拓郎最近在推特上表示,他可能因服务器运营费用而面临破产。据他透…

[文本挖掘和知识发现] 03.基于大连理工情感词典的情感分析和情绪计算

作者于2023年8月新开专栏——《文本挖掘和知识发现》,主要结合Python、大数据分析和人工智能分享文本挖掘、知识图谱、知识发现、图书情报等内容。这些内容也是作者《文本挖掘和知识发现(Python版)》书籍的部分介绍,本书预计2024年…

vscode 括号 python函数括号补全

解决方法 在setting.json中添加 “python.analysis.completeFunctionParens”: true 打开设置; 点击图中按钮打开setting.json文件 添加 “python.analysis.completeFunctionParens”: true

管理类联考-复试-全流程演练-导航页

文章目录 整体第一步:学校导师两手抓——知己知彼是关键学校校训历史 导师 第二步:面试问题提前背——押题助沟通自我介绍——出现概率:100%为什么选择这个专业?今后如何打算?你认为自己本科专业和现在所考的专业有什么…

嵌入式linux移植篇之Uboot

什么是bootloader? 芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。当然了&#…

分享5款让人眼前一亮的软件

​ 让你眼前一亮的软件,不一定是市面上最流行的。今天,我将推荐给你五款非常小众,但是十分好用的软件。 1.自动化脚本——AutoIt ​ AutoIt是一款自动化脚本软件,可以让你编写和运行一些简单的程序,实现一些重复性或…

【C++】拷贝构造函数和赋值运算符重载详解

目录 拷贝构造函数 概念 特征 赋值运算符重载 运算符重载 赋值运算符重载 ​编辑前置和后置重载 ⭐拷贝构造函数 ⭐概念 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新…

Apache Doris 整合 FLINK CDC + Iceberg 构建实时湖仓一体的联邦查询

1概况 本文展示如何使用 Flink CDC Iceberg Doris 构建实时湖仓一体的联邦查询分析,Doris 1.1版本提供了Iceberg的支持,本文主要展示Doris和Iceberg怎么使用,大家按照步骤可以一步步完成。完整体验整个搭建操作的过程。 2系统架构 我们整…

【AI绘画+Midjourney平替】Fooocus:图像生成、修改软件(Controlnet原作者重新设计的UI+Windows一键部署)

代码:https://github.com/lllyasviel/Fooocus windows一键启动包下载:https://github.com/lllyasviel/Fooocus/releases/download/release/Fooocus_win64_2-1-831.7z B站视频教程:AI绘画入门神器:Fooocus | 简化SD流程&#xff0c…

2024年Java面试题大全 面试题附答案详解,BTA内部面试题

基础篇 1、 Java语言有哪些特点 1、简单易学、有丰富的类库 2、面向对象(Java最重要的特性,让程序耦合度更低,内聚性更高) 阿里内部资料 基本类型 大小(字节) 默认值 封装类 6、Java自动装箱与拆箱 装箱就是…

Django视图

一、返回错误响应 返回错误的3种方式: 中间件设置的属性: Django的contrib应用程序中包含的一些中间件在请求中设置了属性。如果在请求中看不到该属性,请确保使用了相应的中间件类MIDDLEWARE 返回 HttpResponseNotFound返回 HttpResponse 设置 status 状态码返回 Http404状…

Python基础系列-文件

🌈个人主页: 会编程的果子君 ​💫个人格言:“成为自己未来的主人~” 目录 文件是什么 文件路径 文件操作 打开文件 关闭文件 写文件 读文件 关于中文的处理 使用上下文管理器 文件是什么 变量是把数据保存到内存中,如果把程序重启/…

【MySQL】——数据定义

🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL&#xff1a…

物流平台架构设计与实践

随着电商行业的迅猛发展,物流行业也得到了极大的发展。从最初的传统物流到现在的智慧物流,物流技术和模式也在不断的更新与升级。物流平台作为连接电商和物流的重要媒介,其架构设计和实践显得尤为重要。 一、物流平台架构设计 1. 前端架构设…

PyQt5零基础入门(十)——数字显示控件

前言 在PyQt中,可以使用QLCDNumber控件来显示数字。QLCDNumber控件是一个用于显示数字的小部件,模拟了真实的液晶数字显示屏。这个控件主要用于显示数字,如计时器、状态指示等。QSpinBox和QDoubleSpinBox是PyQt中用于输入和显示数字的控件。…

ele-h5项目使用vue3+vite+vant4开发:第四节、业务组件-SearchView组件开发

需求分析 展示切换动画搜索框输入文字&#xff0c;自动发送请求搜索结果展示搜索状态维护历史搜索展示&#xff0c;点击历史搜索后发送请求历史搜索更多切换动画效果 <script setup lang"ts"> import OpSearch from /components/OpSearch.vue import { ref } f…

React Hooks 学习笔记

1.useState&#xff08;&#xff09; 实现对页面数据的存储&#xff0c;当数据改变时候&#xff0c;自动触发render函数 2.useRef 用来解决两个问题&#xff1a; 1).是获取DOM元素或子组件的实例对象 2).存储渲染周期之间共享的数据 3.useEffect 4.useLayoutEffect 5…

IDEA 配置以及一些技巧

1. IDEA设置 1.1 设置主题 1.2 设置字体和字体大小 1.3 编辑区的字体用ctrl鼠标滚轮可以控制大小 1.4 自动导包和优化多余的包 1.5 设置编码方式 1.6 配置 maven 1.7 设置方法形参参数提示 1.8 设置控制台的字体和大小 注意&#xff1a;设置控制台字体和大小后需要重启IDEA才会…

90.网游逆向分析与插件开发-游戏窗口化助手-项目需求与需求拆解

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;实现物品使用策略的功能-CSDN博客 项目需求&#xff1a; 在游戏窗口化时&#xff0c;可以在游戏之外弹出一个窗口&#xff0c;可以隐藏或者显示游戏窗口&#xff0c;显示游戏人物的基本状态&#xff…