OpenCV实例(四)手写数字识别

作者: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)

输出结果:
在这里插入图片描述

posted @ 2023-04-13 20:08  小幽余生不加糖  阅读(470)  评论(0编辑  收藏  举报  来源