智能计算课第一周的实验是做基于模板匹配的手写数字识别,光听见就很感兴趣,于是决定认真做做这个实验,本实验基于python3+opencv的python版本,所用到的知识都比较简单,基本上边学边做,技术含量很低。

实现思路:

大致就是这么个思路但其实纠错模块还没写出来,先搁置一下吧,准备先上手第二个实验。

下面按照流程图讲讲详细步骤吧

手写数字window.py

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80import tkinter

from PIL import Image

import recognition as rec

import numpy as np

import cv2

img = np.zeros((400,400),np.uint8)

app = tkinter.Tk()

app.resizable(0,0)

app.title('数字识别 v1.0')

app['width']=400

app['height']=400

yseno = tkinter.IntVar(value=0)

X = tkinter.IntVar(value=0)

Y = tkinter.IntVar(value=0)

foreColor = '#000000'

backColor = '#FFFFFF'

image = tkinter.PhotoImage()

canvas = tkinter.Canvas(app,bg='white',width=400,height=400)

canvas.create_image(400,400,image=image)

def (event):

yseno.set(1)

X.set(event.x)

Y.set(event.y)

canvas.bind('',onLeftButtonDown)

def onLeftButtonMove(event):

if yseno.get()==0:

return

canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor,width=10)

X.set(event.x)

Y.set(event.y)

if (event.x-3>=0) and (event.x+3<=400) and (event.y-3>=0) and (event.y+3<=400):

img[event.y-3:event.y+3,event.x-3:event.x+3]=255

canvas.bind('',onLeftButtonMove)

def onLeftButtonUp(event):

# canvas.create_line(X.get(),Y.get(),event.x,event.y,fill=foreColor)

yseno.set(0)

canvas.bind('',onLeftButtonUp)

def clear():

global img

img = img * 0

for item in canvas.find_all():

canvas.delete(item)

# print(item)

buttonClear = tkinter.Button(app,text='清除',command=clear)

buttonClear.place(x=200,y=370,width=200,height=30)

def recognition():

#保存图片...得到img

global img

# img = img.T

num = rec.recognition(img)

print('识别出的数字为:',num)

# cv2.imshow('img',img)

# cv2.waitKey(0)

# cv2.destroyAllWindows

buttonRec = tkinter.Button(app,text='识别',command=recognition)

buttonRec.place(x=0,y=370,width=200,height=30)

canvas.pack(fill=tkinter.BOTH,expand=tkinter.YES)

app.mainloop()

照着图书馆借来的书,边看边敲的代码,所以比较简单,实现的功能也比较简单,运行结果如图:

图片标准化

标准化图片我这里分四步:像素取反,灰度化,去噪以及图片分割。

1.像素取反

1

2

3def negation(img):#图片取反

img = cv2.bitwise_not(img)

return img

其实就一句话,也就是用opencv自带的方法 cv2.bitwise_not方法就OK了

2.灰度化(+二值化)

1

2

3

4

5def graying(img):#二值化图像

img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret,thresh=cv2.threshold(img,250,255,cv2.THRESH_BINARY)

img = thresh

return thresh

同样使用opencv函数,得到的是黑底(0)白字(255)。

3.去噪

1

2

3

4

5def denoise(img):

kernel = np.ones((5,5),np.uint8)

img = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)

img = cv2.blur(img,(10,10))

return img

用到中值滤波和低通滤波,原意是为了去掉离群点,但经过老师点拨,发现效果其实并不好我去掉的只是数字周围的毛刺点,并不是离群点,如下图

就没办法得到理想的效果,最新的想法是利用能量分布去除离群点(不是很懂,找时间研究研究),好像马氏距离也行?嗯,先放放···

4.图片分割

原图是这样的

然后分割完(中间经过了上述各种处理)变成了这样的

代码如下:

1

2

3

4

5

6

7

8def splitPicture(img):

img = standard(img)

binary,contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

for i in range(len(contours)):

x,y,w,h = cv2.boundingRect(contours[i])

# print([x,y,w,h])

img = img[y:y+h,x:x+w]

return img

cv2.findContours函数是opencv的轮廓检测函数,其中返回值coutours是轮廓点集,再利用cv2.boundingRect函数,得出最小矩形边框,x,y,w,h分别是该矩形左上角坐标及矩形宽高,然后用numpy索引就可以 高效分割图片啦(之所以强调 高效,是因为最开始我用自己的双重for循环做出来的东西跑一趟要30多秒,而现在只要不到0.3秒,所以好好利用库函数总是没错的!)

与模板库对比

模板匹配,顾名思义就是与模板对比,以某种方式得出两张图片的相似程度,从而判断出手写数字是多少。我的第一版用的是欧氏距离匹配,简单来说,两点欧式距离

$d=sqrt{(x1-x2)^2+(y1-y2)^2}$

而对于图像来说,我们可以先算出它的特征值,然后求特征值之间的距离,就可以得到相似程度的距离值。

首先,求特征值。为了减少计算量,我把每张图片分成$5*5$即每张图分为25小块,每一小块的特征值用该区域白色(255)像素点个数除以该块总像素数代表,每张图片有25个特征值,对比两张图片就是依次比较它们的特征值。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17def getEigenvalue(img):#传入图片,返回一个特征值列表

img = splitPicture(img)

h,w = img.shape

h0 = int(h/5)

w0 = int(w/5)

# print([h0,w0])

# count = 0

# imgList = []#25张小图片

ratioList = []#小图片白色像素特征值列表

for i in range(5):

for j in range(5):

# imgList.append(img[i+i*h0:i+(i+1)*h0,j+j*w0:j+(j+1)*w0])

ratioList.append(getRatio(img[i+i*h0:i+(i+1)*h0,j+j*w0:j+(j+1)*w0]))

# for k in range(len(imgList)):

# ratioList.append(getRatio(imgList[k]))

# print(ratioList)

return ratioList

然后,得到”距离“。

1

2

3

4

5

6

7

8def getDistance(img1,img2):

list1 = getEigenvalue(img1)

list2 = getEigenvalue(img2)

distance = 0

for i in range(25):

distance = distance + (list1[i]-list2[i])**2

return int(math.sqrt(distance))

#return int(distance)

到这里,思路已经很清晰了,将所要识别的数字图像依次和图片库中的图片对比求“距离”,取“距离值”最小的数字代表的值即为所要识别的数字的值。

剩下的就是依次对比的部分了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43def getImgNameList():#获取图片库每张图片的路径及其所代表的数字

wolk_path = os.path.split(os.path.realpath(__file__))[0]

# print(os.listdir(wolk_path))

#rootList = os.listdir(wolk_path)

source_path = os.path.join(wolk_path,'source photo')

#print(source_path)

imgdir_path_list=[]

# img_path_list=[]

namemap={}

for i in range(10):

imgdir_path = os.path.join(source_path,str(i))#source下0,1...等目录

#print(imgdir_path)

imgdir_path_list.append(imgdir_path)

# print(os.listdir(imgdir_path_list[0]))

for j in range(10):

dir = len(os.listdir(imgdir_path_list[j]))

#print(os.listdir(imgdir_path_list[j]))

for k in range(dir):

img_path = os.path.join(imgdir_path_list[j],(os.listdir(imgdir_path_list[j]))[k])

# img_path_list.append(img_path)

#print(img_path)

namemap[img_path]=j

# return img_path_list,namemap

return namemap

def recognition(img1):#识别

# img1 = cv2.imread(img1)

# img_path_list,namemap = getImgNameList()

namemap = getImgNameList()

# print(namemap.keys()[0])

similarty = []

try:

# for i in range(len(img_path_list)):

# img2 = cv2.imread(img_path_list[i])

#print(img_path_list[i])

for key in namemap.keys():

# print(key)

img2 = cv2.imread(key)

# cv2.imshow('img',img2)

# cv2.waitKey(0)

# print(key)

similarty.append(getDistance(img1,img2))

# print(similarty[i],'..................')

最后,纠错模块就是人工指出数字是几,然后将图片保存到相应文件夹,因为图片的命名没啥思路,就先偷个懒先放着了,然后就是,想把识别结果也用窗口显示出来,也先搁着了。st=>start: 开始

e=>end: 结束

io1=>inputoutput: 手写数字

op1=>operation: 图片标准化

op2=>operation: 与模板库对比

cond=>condition: 人工鉴别

op3=>operation: 纠错并加入模板库

io2=>inputoutput: 识别正确

io4=>inputoutput: 无法识别

end=>end: 结束

st->io1->op1->op2->cond

cond(yes)->io2->end

cond(no,left)->op3->end{"scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12}

python opencv数字识别_基于模板匹配的手写数字识别(python+opencv)相关推荐

  1. matlab朴素贝叶斯手写数字识别_基于MNIST数据集实现手写数字识别

    介绍 在TensorFlow的官方入门课程中,多次用到mnist数据集.mnist数据集是一个数字手写体图片库,但它的存储格式并非常见的图片格式,所有的图片都集中保存在四个扩展名为idx*-ubyte ...

  2. 基于模板匹配的手写字体数字识别-含Matlab代码

    目录 一.引言 二.系统知识的表示与组织 2.1 规则前提条件的描述 2.2 规则结论的表示 2.3 知识库的组织 三.手写字体数字识别算法流程 四.识别结果 五.参考文献 六.Matlab代码获取 ...

  3. mnist手写数字识别python_基于tensorflow的MNIST手写数字识别(二)--入门篇

    一.本文的意义 因为谷歌官方其实已经写了MNIST入门和深入两篇教程了,那我写这些文章又是为什么呢,只是抄袭?那倒并不是,更准确的说应该是笔记吧,然后用更通俗的语言来解释,并且补充更多,官方文章中没有 ...

  4. 【手写数字识别】基于Lenet网络实现手写数字识别附matlab代码

    1 内容介绍 当今社会,人工智能得到快速发展,而模式识 别作为人工智能的一个重要应用领域也得到了飞 速发展,它利用计算机通过计算的方法根据样本的 特征对样本进行分类,其中的光学字符识别技术受 到广大研 ...

  5. 基于深度学习的手写数字识别算法Python实现

    摘 要 深度学习是传统机器学习下的一个分支,得益于近些年来计算机硬件计算能力质的飞跃,使得深度学习成为了当下热门之一.手写数字识别更是深度学习入门的经典案例,学习和理解其背后的原理对于深度学习的理解有 ...

  6. Python基于深度学习的手写数字识别

    Python基于深度学习的手写数字识别 1.代码的功能和运行方法 2. 网络设计 3.训练方法 4.实验结果分析 5.结论 1.代码的功能和运行方法 代码可以实现任意数字0-9的识别,只需要将图片载入 ...

  7. Python,OpenCV基于支持向量机SVM的手写数字OCR

    Python,OpenCV基于支持向量机SVM的手写数字OCR 1. 效果图 2. SVM及原理 2. 源码 2.1 SVM的手写数字OCR 2.2 非线性SVM 参考 上一节介绍了基于KNN的手写数 ...

  8. 基于深度学习的手写数字识别、python实现

    基于深度学习的手写数字识别.python实现 一.what is 深度学习 二.加深层可以减少网络的参数数量 三.深度学习的手写数字识别 一.what is 深度学习 深度学习是加深了层的深度神经网络 ...

  9. 基于卷积神经网络的手写数字识别(附数据集+完整代码+操作说明)

    基于卷积神经网络的手写数字识别(附数据集+完整代码+操作说明) 配置环境 1.前言 2.问题描述 3.解决方案 4.实现步骤 4.1数据集选择 4.2构建网络 4.3训练网络 4.4测试网络 4.5图 ...

最新文章

  1. Pair Testing
  2. 10的预览模式_谷歌相机2020年3月更新汇总,适配米10等五摄手机,30s手动曝光
  3. ​什么是TCP/IP
  4. VS直接调试可执行文件main函数.exe输入参数argc(项目--> 属性--> 调试--> 命令参数)
  5. 百练OJ:3865和2677:肿瘤检测
  6. lstm需要优化的参数_使用PyTorch手写代码从头构建LSTM,更深入的理解其工作原理...
  7. Linux内核锁实现原理,linux 大内核锁原理
  8. C++的const修饰
  9. Linux arm 下载程序,arm-linux—gcc如何下载安装
  10. request.post
  11. 如何在Linux中使用ulimit命令
  12. spark sql 的性能调优
  13. C代码中__LINE__输出时与代码行号不同的解决办法
  14. Opencv学习笔记 超像素分割
  15. .doc文件不显示word图标
  16. 基于阿里云服务器使用kubeadm搭建k8s集群
  17. Sun Jan 29 14:34:06 格林尼治标准时间+0800 2012”解析
  18. wireshark抓取Android手机app的包
  19. super()继承关系总结
  20. Seq2Seq模型讲解

热门文章

  1. pic单片机c语言乘除法,PIC单片机C语言编程教程(1)
  2. SDK模拟器安装及配置
  3. STM32 UCOSII移植
  4. 《如何高效记忆》阅读笔记
  5. H3C 三层交换机 设置俩vlan不能相互通讯,只能访问某个端口,且其中一个vlan不能上网...
  6. 线程池ThreadPoolExecutor详解(整理详细)
  7. 所谓”不用加号的加法运算“
  8. 解放生产力!chatGPT接入Excel与Word教程(需要魔法上网,不用的都是骗人的)
  9. 开拓前沿领域,荟萃创新英才
  10. 让百度、Google等各大搜索引擎收录你的博客