随着技术的飞速发展,计算机的能力也在不断增强,它们现在能够识别各种手写内容。本文将介绍如何构建一个能够识别手写数字的应用程序。将探讨两种识别技术:一种是识别字母,另一种是识别数字。本文将重点介绍如何构建一个手写数字识别应用。
为了构建手写数字识别应用,需要导入以下库。在导入之前,请确保这些库已经重新安装在计算机上。如果有任何库未安装,请使用pip install命令进行安装。例如:
pip install tensorflow
将使用Python作为编程语言来构建这个应用。TensorFlow是一个开源库,用它来训练和发展机器学习模型。Keras是一个高级的TensorFlow API,也是一个开源软件库,它提供了用于人工神经网络的Python接口。Tkinter是一个出色的包,它提供了创建图形用户界面(GUI)的方法。PIL(Python Imaging Library)允许Python解释器编辑图像。NumPy是一个基本的标准库,用于处理数组。win32gui也是需要安装的,以便与图形用户界面一起工作。
为了构建这个应用,使用MNIST数据集。这个数据集包含了从0到9的数字图像,所有这些图像都是灰度的。数据集中既有训练图像也有测试图像,包含大约60000张训练图像和大约10000张测试图像。所有这些图像都是28x28像素大小的小正方形。这些是单个数字的手写图像。
在编写任何代码之前,需要导入所有必需的库。已经提到了构建应用的所有要求,所以请导入这些库。从PIL库中导入ImageGrab和Image。
import numpy as np
from tensorflow.keras.models import load_model
from tkinter import *
import tkinter as tk
import win32gui
from PIL import ImageGrab, Image
使用TensorFlow构建模型,首先需要从TensorFlow Keras导入一些库。需要导入keras,然后导入将用于构建应用的数据集,即MNIST数据集。然后导入顺序模型和一些层,如Dense、Dropout、Flatten、Conv2D、MaxPooling2D,并最后导入后端。
from tensorflow import keras
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from tensorflow.keras import backend as K
接下来,将数据集分为训练集和测试集,重新调整训练集和测试集的形状,并将类别向量转换为二进制类别矩阵。
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
接下来,需要定义批次大小、类别数量和训练周期,然后向之前导入的顺序模型添加一些层。然后使用分类交叉熵损失函数、Adadelta优化器和准确度指标编译模型。最后使用x_train、y_train、批次大小、周期和所有训练模型,然后保存它。
batch_size = 128
num_classes = 10
epochs = 30
model = Sequential()
model.add(Conv2D(32, kernel_size=(5, 5), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
hist = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))
model.save('mnist.h5')
现在需要编写一些代码来预测所写的数字。为此,定义一个名为predict_class的函数,需要提供一张图片作为参数。首先,将其调整为所需的像素大小。将图像转换为灰度(之前是RGB)。然后重新调整形状并归一化。最后,使用predict方法预测图像。
model = load_model('mnist.h5')
def predict_digit(img):
img = img.resize((28, 28))
img = img.convert('L')
img = np.array(img)
img = img.reshape(1, 28, 28, 1)
img = img / 255.0
img = 1 - img
res = model.predict([img])[0]
return np.argmax(res), max(res)
让看看如何构建一个用户友好的GUI应用。为此使用Tkinter。在这里,为用户创建一些空间来实际绘制数字,然后提供两个按钮:识别和清除。识别按钮用于识别在给定空间上写的数字,清除按钮用于清除上面的书写。最后,运行主循环以运行应用。
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = self.y = 0
self.canvas = tk.Canvas(self, width=400, height=400, bg="white", cursor="cross")
self.label = tk.Label(self, text="Thinking..", font=("Helvetica", 48))
self.btn_classify = tk.Button(self, text="Recognise", command=self.classify_handwriting)
self.clear_button = tk.Button(self, text="Clear", command=self.clear_all)
self.canvas.grid(row=0, column=0, pady=2, sticky=W)
self.label.grid(row=0, column=1, pady=2, padx=2)
self.btn_classify.grid(row=1, column=1, pady=2, padx=2)
self.clear_button.grid(row=1, column=0, pady=2)
self.canvas.bind("", self.draw_lines)
def clear_all(self):
self.canvas.delete("all")
def classify_handwriting(self):
HWND = self.canvas.winfo_id()
rect = win32gui.GetWindowRect(HWND)
im = ImageGrab.grab(rect)
digit, acc = predict_digit(im)
self.label.configure(text= str(digit)+', '+ str(int(acc*100))+'%')
def draw_lines(self, event):
self.x = event.x
self.y = event.y
r=8
self.canvas.create_oval(self.x-r, self.y-r, self.x + r, self.y + r, fill='black')
app = App()
.mainloop()
当运行应用时,会弹出一个窗口,可以在其中写数字。然后,当点击识别按钮时,它将识别所写的数字,并显示匹配原始数字的准确度百分比。这里写了数字1,它识别为1,准确度为17%。