使用Lenet-5识别手写数字（含简单GUI测试，简单详细版）

1、LeNet-5的搭建与训练

from tensorflow.keras.datasets import mnist
from tensorflow.keras import models
from tensorflow.keras import layers
import tensorflow as tf
import cv2
import numpy as np
import pandas as pd

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images=train_images.reshape(60000,28,28,1)
test_images=test_images.reshape(10000,28,28,1)
&#x5F52;&#x4E00;&#x5316;
train_images=train_images/255
test_images=test_images/255
train_labels=np.array(pd.get_dummies(train_labels))
test_labels=np.array(pd.get_dummies(test_labels))

model =models.Sequential()
model.summary()

model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['acc'])
history=model.fit(train_images,train_labels,epochs=10,validation_data=(test_images,test_labels))
model.evaluate(test_images,test_labels)
model.save('model_mnist.h5')
print(model.evaluate(test_images,test_labels))
network=models.Sequential()
print(network.summary())


Layer (type) Output Shape Param #

conv2d (Conv2D) (None, 28, 28, 6) 156

average_pooling2d (AveragePo (None, 14, 14, 6) 0

conv2d_1 (Conv2D) (None, 10, 10, 16) 2416

average_pooling2d_1 (Average (None, 5, 5, 16) 0

conv2d_2 (Conv2D) (None, 1, 1, 120) 48120

flatten (Flatten) (None, 120) 0

dense (Dense) (None, 84) 10164

dense_1 (Dense) (None, 10) 850

2、测试test

import tensorflow as tf
from tensorflow.keras import models
from tensorflow.keras import layers
import cv2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
&#x8C03;&#x7528;&#x6A21;&#x578B;
&#x8BFB;&#x53D6;&#x56FE;&#x7247;
plt.imshow(img)
print(img.shape)
img=cv2.resize(img,(28,28))
img=img.reshape(1,28,28,1)
img=img/255 #&#x5F52;&#x4E00;&#x5316;
print(img.shape)

predict=newmodel.predict(img)
predict
print(predict)
np.argmax(predict)
print("&#x9884;&#x6D4B;&#x56FE;&#x50CF;&#x4E2D;&#x7684;&#x6570;&#x5B57;&#x4E3A;&#xFF1A;" + str(np.argmax(predict)))


3、GUI页面设计

import platform
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
from PyQt5.Qt import QPixmap, QPainter, QPoint, QPaintEvent, QMouseEvent, QPen, QColor, QSize
from PyQt5.QtCore import Qt
from PyQt5.Qt import QWidget, QColor, QPixmap, QIcon, QSize, QCheckBox
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QPushButton, QSplitter, QComboBox, QLabel, QSpinBox, QFileDialog
import tensorflow as tf
from tensorflow.keras import models
from tensorflow.keras import layers
import cv2
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def main():
app = QApplication(sys.argv)

mainWidget = MainWidget() #&#x65B0;&#x5EFA;&#x4E00;&#x4E2A;&#x4E3B;&#x754C;&#x9762;
mainWidget.show()    #&#x663E;&#x793A;&#x4E3B;&#x754C;&#x9762;

exit(app.exec_()) #&#x8FDB;&#x5165;&#x6D88;&#x606F;&#x5FAA;&#x73AF;

class PaintBoard(QWidget):

def __init__(self, Parent=None):
'''
Constructor
'''
super().__init__(Parent)

self.__InitData()  # &#x5148;&#x521D;&#x59CB;&#x5316;&#x6570;&#x636E;&#xFF0C;&#x518D;&#x521D;&#x59CB;&#x5316;&#x754C;&#x9762;
self.__InitView()
self.setWindowTitle("&#x753B;&#x7B14;")

def __InitData(self):

self.__size = QSize(280, 280)

# &#x65B0;&#x5EFA;QPixmap&#x4F5C;&#x4E3A;&#x753B;&#x677F;&#xFF0C;&#x5C3A;&#x5BF8;&#x4E3A;__size
self.__board = QPixmap(self.__size)
self.__board.fill(Qt.black)  # &#x7528;&#x9ED1;&#x8272;&#x586B;&#x5145;&#x753B;&#x677F;

self.__IsEmpty = True  # &#x9ED8;&#x8BA4;&#x4E3A;&#x7A7A;&#x753B;&#x677F;

self.__lastPos = QPoint(0, 0)  # &#x4E0A;&#x4E00;&#x6B21;&#x9F20;&#x6807;&#x4F4D;&#x7F6E;
self.__currentPos = QPoint(0, 0)  # &#x5F53;&#x524D;&#x7684;&#x9F20;&#x6807;&#x4F4D;&#x7F6E;

self.__painter = QPainter()  # &#x65B0;&#x5EFA;&#x7ED8;&#x56FE;&#x5DE5;&#x5177;

self.__thickness = 10  # &#x9ED8;&#x8BA4;&#x753B;&#x7B14;&#x7C97;&#x7EC6;&#x4E3A;10px
self.__penColor = QColor("white")  # &#x8BBE;&#x7F6E;&#x9ED8;&#x8BA4;&#x753B;&#x7B14;&#x989C;&#x8272;&#x4E3A;&#x767D;&#x8272;

def __InitView(self):
# &#x8BBE;&#x7F6E;&#x754C;&#x9762;&#x7684;&#x5C3A;&#x5BF8;&#x4E3A;__size
self.setFixedSize(self.__size)

def Clear(self):
# &#x6E05;&#x7A7A;&#x753B;&#x677F;
self.__board.fill(Qt.black)
self.update()
self.__IsEmpty = True

def IsEmpty(self):
# &#x8FD4;&#x56DE;&#x753B;&#x677F;&#x662F;&#x5426;&#x4E3A;&#x7A7A;
return self.__IsEmpty

def GetContentAsQImage(self):
# &#x83B7;&#x53D6;&#x753B;&#x677F;&#x5185;&#x5BB9;&#xFF08;&#x8FD4;&#x56DE;QImage&#xFF09;
image = self.__board.toImage()
return image

def paintEvent(self, paintEvent):
# &#x7ED8;&#x56FE;&#x4E8B;&#x4EF6;
# &#x7ED8;&#x56FE;&#x65F6;&#x5FC5;&#x987B;&#x4F7F;&#x7528;QPainter&#x7684;&#x5B9E;&#x4F8B;&#xFF0C;&#x6B64;&#x5904;&#x4E3A;__painter
# &#x7ED8;&#x56FE;&#x5728;begin()&#x51FD;&#x6570;&#x4E0E;end()&#x51FD;&#x6570;&#x95F4;&#x8FDB;&#x884C;
# begin(param)&#x7684;&#x53C2;&#x6570;&#x8981;&#x6307;&#x5B9A;&#x7ED8;&#x56FE;&#x8BBE;&#x5907;&#xFF0C;&#x5373;&#x628A;&#x56FE;&#x753B;&#x5728;&#x54EA;&#x91CC;
# drawPixmap&#x7528;&#x4E8E;&#x7ED8;&#x5236;QPixmap&#x7C7B;&#x578B;&#x7684;&#x5BF9;&#x8C61;
self.__painter.begin(self)
# 0,0&#x4E3A;&#x7ED8;&#x56FE;&#x7684;&#x5DE6;&#x4E0A;&#x89D2;&#x8D77;&#x70B9;&#x7684;&#x5750;&#x6807;&#xFF0C;__board&#x5373;&#x8981;&#x7ED8;&#x5236;&#x7684;&#x56FE;
self.__painter.drawPixmap(0, 0, self.__board)
self.__painter.end()

def mousePressEvent(self, mouseEvent):
# &#x9F20;&#x6807;&#x6309;&#x4E0B;&#x65F6;&#xFF0C;&#x83B7;&#x53D6;&#x9F20;&#x6807;&#x7684;&#x5F53;&#x524D;&#x4F4D;&#x7F6E;&#x4FDD;&#x5B58;&#x4E3A;&#x4E0A;&#x4E00;&#x6B21;&#x4F4D;&#x7F6E;
self.__currentPos = mouseEvent.pos()
self.__lastPos = self.__currentPos

def mouseMoveEvent(self, mouseEvent):
# &#x9F20;&#x6807;&#x79FB;&#x52A8;&#x65F6;&#xFF0C;&#x66F4;&#x65B0;&#x5F53;&#x524D;&#x4F4D;&#x7F6E;&#xFF0C;&#x5E76;&#x5728;&#x4E0A;&#x4E00;&#x4E2A;&#x4F4D;&#x7F6E;&#x548C;&#x5F53;&#x524D;&#x4F4D;&#x7F6E;&#x95F4;&#x753B;&#x7EBF;
self.__currentPos = mouseEvent.pos()
self.__painter.begin(self.__board)
self.__painter.setPen(QPen(self.__penColor, self.__thickness))  # &#x8BBE;&#x7F6E;&#x753B;&#x7B14;&#x989C;&#x8272;&#xFF0C;&#x7C97;&#x7EC6;
# &#x753B;&#x7EBF;
self.__painter.drawLine(self.__lastPos, self.__currentPos)
self.__painter.end()
self.__lastPos = self.__currentPos

self.update()  # &#x66F4;&#x65B0;&#x663E;&#x793A;

def mouseReleaseEvent(self, mouseEvent):
self.__IsEmpty = False  # &#x753B;&#x677F;&#x4E0D;&#x518D;&#x4E3A;&#x7A7A;

class MainWidget(QWidget):

def __init__(self, Parent=None):
'''
Constructor
'''
super().__init__(Parent)

self.__InitData()  # &#x5148;&#x521D;&#x59CB;&#x5316;&#x6570;&#x636E;&#xFF0C;&#x518D;&#x521D;&#x59CB;&#x5316;&#x754C;&#x9762;
self.__InitView()

def __InitData(self):
'''
&#x521D;&#x59CB;&#x5316;&#x6210;&#x5458;&#x53D8;&#x91CF;
'''
self.__paintBoard = PaintBoard(self)

def __InitView(self):
'''
&#x521D;&#x59CB;&#x5316;&#x754C;&#x9762;
'''
self.setFixedSize(550, 300)
self.setWindowTitle("Predictive handwritten digits")

# &#x65B0;&#x5EFA;&#x4E00;&#x4E2A;&#x6C34;&#x5E73;&#x5E03;&#x5C40;&#x4F5C;&#x4E3A;&#x672C;&#x7A97;&#x4F53;&#x7684;&#x4E3B;&#x5E03;&#x5C40;
main_layout = QHBoxLayout(self)
# &#x8BBE;&#x7F6E;&#x4E3B;&#x5E03;&#x5C40;&#x5185;&#x8FB9;&#x8DDD;&#x4EE5;&#x53CA;&#x63A7;&#x4EF6;&#x95F4;&#x8DDD;&#x4E3A;10px
main_layout.setSpacing(10)

# &#x5728;&#x4E3B;&#x754C;&#x9762;&#x5DE6;&#x4FA7;&#x653E;&#x7F6E;&#x753B;&#x677F;

# &#x65B0;&#x5EFA;&#x5782;&#x76F4;&#x5B50;&#x5E03;&#x5C40;&#x7528;&#x4E8E;&#x653E;&#x7F6E;&#x6309;&#x952E;
sub_layout = QVBoxLayout()

# &#x8BBE;&#x7F6E;&#x6B64;&#x5B50;&#x5E03;&#x5C40;&#x548C;&#x5185;&#x90E8;&#x63A7;&#x4EF6;&#x7684;&#x95F4;&#x8DDD;&#x4E3A;10px
sub_layout.setContentsMargins(10, 10, 10, 10)

self.__btn_Clear = QPushButton("&#x6E05;&#x7A7A;&#x753B;&#x677F;")
self.__btn_Clear.setParent(self)  # &#x8BBE;&#x7F6E;&#x7236;&#x5BF9;&#x8C61;&#x4E3A;&#x672C;&#x754C;&#x9762;

# &#x5C06;&#x6309;&#x952E;&#x6309;&#x4E0B;&#x4FE1;&#x53F7;&#x4E0E;&#x753B;&#x677F;&#x6E05;&#x7A7A;&#x51FD;&#x6570;&#x76F8;&#x5173;&#x8054;
self.__btn_Clear.clicked.connect(self.__paintBoard.Clear)

self.__btn_Save = QPushButton("&#x4FDD;&#x5B58;&#x4F5C;&#x54C1;")
self.__btn_Save.setParent(self)
self.__btn_Save.clicked.connect(self.on_btn_Save_Clicked)

self.__btn_Predict = QPushButton("&#x9884;&#x6D4B;")
self.__btn_Predict.setParent(self)  # &#x8BBE;&#x7F6E;&#x7236;&#x5BF9;&#x8C61;&#x4E3A;&#x672C;&#x754C;&#x9762;
self.__btn_Predict.clicked.connect(self.Predict)

self.__btn_Quit = QPushButton("&#x9000;&#x51FA;")
self.__btn_Quit.setParent(self)  # &#x8BBE;&#x7F6E;&#x7236;&#x5BF9;&#x8C61;&#x4E3A;&#x672C;&#x754C;&#x9762;
self.__btn_Quit.clicked.connect(self.Quit)

self.__text_browser = QTextBrowser(self)
self.__text_browser.setParent(self)

splitter = QSplitter(self)  # &#x5360;&#x4F4D;&#x7B26;

def __fillColorList(self, comboBox):

index_black = 0
index = 0
for color in self.__colorList:
if color == "black":
index_black = index
index += 1
pix = QPixmap(70, 20)
pix.fill(QColor(color))
comboBox.setIconSize(QSize(70, 20))

comboBox.setCurrentIndex(index_black)

def on_PenColorChange(self):
color_index = self.__comboBox_penColor.currentIndex()
color_str = self.__colorList[color_index]
self.__paintBoard.ChangePenColor(color_str)

def on_PenThicknessChange(self):
penThickness = self.__spinBox_penThickness.value()
self.__paintBoard.ChangePenThickness(penThickness)

def on_btn_Save_Clicked(self):
image = self.__paintBoard.GetContentAsQImage()
image.save('1.png')

def Predict(self):
# &#x8C03;&#x7528;&#x6A21;&#x578B;
# &#x8BFB;&#x53D6;&#x56FE;&#x7247;
# img = cv2.imread('1.png', 0)
img = cv2.imread('1.png', 0)
plt.imshow(img)
# print(img.shape)
img = cv2.resize(img, (28, 28))

rows = img.shape[0]
cols = img.shape[1]
for i in range(rows):
for j in range(cols):
if (img[i, j] > 150):
img[i, j] = 255;
else:
img[i, j] = 0;

img = img.reshape(1, 28, 28, 1)
img = img / 255  # &#x5F52;&#x4E00;&#x5316;
# print(img.shape)

predict = newmodel.predict(img)
predict
# print(predict)
np.argmax(predict)
# print("&#x9884;&#x6D4B;&#x56FE;&#x50CF;&#x4E2D;&#x7684;&#x6570;&#x5B57;&#x4E3A;&#xFF1A;" + str(np.argmax(predict)))
self.__text_browser.append("&#x9884;&#x6D4B;&#x56FE;&#x50CF;&#x4E2D;&#x7684;&#x6570;&#x5B57;&#x4E3A;&#xFF1A;" + str(np.argmax(predict)))
self.cursot = self.__text_browser.textCursor()
self.__text_browser.moveCursor(self.cursot.End)

def Quit(self):
self.close()

if __name__ == '__main__':
main()



Original: https://blog.csdn.net/weixin_52520877/article/details/122815038
Author: 湫歌
Title: 使用Lenet-5识别手写数字（含简单GUI测试，简单详细版）

(0)

大家都在看

• MYSQL 主从复制 — binlog

一个MYSQL数据库存在的问题 在谈主从复制之前，应该都会有一个疑问，那么就是一个MYSQL数据库存在的问题呢？ 读和写所有压力都由一台数据库承担，压力大 数据库服务器磁盘损坏则数…

人工智能 2023年7月31日
0163
• 以太网交换机自学习、转发帧的流程

以太网交换机自学习、转发帧的流程 以太网交换机工作在数据链路层（也包括物理层） 以太网收到帧后，在帧交换表中查找帧的目的地址MAC地址所对应的接口号，然后通过该接口转发帧。 以太网…

人工智能 2023年6月29日
0213
• 时间序列预测——LSTM模型（附代码实现）

目录 模型原理 模型实现 导入所需要的库 设置随机数种子 导入数据集 打印前五行数据进行查看 数据处理 归一化处理 查看归一化处理后的数据 将时间序列转换为监督学习问题 打印数据前…

人工智能 2023年6月16日
0262
• Transformers实际应用案例

首先安装transformers pip install transformers import warnings warnings.filterwarnings(‘ignore’…

人工智能 2023年5月28日
0208
• OpenKE实现转移距离模型trans系列代码

OpenKE实现转移距离模型trans系列代码 前言 前段时间学习了知识图谱表示的转移距离模型trans系列大礼包，编辑这篇博客的起因是一个学妹找我要trans系列的代码，所以就在…

人工智能 2023年6月1日
0149
• 第七届工程训练大赛垃圾分类

第七届全国大学生工程训练大赛垃圾分类 前言 一、机械结构设计 * 1.Solidworks建模 2.建模的不足以及改进 – 1.挡板的添加 2.履带防滑 3.整体实物 …

人工智能 2023年6月30日
0160
• LeetCode — 1436. Destination City 解题报告

You are given the array paths, where paths[i] = [cityAi, cityBi] means there exists a dire…

人工智能 2023年6月28日
0151
• K-Means(K均值聚类)原理及代码实现

机器学习 没有免费午餐定理和三大机器学习任务如何对模型进行评估K-Means(K均值聚类)原理及代码实现KNN(K最近邻算法)原理及代码实现KMeans和KNN的联合演习 文章目录…

人工智能 2023年5月31日
0246
• 知识表示学习（三）：TransR

一.摘要 知识图谱补全旨在执行实体之间的链接预测。 在本文中，我们考虑了知识图嵌入的方法。 最近，诸如 TransE 和 TransH 等模型通过将关系视为从头实体到尾实体的翻译来…

人工智能 2023年7月28日
0227
• 数据挖掘——协同过滤推荐算法

协同过滤推荐算法 一、背景介绍 * 1.1推荐系统 1.2效用矩阵 1.3传统推荐模型 二、算法原理 * 2.1协同过滤算法 2.2相似度计算 – 2.2.1 jacc…

人工智能 2023年7月18日
0148
• 数据库范式应用

学习数据库范式理论后，尽管已经知道范式能够帮助优化数据库设计，但是在使用中却发现，很难将这些理论方便的应用到实际中。本节主要梳理下如何在实际应用中使用范式。范式有很多种，参考关系数…

人工智能 2023年6月10日
0148
• openCV实操笔记

搜索： grep "&#x641C;&#x7D22;&#x540D;" * -Rn | grep "\.h" 含义：…

人工智能 2023年6月20日
0153
• 读书笔记 | 自动驾驶中的雷达信号处理（第5章 雷达目标检测 ）

本文编辑：调皮哥的小助理 5.1 介绍 目标检测的目的通常是将真实的目标回波信号从 噪声和杂波中区分出来，本章讨论了雷达探测的主要概念和方法，其中包含 CFAR算法等内容。 5.2…

人工智能 2023年7月11日
0128
• 格密码的基础概念

格密码的基础概念 前言 一.格的定义 二. 格的延展空间 三. 格的基本区 四.格基的判定定理 五. 格基的关系 六. 格基的变换 七. 格的行列式 八. Gram-Schmidt…

人工智能 2023年6月15日
0182
• 语音识别(ASR)论文优选：端到端ASR综述Recent Advances in End-to-End Automatic Speech Recognition

声明：平时看些文章做些笔记分享出来，文章中难免存在错误的地方，还望大家海涵。搜集一些资料，方便查阅学习：http://yqli.tech/page/speech.html。语音合成…

人工智能 2023年5月25日
0129
• 深度学习实战9-文本生成图像-本地电脑实现text2img

大家好，我是微学AI，今天给大家带来一个文本生成图像的案例。让大家都成为艺术家，自己电脑也能生成图片 ，该模型它能让数十亿人在几秒钟内创建出精美的艺术品。在速度和质量方面，都有所突…

人工智能 2023年7月29日
0139