OpenCV实例(四)手写数字识别
- 1.基本原理
- 2.实现步骤
- 2.1数据准备
- 2.2计算匹配值
- 2.3获取最佳匹配值及对应模板
- 2.4获取最佳匹配模板对应的数字
- 2.5输出识别结果
- 3.代码实例
作者:Xiou
1.基本原理
使用模板匹配的方式实现手写数字识别,其基本实现原理如图所示。
使用模板匹配的方式实现手写数字识别,主要包含流程如下。
Step 1:数据准备。读取待识别图像和模板库。
Step 2:计算匹配值。计算待识别图像与所有模板的匹配值。需要注意的是,匹配值的计算有多种不同的方法。有时,匹配值越大表示二者越匹配;有时,匹配值越小表示二者越匹配。通常,也将该匹配值称为距离值。
Step 3:获取最佳匹配值及对应模板。获取所有匹配值中的最佳匹配值(该匹配值可能是所有匹配值中的最大值,也可能是所有匹配值中的最小值),并找到对应的模板。
Step 4:获取最佳匹配模板对应的数字。将最佳匹配模板对应的数字作为识别结果。
Step 5:输出识别结果。综上所述,使用模板匹配的方式实现手写数字识别的流程图所示。
2.实现步骤
2.1数据准备
数据准备工作主要是读取待识别图像和模板库,核心程序如下:
上述程序中,images存储了所有模板图像的路径。程序在遍历时,按照从数字0到数字9的顺序依次遍历。因此,遍历完成后,images内依次存储了数字0到数字9的所有模板。
每个数字共有10个模板,images的索引与模板图的路径名之间的关系如表所示。
images中依次存储的是数字0~9的共计100个模板图像的路径名,其中索引对应各模板图像的编号。例如,images[mn]表示,数字m的第n个模板图像的路径名。
2.2计算匹配值
在OpenCV内,模板匹配是使用函数cv2.matchTemplate()实现的,该函数的语法格式为:
匹配值=cv2.matchTemplate(原始图像,模板图像,cv2.TM_CCOEF)
在参数cv2.TM_CCOEFF的控制下,原始图像和模板图像越匹配返回的匹配值越大;原始图像和模板图像越不匹配,返回的匹配值越小。
构造一个函数,用来计算匹配值,程序如下:
该函数中,参数template是文件名,参数image是待检测图像。
2.3获取最佳匹配值及对应模板
本章通过将函数cv2.matchTemplate()的参数设置为cv2.TM_CCOEFF来计算匹配值,因此最大的匹配值就是最佳匹配值。
构造一个列表matchValue用来存储待识别图像与images中每个模板的匹配值,其中依次存储的是待识别图像与数字0~9的100个模板图像的匹配值。
列表matchValue中的索引对应各模板图像的编号。例如,matchValue[mn]表示待识别图像与数字m的第n个模板图像的匹配。列表matchValue中的最大值的索引即最佳匹配模板的索引。
具体程序如下:
2.4获取最佳匹配模板对应的数字
找到最佳匹配模板对应的数字,将该数字作为识别结果。
模板索引整除10得到的值正好是该模板图像对应的数字值。例如,matchValue[34]对应着数字3的第4个模板图像的匹配值。简单来说,索引为34的模板,对应着数字3。
索引34整除10,int(34/10)=3,3正好是模板对应的数字。确定了模板图像索引、识别值之间的关系,就可以通过计算索引来达到数字识别的目的了。
2.5输出识别结果
将识别的数字输出,程序如下:
print('识别结果:数字',number)
3.代码实例
使用模板实现手写数字识别。
测试图片:
# -*- coding: utf-8 -*-
import glob
import cv2
#==============准备数据========================
#读取待识别图像
o=cv2.imread("image/test2/3.bmp",0)
# images用于存储模板
images = []
# 遍历指定目录下所有子目录及模板图像
for i in range(10):
images.extend(glob.glob('image/'+str(i)+'/*.*'))
#=============计算匹配值函数=====================
def getMatchValue(template,image):
#读取模板图像
templateImage=cv2.imread(template)
#模板图像色彩空间转换,BGR-->灰度
templateImage = cv2.cvtColor(templateImage, cv2.COLOR_BGR2GRAY)
#模板图像阈值处理, 灰度-->二值
ret, templateImage = cv2.threshold(templateImage, 0, 255, cv2.THRESH_OTSU)
# 获取待识别图像的尺寸
height, width = image.shape
# 将模板图像调整为与待识别图像尺寸一致
templateImage = cv2.resize(templateImage, (width, height))
#计算模板图像、待识别图像的模板匹配值
result = cv2.matchTemplate(image, templateImage, cv2.TM_CCOEFF)
# 将计算结果返回
return result[0][0]
#===============计算最佳匹配值及模板序号======================
# matchValue用于存储所有匹配值
matchValue = []
# 从images中逐个提取模板,并将其与待识别图像o计算匹配值
for xi in images:
d = getMatchValue(xi,o)
matchValue.append(d)
# print(distance) #测试语句:看看各个距离值
# 获取最佳匹配值
bestValue=max(matchValue)
# 获取最佳匹配值对应模板编号
i = matchValue.index(bestValue)
# print(i) #测试语句:看看匹配的模板编号
#===============计算识别结果======================
#计算识别结果
number=int(i/10)
#===============显示识别结果======================
print("识别结果:数字",number)
输出结果: