精华内容
下载资源
问答
  • 2019-04-13 14:53:08

    python_手写数字识别案例、手写数字图片处理

    • 1、手写数字识别案例

    步骤:

    1. 收集数据
      带有标签的训练数据集来源于trainingDigits文件夹里面所有的文件,接近2000个文件,每个文件中有32*32的二维数组,由01构成,文件名称就是该文件数据对应的标签类型(即一个数字)。
    2. 处理数据使其符合算法要求
      最终我们要求是一个二维数组作为数据源,所以需要将每一个文件对应的特征数据处理成一行,即1*1024,这样所有样本集就变成了2000行的1024列的大二维数组
    3. 根据以上得到的标签集合和大二维数据数据集,再确定一个k紧邻的k值,就可以作为输入条件进行训练了。
    4. 给定一个测试文件,将其跟第2步一样处理成为1*1024数组,作为未知样本,然后根据knn分类算法,进行分类操作,算法同电影分类案例。
      函数头:def getcls(cur,cls,dataSet,k): def getcls(cur,cls,dataSet,k)
      Cur:未知样本,cls:训练数据集标签集合,dataSet:训练数据集 k:最近的几个邻居

    ‘’’
    #coding=utf-8
    #手写数字识别案例
    import numpy as np
    import os
    ‘’‘fnames为所有的文件名,fname为每一个文件名,vec为一个1*1024的二维数组,f表示整个文件内容,line为某一行’’’
    ‘’‘函数用来根据样本集合和未知点判断最终未知点所属类别,knn’’’
    def knncls(dataSet,cur,labels,k):
    #1、判断当前点到每个样本点距离
    a=np.tile(cur,(dataSet.shape[0],1)) #重复cur使其dataSet数组的shape相同
    #a与dataSet距离
    diff=dataSet-a;
    diff=diff2
    diff=np.sum(diff,axis=1)
    diff=diff
    0.5 #欧式距离
    #对diff进行排序
    indexes=np.argsort(diff) #返回值是距离在原来样本集合下标
    #寻找前k个邻居的标签都是什么,确定了标签及出现次数{‘爱情’:11,‘动作’:80}
    dic={}
    for i in range(k):
    key=labels[indexes[i]]
    dic[key]=dic.get(key,0)+1
    #对字典按照value进行排序,次数多的在前面
    lst=sorted(dic.items(),key=lambda kv:kv[1],reverse=True)
    return lst[0][0]

    ‘’‘创建一个训练集合20001024,未知数据就是11024’’’
    def createDataSet():
    #从traningset文件夹读取所有的文件,然后每个文件处理成一个1*1024的数组
    fnames=os.listdir(‘D:/trainingDigits’)
    dataSet=np.zeros((len(fnames),1024))#训练集合二维数组
    labels=[]#分类标签
    i=0
    for fname in fnames:
    #读取这个文件,然后将文件内容转为一维数组
    vec=img2vec(‘D:/trainingDigits/’+fname)
    dataSet[i,:]=vec[0]
    labels.append(fname[0])
    i+=1
    return dataSet,labels #python可以返回两个值

    ‘’‘将图片变成一维数组’’’
    def img2vec(fname):
    #定义一个11024的数组
    vec=np.zeros((1,1024))
    f=open(fname,‘r’)
    row=0
    for line in f:
    for j in range(32):
    vec[0][row
    32+j]=line[j] #例如vec[0][1]=line[1]
    row+=1
    return vec

    if name==‘main’:
    num=0
    i=0
    k=input(“请输入k值:”) #提示用户输入k值
    k=int(k)
    #创建训练集
    dataSet,labels=createDataSet()
    #定义一个未知数据
    tnames=os.listdir(‘D:/testDigits’) #读取testDigits文件
    curs=np.zeros((len(tnames),1024))#测试集合二维数组
    for tname in tnames:
    #读取这个文件,然后将文件内容转为一维数组
    cur=img2vec(‘D:/testDigits/’+tname)
    curs[i,:]=cur[0] #curs中是所有的文件内容
    res=knncls(dataSet,cur,labels,k)
    #判断正确的个数用num记录,正确时加一
    if tname[0]==res:
    num+=1
    accuracy=round(100*num/curs.shape[0],3) #计算手写数字识别的正确率,用百分率表示
    print(“正确率为:{}%”.format(accuracy))
    ‘’’

    • 2、手写数字图片处理

      处理问题:给定一张图片,对图片进行灰阶处理,然后进行二进制化,最终变成我们knn算法需要的样子。函数:将图片变成01
      

      将处理图片为二进制的函数定义在单独的一个py文件中,形成一个模块,方便别的模块进行导入。
      主要的流程就是将图片打开之后,进行降噪处理,然后将其灰度化,最后设置一个阙值将其二值化保存到一个32*32的数组中

    import numpy as np
    from PIL import Image
    import img2vec as pic
    import os
    ‘’‘函数用来根据样本集合和未知点判断最终未知点所属类别,knn’’’
    def knncls(dataSet,cur,labels,k):
    #1、判断当前点到每个样本点距离
    a=np.tile(cur,(dataSet.shape[0],1))
    #a与dataSet距离
    diff=dataSet-a;
    diff=diff2
    diff=np.sum(diff,axis=1)
    diff=diff
    0.5 #欧式距离
    #对diff进行排序
    indexes=np.argsort(diff) #返回值是距离在原来样本集合下标
    #寻找前k个邻居的标签都是什么,确定了标签及出现次数{‘爱情’:11,‘动作’:80}
    dic={}
    for i in range(k):
    key=labels[indexes[i]]
    dic[key]=dic.get(key,0)+1
    #对字典按照value进行排序,次数多的在前面
    lst=sorted(dic.items(),key=lambda kv:kv[1],reverse=True)
    return lst[0][0]

    ‘’‘创建一个训练集合20001024,未知数据就是11024’’’
    def createDataSet():
    #从traningset文件夹读取所有的文件,然后每个文件处理成一个1*1024的数组
    fnames=os.listdir(‘D:/trainingDigits’) #注意是/而不是
    dataSet=np.zeros((len(fnames),1024))#训练集合二维数组
    labels=[]#分类标签
    i=0
    for fname in fnames:
    #读取这个文件,然后将文件内容转为一维数组
    vec=img2vec(‘D:/trainingDigits/’+fname)
    dataSet[i,:]=vec
    labels.append(fname[0])
    i+=1
    return dataSet,labels

    ‘’‘将图片变成一维数组’’’
    def img2vec(fname):
    #定义一个11024的数组
    vec=np.zeros((1,1024))
    f=open(fname,‘r’)
    row=0
    for line in f:
    for j in range(32):
    vec[0][row
    32+j]=line[j]
    row+=1
    return vec

    if name==‘main’:
    #创建训练集
    dataSet,labels=createDataSet()
    #定义一个未知数据
    testfile=‘test.png’
    #将图片处理成txt文件,里面是0、1
    pic.picTo01(testfile)
    cur=img2vec(“test.txt”)
    res=knncls(dataSet,cur,labels,3)
    print(res)

    附代码链接:
    http://localhost:8888/notebooks/cyl_day4(手写数字识别).ipynb

    更多相关内容
  • 手写数字图片,一共5000张,像素28*28,数字0-9,每个各500张; 可用于神经网络的图像分类的样本等,
  • 自己制作手写数字训练图片,全部都已经灰度化,二值化,归一化,处理好了,适合做迁移学习,也可直接训练模型
  • 用vs运行,可以实现输入为一张灰度数字图片28*28像素,识别结果。参数都固定好了。
  • 利用著名的MNIST数据集,训练构造好的人工神经网络,实现对手写28*28的数字灰度图像的识别
  • 美国邮政服务USPS手写数字识别库,库中为16×16像素的灰度图像,共有9298个手写数字图像。对于要做迁移学习(Transfer Learning)、连续学习(Life Long learning)等的研究来说,是除mnist之外又一实用的数据集。
  • MATLAB手写数字识别

    2022-01-24 23:35:23
    该课题为基于Matlab的手写数字识别系统。在一张图像上面手写了很多手写数字。利用鼠标进行框定你所要识别的数字区域。裁剪灰度化处理,二值化处理。提取数字特征。利用神经网络的方法进行识别。带有人际交互界面,...
  • 实施一对多的Logistic回归和神经网络来识别手写数字 多类分类和神经网络 在这个项目中,我实现了对所有逻辑回归和神经网络来识别手写数字。 要开始使用该项目,您将需要下载代码并将其内容解压缩到希望运行该项目的...
  • minist手写数字数据集(原始图片);42000张图片,0-9 MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST). 训练集 (training set) 由来自 250 个不同人手写数字...
  • 该课题为基于Matlab的手写数字识别系统。在一张图像上面手写了很多手写数字。利用鼠标进行框定你所要识别的数字区域。裁剪灰度化处理,二值化处理。提取数字特征。利用神经网络的方法进行识别。带有人际交互界面,...
  • 用vs运行,可以实现输入为一张灰度数字图片28*28像素,识别结果。参数都固定好了。
  • 每个样本都是一张28*28像素的灰度手写数字图片。 #(3)one_hot表示独热编码,其值被设为true。在分类问题的数据集标注时,如何不采用独热编码的方式, 类别通常就是一个符号而已,比如说是9。但如果采用独热编码的...
  • MNIST数据集是一个手写阿拉伯数字图像识别数据集,图片分辨率为 20x20 灰度图图片,包含‘0 - 9’ 十组手写手写阿拉伯数字的图片。其中,训练样本 60000 ,测试样本 10000,数据为图片的像素点值,作者已经对数据集...
  • 这些训练样本包括了9-0共十个数字手写图像。这些样本中每个像素都用浮点数表示。加载得到的数据中,每幅图像都被展开为一个400维的向量,构成了数据矩阵中的一行。完整的训练数据是一个5000x400的矩阵,其每一行为...
  • TensorFlow下利用MNIST训练模型并识别自己手写数字 test2.m:利用matlab将图片转为28*28像素 test3.m:完成灰度化与二值化处理 运行完前两个文件,图片的预处理就算成功了 也可以使用opencv.py:利用opencv对图片就...
  • 深度学习基于Matlab神经网络的手写数字识别系统源代码。在一张图像上面手写了很多手写数字。利用鼠标进行框定你所要识别的数字区域。裁剪灰度化处理,二值化处理。提取数字特征。利用神经网络的方法进行识别。带有...
  • 手写数据集,包括测试集和训练集,是将图片文件经过灰度化,二值化后在处理转换成txt文件后的数据集,适合用于实现新手入门的手写数字识别的数据集,
  • 手写数字测试图片.zip

    2019-09-03 09:58:12
    手写数字0-9图片,用于深度学习入门实践项目mnist,训练完模型之后,可用训练的模型预测本图片,尺寸为28*28,灰度图片,有0-910个数字
  • 该课题为基于Matlab的手写数字识别系统。在一张图像上面手写了很多手写数字。利用鼠标进行框定你所要识别的数字区域。裁剪灰度化处理,二值化处理。提取数字特征。利用神经网络的方法进行识别。带有人际交互界面,...
  • 基于KNN的手写数字识别 3.代码 import numpy as np from PIL import Image import random from sklearn.neighbors import KNeighborsClassifier def img2vec(fname): '''将jpg等格式的图片转为向量''' im = Image....

    1.KNN原理

    机器学习的原理

    是通过大量的数据,训练出一个能处理此类数据的模型。使得这个模型可以根据已知的数据,准确率很高的判断出未知的数据,从而使得人类能够采取正确的方法去处理某些事情。

    传统机器学习算法主要包括以下五类:

    回归:建立一个回归方程来预测目标值,用于连续型分布预测
    分类:给定大量带标签的数据,计算出未知标签样本的标签取值
    聚类:将不带标签的数据根据距离聚集成不同的簇,每一簇数据有共同的特征
    关联分析:计算出数据之间的频繁项集合
    降维:原高维空间中的数据点映射到低维度的空间中
    在这里插入图片描述

    1. 线性回归:找到一条直线预测目标值
    2. 逻辑回归:找到一条直线来分类数据
    3. KNN:用距离度量最相近邻的分类标签
    4. NB:选着后验概率最大的类为分类标签
    5. 决策树:构造一科熵值下降最快的分类树
      决策树是一种树型结构,其中每个内部结点表示在一个属性上的测试,每个分支代表一个测试输出,每个叶结点代表一种类别。采用的是自顶向下的递归方法,选择信息增益最大的特征作为当前的分裂特征。
    6. SVM:构造超平面,分类非线性数据
    7. k-means:计算质心,聚类无标签数据
    8. 关联分析: 在大规模数据集中寻找有趣的关系
    9. PCA降维:减少数据维度,降低数据复杂度

    K-近邻算法(KNN)是通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

    如下图,绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?
    在这里插入图片描述
    如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。

    在KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,避免了对象之间的匹配问题,在这里距离一般使用欧氏距离或曼哈顿距离:
    在这里插入图片描述
    同时,KNN通过依据k个对象中占优的类别进行决策,而不是单一的对象类别决策。这两点就是KNN算法的优势。

    就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类。

    1)计算测试数据与各个训练数据之间的距离;
    2)按照距离的递增关系进行排序;
    3)选取距离最小的K个点;
    4)确定前K个点所在类别的出现频率;
    5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

    2.基于KNN的手写数字识别
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    3.代码

    import numpy as np
    from PIL import Image
    import random
    from sklearn.neighbors import KNeighborsClassifier 
    
    def img2vec(fname):
        '''将jpg等格式的图片转为向量'''
        im = Image.open(fname).convert('L')     #转为灰度图像
        tmp = np.array(im)                                #将灰度图像转化为数组
        vec = tmp.ravel()                               #将多维数组转换为一维数组
        return vec
    
    def generate_data():     
        '''36张图片作为训练集'''
        X = []
        y = []
        name=[1,2,3,4,5,6]
        for i in range(1,len(name)):
            for j in range(1,7):
                y.append(name[i])
                X.append(img2vec('data'+'/'+str(name[i])+'-'+str(j)+'.jpg'))
        return X,y
    
    
    x_test=[]
    x_test.append(img2vec('data/myTest1.jpg'))           #将手写测试图像放入x_test列表
    
    '''构建分类器'''
    knn_classifier = KNeighborsClassifier(6)
    X_train,y_label = generate_data()
    knn_classifier.fit(X_train,y_label)                #训练模型
    y_predict=knn_classifier.predict(x_test)     # 预测分类
    
    print(y_predict)
    
    

    结果:

    在这里插入图片描述

    预测出,myTest1.jpg为数字3

    数据和代码:百度网盘
    提取码:tian
    –来自百度网盘超级会员V7的分享

    如果这篇文章帮助到你了,那就点个赞,给个关注吧!

    展开全文
  • 在上一篇文章Python徒手实现手写数字识别—大纲中,我们已经讲过了我们想要写的全部思路,所以我们不再说全部的思路。 我这一次将图片的读入与处理的代码写了一下,和大纲写的过程一样,这一段代码分为以下几个部分...
  • 该课题为基于Matlab的手写数字识别系统。在一张图像上面手写了很多手写数字。利用鼠标进行框定你所要识别的数字区域。裁剪灰度化处理,二值化处理。提取数字特征。利用神经网络的方法进行识别。带有人际交互界面,...
  • 手写数字识别(识别纸上手写数字) 使用pytorch框架,实现对MNIST手写数字数据集的训练和识别。重点是,自己手写数字,手机拍照后传入电脑,使用你自己训练的权重和偏置能够识别。数据预处理过程的代码是重点。 ...

    说明

    使用pytorch框架,实现对MNIST手写数字数据集的训练和识别。重点是,自己手写数字,手机拍照后传入电脑,使用你自己训练的权重和偏置能够识别。数据预处理过程的代码是重点。

    分析

    要识别自己用手在纸上写的数字,从特征上来看,手写数字相比于普通的电脑上的数字最大的 不同就是数字的边缘会发生不同幅度的抖动。而且,在MNIST数据集中的数字是边缘为黑色的,然后数字是不同灰度的白色的,如下所示:
    在这里插入图片描述
    在数据集中,每个数据都是 28 ∗ 28 28*28 2828的灰度图,并且黑色部分都是零,其余白色的灰度值并不统一。因为如果训练时背景都是统一的时候我们测试用的图片背景也必须是统一的,否则基本无法识别出来。除非训练的时候换各种不同的背景大数据进行训练,这样特征就不会依托着背景而存在,剩下的就是要识别的物体自己所拥有的特征了。所以在这里我要做的就是在图片预处理的时候尽量让图片处理成接近测试图片的样子。

    训练网络

    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torchvision import datasets, transforms
    from torch.autograd import Variable
    from torch.utils.data import DataLoader
    
    # 下载训练集
    train_dataset = datasets.MNIST(root='./data/',
    				train=True,
    				transform=transforms.ToTensor(),
    				download=False)
    # 下载测试集
    test_dataset = datasets.MNIST(root='./data/',
    				train=False,
    				transform=transforms.ToTensor(),
    				download=False)
    
    # 设置批次数
    batch_size = 100
    
    # 装载训练集
    train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
    						batch_size = batch_size,
    						shuffle=True)
    # 装载测试集
    test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
    						batch_size = batch_size,
    						shuffle = True)
    
    # 自定义手写数字识别网络
    class net(nn.Module):
    	def __init__(self):
    		super(net, self).__init__()
    
    		self.Conn_layers = nn.Sequential(
    				nn.Linear(784, 100),
    				nn.Sigmoid(),
    				nn.Linear(100, 10),
    				nn.Sigmoid()
    			)
    
    	def forward(self, input):
    		output = self.Conn_layers(input)
    
    		return output
    
    # 定义学习率
    LR = 0.1
    
    # 定义一个网络对象
    net = net()
    
    # 损失函数使用交叉熵
    loss_function = nn.CrossEntropyLoss()
    
    # 优化函数使用 SGD
    optimizer = optim.SGD(
    	net.parameters(),
    	lr = LR,
    	momentum = 0.9,
    	weight_decay = 0.0005
    )
    
    # 定义迭代次数
    epoch = 20
    
    # 进行迭代训练
    for epoch in range(epoch):
    	for i, data in enumerate(train_loader):
    		inputs, labels = data
    		
    		# 转换下输入形状
    		inputs = inputs.reshape(batch_size, 784)
    
    		inputs, labels = Variable(inputs), Variable(labels)
    		outputs = net(inputs)
    		loss = loss_function(outputs, labels)
    		optimizer.zero_grad()
    		loss.backward()
    		optimizer.step()
    	
    	# 初始化正确结果数为0
    	test_result = 0
    	
    	# 用测试数据进行测试
    	for data_test in test_loader:
    		images, labels = data_test
    		
    		# 转换下输入形状
    		images = images.reshape(batch_size, 784)
    
    		images, labels = Variable(images), Variable(labels)
    		output_test = net(images)
    		
    		# 对一个批次的数据的准确性进行判断
    		for i in range(len(labels)):
    		
    			# 如果输出结果的最大值的索引与标签内正确数据相等,准确个数累加
    			if torch.argmax(output_test[i]) == labels[i]:
    				test_result += 1
    				
    	# 打印每次迭代后正确的结果数
    	print("Epoch {} : {} / {}".format(epoch, test_result, len(test_dataset)))
    	
    # 保存权重模型
    torch.save(net, 'weight/test.pkl')
    

    至此,对手写数字网络的训练已经结束,且训练的准确性为:
    在这里插入图片描述
    这个网络比较粗糙,所以准确性也只是一般,但如果要精确起来后面有很多文章可做。

    图像预处理

    因为我们手机拍的照片和训练集的图片有很大的区别,所以无法将手机上拍的照片直接丢到训练好的网络模型中进行识别,需要先对图片进行预处理。有几点需要对原图进行改变:

    1. 图片的大小:肯定得将拍摄到的图片转换成 28 ∗ 28 28*28 2828尺寸大小的图片。
    2. 图片的通道数:由于MNIST是灰度图,所以原图的channel也得转换成1。
    3. 图片的背景:图片的背景得转换成MNIST相同的黑色,这样识别结果准确性更高。
    4. 数字的颜色:毋庸置疑,数字的颜色得变成MNIST相同的白色。
    5. 数字颜色中间深边缘前:观察MNIST的白色部分并不都是255全白,而是有渐变色的,这个渐变色模拟起来比较困难,算是难度最大的一点了。
      接下来直接上代码了:
    import cv2
    import numpy as np
    
    def image_preprocessing():
    
    	# 读取图片
    	img = cv2.imread("picture/test8.jpeg")
    
    	# =====================图像处理======================== #
    
    	# 转换成灰度图像
    	gray_img = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY)
    
    	# 进行高斯滤波
    	gauss_img = cv2.GaussianBlur(gray_img, (5,5), 0, 0, cv2.BORDER_DEFAULT)
    
    	# 边缘检测
    	img_edge1 = cv2.Canny(gauss_img, 100, 200)
    
    	# ==================================================== #
    	# =====================图像分割======================== #
    
    	# 获取原始图像的宽和高
    	high = img.shape[0]
    	width = img.shape[1]
    
    	# 分别初始化高和宽的和
    	add_width = np.zeros(high, dtype = int)
    	add_high = np.zeros(width, dtype = int)
    
    	# 计算每一行的灰度图的值的和
    	for h in range(high):
    		for w in range(width):
    			add_width[h] = add_width[h] + img_edge1[h][w]
    
    	# 计算每一列的值的和
    	for w in range(width):
    		for h in range(high):
    			add_high[w] = add_high[w] + img_edge1[h][w]
    
    	# 初始化上下边界为宽度总值最大的值的索引
    	acount_high_up = np.argmax(add_width)
    	acount_high_down = np.argmax(add_width)
    
    	# 将上边界坐标值上移,直到没有遇到白色点停止,此为数字的上边界
    	while add_width[acount_high_up] != 0:
    		acount_high_up = acount_high_up + 1
    
    	# 将下边界坐标值下移,直到没有遇到白色点停止,此为数字的下边界
    	while add_width[acount_high_down] != 0:
    		acount_high_down = acount_high_down - 1
    
    	# 初始化左右边界为宽度总值最大的值的索引
    	acount_width_left = np.argmax(add_high)
    	acount_width_right = np.argmax(add_high)
    
    	# 将左边界坐标值左移,直到没有遇到白色点停止,此为数字的左边界
    	while add_high[acount_width_left] != 0:
    		acount_width_left = acount_width_left - 1
    
    	# 将右边界坐标值右移,直到没有遇到白色点停止,此为数字的右边界
    	while add_high[acount_width_right] != 0:
    		acount_width_right = acount_width_right + 1
    
    	# 求出宽和高的间距
    	width_spacing = acount_width_right - acount_width_left
    	high_spacing = acount_high_up - acount_high_down
    
    	# 求出宽和高的间距差
    	poor = width_spacing - high_spacing
    
    	# 将数字进行正方形分割,目的是方便之后进行图像压缩
    	if poor > 0:
    		tailor_image = img[acount_high_down - poor // 2 - 5:acount_high_up + poor - poor // 2 + 5, acount_width_left - 5:acount_width_right + 5]
      else:
    		tailor_image = img[acount_high_down - 5:acount_high_up + 5, acount_width_left + poor // 2 - 5:acount_width_right - poor + poor // 2 + 5]
    
    	# ==================================================== #
    	# ======================小图处理======================= #
    
    	# 将裁剪后的图片进行灰度化
    	gray_img = cv2.cvtColor(tailor_image , cv2.COLOR_BGR2GRAY)
    
    	# 高斯去噪
    	gauss_img = cv2.GaussianBlur(gray_img, (5,5), 0, 0, cv2.BORDER_DEFAULT)
    
    	# 将图像形状调整到28*28大小
    	zoom_image = cv2.resize(gauss_img, (28, 28))
    
    	# 获取图像的高和宽
    	high = zoom_image.shape[0]
    	wide = zoom_image.shape[1]
    
    	# 将图像每个点的灰度值进行阈值比较
    	for h in range(high):
    		for w in range(wide):
    
    			# 若灰度值大于100,则判断为背景并赋值0,否则将深灰度值变白处理
    			if zoom_image[h][w] > 100:
    				zoom_image[h][w] = 0
    			else:
    				zoom_image[h][w] = 255 - zoom_image[h][w]
    
    	# ==================================================== #
    
    	return zoom_image
    

    在此,我在纸上写了个6,如下图所示:
    在这里插入图片描述
    然后是对图像进行分割,首先要介绍下我分割图像的方法。下面是一张进行canny边缘检测后的6:
    在这里插入图片描述
    在这里这个6有个特点,就是被白边给包围着了,因为白色的灰度值为255,黑色的灰度值为0,所以我就假设以高为很坐标,然后每个高对应着的宽的灰度值进行相加。所以会很明显发现就6这个字的整体的值比较聚集,当然有可能有零星的散点,但并不影响对6所在位置的判断。最后以高为例,得到的值的坐标图如下:
    在这里插入图片描述
    因为最大值比较容易找到,所以就找到最大值然后向两边延伸,当发现值为零时就可以把边界给标定出来了。
    最后进行分割分割注意的是后面对图像进行裁剪的时候是将宽和高较长的一边减去较短的一边然后除以2平分给较短的一边的两侧,为了防止边缘检测没有包裹着数字,于是在数字四周都加了五个像素点进行裁剪,最后裁剪出来的效果如下:
    在这里插入图片描述
    这个图片就是上述代码中的tailor_image所显示出来的图片,因为显示图片的代码只作为测试使用,而且又很简单,这里就没有展示出来。
    好了,接下来就是要对辛辛苦苦裁剪出来的小图进行图像进行处理了,首先还是最基本的灰度化和高斯滤波处理,然后就是对图像进行大小转换,因为MNIST数据形状就是 28 ∗ 28 28*28 2828所以也要将输入图片转换成 28 ∗ 28 28*28 2828的大小。大小转换完成后,就是要完成把灰度图转换成背景为0,然后数字变成白色的图片,因为这样和MNIST数据集里的数字图片特别的像。在这里我用了阈值控制的方法将背景变成黑色的。至于这100当然是将图片的灰度值打出来后观察得出来的。但是这种方法是比较危险的,因为这样的鲁棒性并不强,但后面如果要加强鲁棒性则同样可以用边缘检测把数字包裹住,然后数字之外的背景清零,这确实是一个很好的思路,但在这里就建议的用阈值控制的方法来实现背景黑化了。黑化背景后当然就是将数字白化了,之前有将数字部分都是255值,但发现识别的效果并不理想,所以这里我采用了用255-原先数字的值,这样如果原先的数字黑度深的部分就会变成白色程度深,就简单的实现了数字边缘浅,中间深的变换。最后处理得到的图像如下:
    在这里插入图片描述
    虽说看起来没有第一张图那么完美,但大概还是能达到验证数据所需的要求了。至此,数据预处理已经完成了,接下来就是激动的预测了。

    预测

    预测代码如下:

    import torch
    
    # pretreatment.py为上面图片预处理的文件名,导入图片预处理文件
    import pretreatment as PRE
    
    # 加载网络模型
    net = torch.load('weight/test.pkl')
    
    # 得到返回的待预测图片值,就是pretreatment.py中的zoom_image
    img = PRE.image_preprocessing()
    
    # 将待预测图片转换形状
    inputs = img.reshape(-1, 784)
    
    # 输入数据转换成tensor张量类型,并转换成浮点类型
    inputs = torch.from_numpy(inputs)
    inputs = inputs.float()
    
    # 丢入网络进行预测,得到预测数据
    predict = net(inputs)
    
    # 打印对应的最后的预测结果
    print("The number in this picture is {}".format(torch.argmax(predict).detach().numpy()))
    

    最后得到结果如图所示:
    在这里插入图片描述
    这样,整个手写数字识别基本已经完成了。

    展开全文
  • mnist手写数字图片集

    2020-04-07 13:20:26
    minist手写数字图片集,用于tensorflow的手写数字是被训练的数据,内含1.5M图片一张。
  • MNIST手写数字数据库

    2019-03-04 15:32:50
    MNIST手写数字图像数据库 60000个训练集,10000个测试集,灰度图,大小均为为28*28 train-images-idx3-ubyte.gz: training set images (9912422 bytes) train-labels-idx1-ubyte.gz: training set labels (28881 ...
  • matlab直线回归近视预测代码手写数字识别系统 手写数字识别系统 在这个项目中,我实现了一对多逻辑回归和神经网络(前馈传播和反向传播)来识别手写数字(从 0 到 9)。 自动手写数字识别在今天被广泛使用 - 从识别...
  • 带GUI界面的手写数字识别

    千次阅读 2022-01-03 21:57:00
    带GUI界面的手写数字识别1.效果图2.数据集3.关于模型4.关于GUI设计1)排版2)直接运行这个文件(调用1)5.缺点6.遗留问题 1.效果图 有点low,轻喷 点击选择图片会优先从当前目录查找 2.数据集 这部分我是对MNIST...

    1.效果图

    有点low,轻喷
    在这里插入图片描述
    点击选择图片会优先从当前目录查找
    在这里插入图片描述
    在这里插入图片描述

    2.数据集

    这部分我是对MNIST数据集进行处理保存
    对应代码:

    import tensorflow as tf
    import matplotlib.pyplot as plt
    import cv2
    from PIL import Image
    import numpy as np
    from scipy import misc
    (x_train_all,y_train_all),(x_test,y_test) = tf.keras.datasets.mnist.load_data()
    x_valid,x_train = x_train_all[:5000],x_train_all[5000:]
    y_valid,y_train = y_train_all[:5000],y_train_all[5000:]
    print(x_valid.shape,y_valid.shape)
    print(x_train.shape,y_train.shape)
    print(x_test.shape,y_test.shape)
    #读取单张图片
    def show_single_img(img_arr,len=100,path='/Users/zhangcaihui/Desktop/case/jpg/'):
        for i in range(len):#我这种写法会进行覆盖,只能保存10张照片,想保存更多的数据自己看着改
            new_im = Image.fromarray(img_arr[i])  # 调用Image库,数组归一化
            #new_im.show()
            #plt.imshow(img_arr)  # 显示新图片
            label=y_train[i]
            new_im.save(path+str(label)+'.jpg')  # 保存图片到本地
    
    #显示多张图片
    def show_imgs(n_rows,n_cols,x_data,y_data):
        assert len(x_data) == len(y_data)
        assert n_rows * n_cols < len(x_data)
        plt.figure(figsize=(n_cols*1.4,n_rows*1.6))
        for row in range(n_rows):
            for col in range(n_cols):
                index = n_cols * row + col
                plt.subplot(n_rows,n_cols,index+1)
                plt.imshow(x_data[index],cmap="binary",interpolation="nearest")
                plt.axis("off")
        plt.show()
    #show_imgs(2,2,x_train,y_train)
    show_single_img(x_train)
    

    3.关于模型

    我保存了了之前训练好的模型,用来加载预测
    关于tensorflow下训练神经网络模型:手把手教你,MNIST手写数字识别
    训练好的模型model.save(path)即可

    4.关于GUI设计

    1)排版

    #ui_openimage.py
    # -*- coding: utf-8 -*-
    # from PyQt5 import QtCore, QtGui, QtWidgets
    # from PyQt5.QtCore import Qt
    import sys,time
    from PyQt5 import QtGui, QtCore, QtWidgets
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName("Form")
            Form.resize(1144, 750)
            self.label_1 = QtWidgets.QLabel(Form)
            self.label_1.setGeometry(QtCore.QRect(170, 130, 351, 251))
            self.label_1.setObjectName("label_1")
            self.label_2 = QtWidgets.QLabel(Form)
            self.label_2.setGeometry(QtCore.QRect(680, 140, 351, 251))
            self.label_2.setObjectName("label_2")
            self.btn_image = QtWidgets.QPushButton(Form)
            self.btn_image.setGeometry(QtCore.QRect(270, 560, 93, 28))
            self.btn_image.setObjectName("btn_image")
            self.btn_recognition = QtWidgets.QPushButton(Form)
            self.btn_recognition.setGeometry(QtCore.QRect(680,560,93,28))
            self.btn_recognition.setObjectName("bnt_recognition")
            #显示时间按钮
            self.bnt_timeshow = QtWidgets.QPushButton(Form)
            self.bnt_timeshow.setGeometry(QtCore.QRect(900,0,200,50))
            self.bnt_timeshow.setObjectName("bnt_timeshow")
            self.retranslateUi(Form)
            self.btn_image.clicked.connect(self.slot_open_image)
            self.btn_recognition.clicked.connect(self.slot_output_digital)
            self.bnt_timeshow.clicked.connect(self.buttonClicked)
            self.center()
            QtCore.QMetaObject.connectSlotsByName(Form)
    
        def retranslateUi(self, Form): #设置文本填充label、button
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate("Form", "数字识别系统"))
            self.label_1.setText(_translate("Form", "点击下方按钮"))
            self.label_1.setStyleSheet('font:50px;')
            self.label_2.setText(_translate("Form", "0~9"))
            self.label_2.setStyleSheet('font:50px;')
            self.btn_image.setText(_translate("Form", "选择图片"))
            self.btn_recognition.setText(_translate("From","识别结果"))
            self.bnt_timeshow.setText(_translate("Form","当前时间"))
    
        # 状态条显示时间模块
        def buttonClicked(self):  # 动态显示时间
            timer = QTimer(self)
            timer.timeout.connect(self.showtime)
            timer.start()
        def showtime(self):
            datetime = QDateTime.currentDateTime()
            time_now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            #self.statusBar().showMessage(time_now)
            #self.bnt_timeshow.setFont(QtGui.QFont().setPointSize(100))
            self.bnt_timeshow.setText(time_now)
    
        def center(self):#窗口放置中央
            screen = QDesktopWidget().screenGeometry()
            size = self.geometry()
            self.move((screen.width() - size.width()) / 2,
                        (screen.height() - size.height()) / 2)
    
    
        def keyPressEvent(self, e):
            if e.key() == Qt.Key_Escape:
                self.close()
    
    
    
    
    ## 2)直接运行这个文件(调用1)
    
    ```python
    #ui_main.py
    import random
    
    from PyQt5.QtWidgets import QFileDialog
    from PyQt5.QtGui import QPixmap
    from ui_openimage import Ui_Form
    import sys
    from PyQt5 import QtWidgets, QtGui
    from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction, QApplication
    import os,sys
    from PyQt5.QtCore import Qt
    
    import tensorflow
    from tensorflow.keras.models import load_model
    from tensorflow.keras.datasets import mnist
    from tensorflow.keras import models
    from tensorflow.keras import layers
    from tensorflow.keras.utils import to_categorical
    import tensorflow.keras.preprocessing.image as image
    import matplotlib.pyplot as plt
    import numpy as np
    import cv2
    import warnings
    warnings.filterwarnings("ignore")
    class window(QtWidgets.QMainWindow,Ui_Form):
        def __init__(self):
            super(window, self).__init__()
            self.cwd = os.getcwd()
            self.setupUi(self)
            self.labels = self.label_1
            self.img=None
        def slot_open_image(self):
            file, filetype = QFileDialog.getOpenFileName(self, '打开多个图片', self.cwd, "*.jpg, *.png, *.JPG, *.JPEG, All Files(*)")
            jpg = QtGui.QPixmap(file).scaled(self.labels.width(), self.labels.height())
            self.labels.setPixmap(jpg)
            self.img=file
    
        def slot_output_digital(self):
        	'''path为之前保存的模型路径'''
            path='/Users/zhangcaihui/PycharmProjects/py38_tf/DL_book_keras/save_the_model.h5'
            model= load_model(path)
            #防止不上传数字照片而直接点击识别
            if self.img==None:
                self.label_2.setText('请上传照片!')
                return
            img = image.load_img(self.img, target_size=(28, 28))
            img = img.convert('L')#转灰度图像
            x = image.img_to_array(img)
            #x = abs(255 - x)
            x = np.expand_dims(x, axis=0)
            print(x.shape)
            x = x / 255.0
            prediction = model.predict(x)
            print(prediction)
            output = np.argmax(prediction, axis=1)
            print("手写数字识别为:" + str(output[0]))
            self.label_2.setText(str(output[0]))
    
    if __name__ == "__main__":
      app = QtWidgets.QApplication(sys.argv)
      my = window()
      my.show()
      sys.exit(app.exec_())
    
    

    5.缺点

    1. 界面low
    2. 只能识别单个数字
      其实可以将多数字图片进行裁剪分割,这就涉及到制作数据集了

    6.遗留问题

    我自己手写的数据照片处理成28281送入网络预测,识别结果紊乱。
    反思:自己写的数据是RGB,且一张几KB,图片预处理后,按28*28读入失真太严重了,谁有好的方法可以联系我!!!

    其他的水果识别系统,手势识别系统啊,改改直接套!

    展开全文
  • 进行手写数字的图片预测的时候碰到了这样的问题。 先说说处理图片有三种方式 一、matplotlib 二、PIL 三、opencv 一、matplotlib 1、显示图片 import matplotlib.pyplot as plt #plt 用于显示图片 import matplotlib...
  • 每个样本都是一张28*28像素的灰度手写数字图片。 #(3)one_hot表示独热编码,其值被设为true。在分类问题的数据集标注时,如何不采用独热编码的方式, 类别通常就是一个符号而已,比如说是9。但如果采用独热编码的...
  • 已经分开了训练集与测试集,标签也转换为直接能用的类型。test_x 28*28*10000,train_x 28*28*60000.test_y 10*10000, train_y 10*60000

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,235
精华内容 3,694
关键字:

如何制作灰度手写数字