python opencv数字识别_基于模板匹配的手写数字识别(python+opencv)
智能计算课第一周的实验是做基于模板匹配的手写数字识别,光听见就很感兴趣,于是决定认真做做这个实验,本实验基于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)相关推荐
- matlab朴素贝叶斯手写数字识别_基于MNIST数据集实现手写数字识别
介绍 在TensorFlow的官方入门课程中,多次用到mnist数据集.mnist数据集是一个数字手写体图片库,但它的存储格式并非常见的图片格式,所有的图片都集中保存在四个扩展名为idx*-ubyte ...
- 基于模板匹配的手写字体数字识别-含Matlab代码
目录 一.引言 二.系统知识的表示与组织 2.1 规则前提条件的描述 2.2 规则结论的表示 2.3 知识库的组织 三.手写字体数字识别算法流程 四.识别结果 五.参考文献 六.Matlab代码获取 ...
- mnist手写数字识别python_基于tensorflow的MNIST手写数字识别(二)--入门篇
一.本文的意义 因为谷歌官方其实已经写了MNIST入门和深入两篇教程了,那我写这些文章又是为什么呢,只是抄袭?那倒并不是,更准确的说应该是笔记吧,然后用更通俗的语言来解释,并且补充更多,官方文章中没有 ...
- 【手写数字识别】基于Lenet网络实现手写数字识别附matlab代码
1 内容介绍 当今社会,人工智能得到快速发展,而模式识 别作为人工智能的一个重要应用领域也得到了飞 速发展,它利用计算机通过计算的方法根据样本的 特征对样本进行分类,其中的光学字符识别技术受 到广大研 ...
- 基于深度学习的手写数字识别算法Python实现
摘 要 深度学习是传统机器学习下的一个分支,得益于近些年来计算机硬件计算能力质的飞跃,使得深度学习成为了当下热门之一.手写数字识别更是深度学习入门的经典案例,学习和理解其背后的原理对于深度学习的理解有 ...
- Python基于深度学习的手写数字识别
Python基于深度学习的手写数字识别 1.代码的功能和运行方法 2. 网络设计 3.训练方法 4.实验结果分析 5.结论 1.代码的功能和运行方法 代码可以实现任意数字0-9的识别,只需要将图片载入 ...
- Python,OpenCV基于支持向量机SVM的手写数字OCR
Python,OpenCV基于支持向量机SVM的手写数字OCR 1. 效果图 2. SVM及原理 2. 源码 2.1 SVM的手写数字OCR 2.2 非线性SVM 参考 上一节介绍了基于KNN的手写数 ...
- 基于深度学习的手写数字识别、python实现
基于深度学习的手写数字识别.python实现 一.what is 深度学习 二.加深层可以减少网络的参数数量 三.深度学习的手写数字识别 一.what is 深度学习 深度学习是加深了层的深度神经网络 ...
- 基于卷积神经网络的手写数字识别(附数据集+完整代码+操作说明)
基于卷积神经网络的手写数字识别(附数据集+完整代码+操作说明) 配置环境 1.前言 2.问题描述 3.解决方案 4.实现步骤 4.1数据集选择 4.2构建网络 4.3训练网络 4.4测试网络 4.5图 ...
最新文章
- Pair Testing
- 10的预览模式_谷歌相机2020年3月更新汇总,适配米10等五摄手机,30s手动曝光
- ​什么是TCP/IP
- VS直接调试可执行文件main函数.exe输入参数argc(项目--> 属性--> 调试--> 命令参数)
- 百练OJ:3865和2677:肿瘤检测
- lstm需要优化的参数_使用PyTorch手写代码从头构建LSTM,更深入的理解其工作原理...
- Linux内核锁实现原理,linux 大内核锁原理
- C++的const修饰
- Linux arm 下载程序,arm-linux—gcc如何下载安装
- request.post
- 如何在Linux中使用ulimit命令
- spark sql 的性能调优
- C代码中__LINE__输出时与代码行号不同的解决办法
- Opencv学习笔记 超像素分割
- .doc文件不显示word图标
- 基于阿里云服务器使用kubeadm搭建k8s集群
- Sun Jan 29 14:34:06 格林尼治标准时间+0800 2012”解析
- wireshark抓取Android手机app的包
- super()继承关系总结
- Seq2Seq模型讲解
热门文章
- pic单片机c语言乘除法,PIC单片机C语言编程教程(1)
- SDK模拟器安装及配置
- STM32 UCOSII移植
- 《如何高效记忆》阅读笔记
- H3C 三层交换机 设置俩vlan不能相互通讯,只能访问某个端口,且其中一个vlan不能上网...
- 线程池ThreadPoolExecutor详解(整理详细)
- 所谓”不用加号的加法运算“
- 解放生产力!chatGPT接入Excel与Word教程(需要魔法上网,不用的都是骗人的)
- 开拓前沿领域,荟萃创新英才
- 让百度、Google等各大搜索引擎收录你的博客