python实现识别手写数字 python图像识别算法


Posted in Python onMarch 23, 2020

写在前面

这一段的内容可以说是最难的一部分之一了,因为是识别图像,所以涉及到的算法会相比之前的来说比较困难,所以我尽量会讲得清楚一点。

而且因为在编写的过程中,把前面的一些逻辑也修改了一些,将其变得更完善了,所以一切以本篇的为准。当然,如果想要直接看代码,代码全部放在我的GitHub中,所以这篇文章主要负责讲解,如需代码请自行前往GitHub。

本次大纲

上一次写到了数据库的建立,我们能够实时的将更新的训练图片存入CSV文件中。所以这次继续往下走,该轮到识别图片的内容了。

首先我们需要从文件夹中提取出需要被识别的图片test.png,并且把它经过与训练图片相同的处理得到1x10000大小的向量。因为两者之间存在微小的差异,我也不是很想再往源代码之中增加逻辑了,所以我就直接把增加待识别图片的函数重新写一个命名为GetTestPicture,内容与GetTrainPicture类似,只不过少了“增加图片名称”这一个部分。

之后我们就可以开始进行正式图片识别内容了。

主要是计算待识别图片与所有训练图片的距离。当两个图片距离越近的时候,说明他们越相似,那么他们很有可能写的就是同一个数。所以利用这个原理,我们可以找出距离待识别图像最近的几个训练图片,并输出他们的数字分别是几。比如说我想输出前三个,前三个分别是3,3,9,那就说明这个待识别图片很有可能是3.

之后还可以对每一个位置加个权重,具体的就放在下一次再讲,本节内容已经够多了。

(第一篇文章之中我说过利用图片洞数检测。我尝试了一下,认为有些不妥,具体原因放在本文末。)

MAIN代码

所以直接把主要代码放上来,逻辑相对来说还是比较清晰的

import os
import OperatePicture as OP
import OperateDatabase as OD
import PictureAlgorithm as PA
import csv

##Essential vavriable 基础变量
#Standard size 标准大小
N = 100
#Gray threshold 灰度阈值
color = 200/255

n = 10

#读取原CSV文件
reader = list(csv.reader(open('Database.csv', encoding = 'utf-8')))
#清除读取后的第一个空行
del reader[0]
#读取num目录下的所有文件名
fileNames = os.listdir(r"./num/")
#对比fileNames与reader,得到新增的图片newFileNames
newFileNames = OD.NewFiles(fileNames, reader)
print('New pictures are: ', newFileNames)
#得到newFilesNames对应的矩阵
pic = OP.GetTrainPicture(newFileNames)
#将新增图片矩阵存入CSV中
OD.SaveToCSV(pic, newFileNames)
#将原数据库矩阵与新数据库矩阵合并
pic = OD.Combination(reader, pic)

#得到待识别图片
testFiles = os.listdir(r"./test/")
testPic = OP.GetTestPicture(testFiles)

#计算每一个待识别图片的可能分类
result = PA.CalculateResult(testPic, pic)
for item in result:
 for i in range(n):
  print('第'+str(i+1)+'个向量为'+str(item[i+n])+',距离为'+str(item[i]))

相比上一篇文章的内容,本篇文章里只增加了下面的的一段代码,即得到待识别图片名称、得到待识别图片向量、计算分类。

下面我们将着重讲解CalculateResult函数的内容,即识别图片的算法。

算法内容

算法大致讲解

我们在大纲之中已经简单介绍过了,所以我就直接把复制过来,并且再添加一些内容。

假设我们在二维平面上有两个点A=(1,1)和B=(5,5),我现在再放一个点C=(2,2),那么请问,C点离哪一个更近?

学过初中数学的都会知道肯定是离A点更近。所以我们换一种说法,我们现在有两个类A和B,A类中包括了点(1,1),B类中包括了点(5,5),所以对于点(2,2),它可能属于哪一类?

因为这个点离A类的点更近一点,所以它可能属于A类。这就是结论。那么对于3维空间,A类是点(1,1,1)和B类是(5,5,5),那么对于点(2,2,2)肯定也是属于A类。

可以看出,我们这里是将两个点的距离来作为判断属于哪一类的标准。那么对于我们将图片拉成的1xn维向量,他实际上投影到n维空间上就是一个点,所以我们将训练向量分成10类,分别代表十个数字,那么被识别数字靠近哪一个类,那说明它有可能属于这一个类。

那么我们这里可以假设对于被识别向量,列出距离他最近的前十个向量分别属于哪一类别,然后根据名次加上一个权重,并计算出一个值。该值代表了可能是属于哪一个类,因此这就是我们得出的最终的一个结果——被识别手写数字图片的值。

以上是第一篇文章中的内容,下面我着重讲一下数学方面的内容。

考虑到某些地方不能够输入数学公式(或不方便输入),我还是把这一段内容贴成图片出来。

python实现识别手写数字 python图像识别算法

之后直接挑出前几个离被识别图片最近的向量数字,基本上这几个数字就是被识别图片的数字了。但这样做未免有些简单,所以下一篇文章我会再深入一下,这张先讲计算距离的内容。

主代码

下面的代码中文件夹test用来存放待识别图片,并通过函数GetTestPicture来得到图片向量,之后和训练图片pic一起放进计算距离的函数CalculateResult中计算每一个待识别向量和其他所有图片向量的距离。

#得到待识别图片
testFiles = os.listdir(r"./test/")
testPic = OP.GetTestPicture(testFiles)

#计算每一个待识别图片的可能分类
result = PA.CalculateResult(testPic, pic)
for item in result:
 for i in range(n):
  print('第'+str(i+1)+'个向量为'+str(item[i+n])+',距离为'+str(item[i]))

函数CalculateResult在文件PictureAlgorithm.py中,这个文件里面包含了两个函数为CalculateDistance函数和CalculateResult函数,代表识别图片所用到的算法。

函数CalculateResult

这个函数的逻辑比较简单,也没什么好说的,主要的联系就是这个计算距离的CalculateDistance函数。

def CalculateResult(test, train):
 '''计算待识别图片test的可能分类'''
 #得到每个图片的前n相似图片
 testDis = CalculateDistance(test[:,0:N**2], train[:,0:N**2], train[:,N**2], n)
 #将testDis变成列表
 tt = testDis.tolist()
 #输出每一个待识别图片的所有前n个
 for i in tt:
  for j in i:
   print(j)

函数CalculateDistance

函数中我导入了四个参数:被识别向量test,训练向量train,与训练向量对应的每个向量对应代表的数字num,想要导出的前n个距离最近的向量。

def CalculateDistance(test, train, num, n):
 '''计算每个图片前n相似图片'''
 #前n个放距离,后n个放数字
 dis = np.zeros(2*n*len(test)).reshape(len(test), 2*n)
 for i, item in enumerate(test):
  #计算出每个训练图片与该待识别图片的距离
  itemDis = np.sqrt(np.sum((item-train)**2, axis=1))
  #对距离进行排序,找出前n个
  sortDis = np.sort(itemDis)
  dis[i, 0:n] = sortDis[0:n]
  for j in range(n):
   #找到前几个在原矩阵中的位置
   maxPoint = list(itemDis).index(sortDis[j])
   #找到num对应位置的数字,存入dis中
   dis[i, j+n] = num[maxPoint]
 return dis

首先建立一个行数为test内被识别向量数量,列数为2*n的矩阵,每一行前n个放距离,后n个放数字。之后针对每一个被识别向量进行循环。

首先直接计算每个训练图片与该识别图片的距离,直接可以用一行代码表示

itemDis = np.sqrt(np.sum((item-train)**2, axis=1))

这一行代码就是上文中的算法过程,我个人觉得还是比较复杂的,可以详细的拆开看一下,我这里不细讲了。下面的内容就是开始排序并且找到距离最近的前几个向量。

这里的逻辑是:先排序,找到距离最小的前n个,存入矩阵。找到前n个在原矩阵中的位置,并找到对应位置上num的数字,存入dis的后n个。

这样子就相当于完成了所有内容,返回dis即可。

实际测试

我自己动手写了一些数字,如图所示。所以实际上我们的数据库还是比较小的。

python实现识别手写数字 python图像识别算法

所以我又写了一个数字作为待识别图像,通过程序运行以后,我们的以直接输出前十个最相似的向量:

第1个向量为2.0,距离为33.62347223932534
第2个向量为2.0,距离为35.64182105224185
第3个向量为2.0,距离为38.69663119274146
第4个向量为2.0,距离为43.52904133387693
第5个向量为2.0,距离为43.69029199677604
第6个向量为1.0,距离为43.730883339256714
第7个向量为6.0,距离为44.94800943845918
第8个向量为2.0,距离为45.033283944455924
第9个向量为4.0,距离为45.43926712996951
第10个向量为7.0,距离为45.64893989116544

之后我又依次从1-9试了一遍,我自己手写的数字全部识别正确,可以看出准确率还是挺高的。所以做到这一步相当于已经完成度很高了。

所以我就试了一下从网上找的图片,发现几乎没有正确的了。说明我们的数据库还是太小,只认得我的字体。不过话说这样,也可以做一个字体识别的程序。

所以如果要提高准确率,那么扩大图库是必须的。这一次就到这里。

总结

所有源代码我都放在了我的GitHub中,如果有兴趣的话可以去看看。

到这里就相当于算法内容写完了,比较简单,只用了一个类似于K最近邻的算法。

下一篇文章将会讲一个给前n个排名加权的想法,这样来提高准确度。

所以这一次就先到这里为止,谢谢。

如果喜欢的话,麻烦点一个喜欢和关注一下噢,谢谢~

本文已被收录到专题《python图片处理操作》 ,欢迎大家点击学习更多精彩内容。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现机械分词之逆向最大匹配算法代码示例
Dec 13 Python
TensorFlow实现MLP多层感知机模型
Mar 09 Python
解决Python2.7中IDLE启动没有反应的问题
Nov 30 Python
python钉钉机器人运维脚本监控实例
Feb 20 Python
一篇文章弄懂Python中所有数组数据类型
Jun 23 Python
Python-Seaborn热图绘制的实现方法
Jul 15 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
Aug 08 Python
Tensorflow不支持AVX2指令集的解决方法
Feb 03 Python
简单了解Python变量作用域正确使用方法
Jun 12 Python
用Python实现职工信息管理系统
Dec 30 Python
Python MNIST手写体识别详解与试练
Nov 07 Python
opencv深入浅出了解机器学习和深度学习
Mar 17 Python
Python实现简易版的Web服务器(推荐)
Jan 29 #Python
python实现图像识别功能
Jan 29 #Python
Python使用正则表达式获取网页中所需要的信息
Jan 29 #Python
python实现K最近邻算法
Jan 29 #Python
python简单实现操作Mysql数据库
Jan 29 #Python
Django框架教程之正则表达式URL误区详解
Jan 28 #Python
python通过百度地图API获取某地址的经纬度详解
Jan 28 #Python
You might like
php $_SERVER当前完整url的写法
2009/11/12 PHP
PHP5.5在windows安装使用memcached服务端的方法
2014/04/16 PHP
php可应用于面包屑导航的迭代寻找家谱树实现方法
2015/02/02 PHP
浅谈PHP的exec()函数无返回值排查方法(必看)
2017/03/31 PHP
PHP使用preg_split和explode分割textarea存放内容的方法分析
2017/07/03 PHP
javascript的数据类型、字面量、变量介绍
2012/05/23 Javascript
json对象转字符串如何实现
2012/12/02 Javascript
JQuery中$(document)是什么意思有什么作用
2014/07/21 Javascript
js判断当前页面用什么浏览器打开的方法
2016/01/06 Javascript
JavaScript  cookie 跨域访问之广告推广
2016/04/20 Javascript
jQuery时间日期三级联动(推荐)
2016/11/27 Javascript
jQuery Easyui加载表格出错时在表格中间显示自定义的提示内容
2016/12/08 Javascript
Vue.js中用v-bind绑定class的注意事项
2016/12/13 Javascript
JavaScript实现公历转农历功能示例
2017/02/13 Javascript
微信小程序 template模板详解及实例
2017/02/21 Javascript
js实现按座位号抽奖
2017/04/05 Javascript
基于Vue 2.0 监听文本框内容变化及ref的使用说明介绍
2018/08/24 Javascript
javascript使用substring实现的展开与收缩文字功能示例
2019/06/17 Javascript
Typescript的三种运行方式(小结)
2019/09/18 Javascript
Python httplib,smtplib使用方法
2008/09/06 Python
python基础教程之popen函数操作其它程序的输入和输出示例
2014/02/10 Python
Python实现快速排序算法及去重的快速排序的简单示例
2016/06/26 Python
python3.5 tkinter实现页面跳转
2018/01/30 Python
python3获取两个日期之间所有日期,以及比较大小的实例
2018/04/08 Python
对Python之gzip文件读写的方法详解
2019/02/08 Python
Django模型序列化返回自然主键值示例代码
2019/06/12 Python
pyqt5 lineEdit设置密码隐藏,删除lineEdit已输入的内容等属性方法
2019/06/24 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
python 的topk算法实例
2020/04/02 Python
美国最大的珠宝商之一:Littman Jewelers
2016/11/13 全球购物
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
Athleta官网:购买女士瑜伽服、技术运动服和休闲运动服
2020/11/12 全球购物
Java多态性的定义以及类型
2014/09/16 面试题
暑期学习心得体会
2014/09/02 职场文书
党的群众路线对照检查材料范文
2014/09/24 职场文书
2014年林业工作总结
2014/12/05 职场文书