模板匹配算法(手写数字识别)

研一的课程结束了,抓住暑假最后的尾巴,将模式识别与机器学习课程上的作业整理出来,当做是一次复习。

模板匹配算法(手写数字识别)_第1张图片 来自我b导的图

模板匹配

模板是已知的、带标签的,将未知的样本和所有模板进行匹配,计算相似度。相似度如何计算呢,我们的研究对象是图像,可以计算图像和模板特征向量之间的距离(欧式距离)。

作业要求为:使用模板匹配对手写数字,和车牌数字进行识别。数据集提供大家参考(提取码:roz1)

模板匹配算法(手写数字识别)_第2张图片

模板匹配算法(手写数字识别)_第3张图片

思路也挺简单的:

  1. 首先是做模板,将10个数字做成模板,定义一个函数将二维数组的图像展平为一纬数组,将十个模板存放在一个list中。需要对手写数字和车牌数字两种字体识别,所以需要做分别做模板
  2. 计算相似度用的是欧式距离,定义一个函数计算欧式距离
  3. 将待识别的图像分别和模型计算欧式距离,取最小距离的模型数字为识别结果 
import numpy as np
import cv2

#展平二维图像
def vector(data):
    h,w = data.shape[0:2]
    img_pixel = np.asarray(data).reshape(1,h*w)
    return img_pixel

#制作手写数字模板
def write_template():
    temple_list = []
    for i in range(0,10):
        path_tem = './课程数据集/手写数字/{}/'.format(i)
        img = cv2.imdecode(np.fromfile(path_tem+'2.bmp',np.uint8), cv2.IMREAD_GRAYSCALE)
        img_resize = cv2.resize(img, (250,250))
        tem_pixel = vector(img_resize)
        temple_list.append(tem_pixel)
    return temple_list

#制作车牌数字模板
def car_template():
    template_list2 = []
    for i in range(0,10):
        path_tem2 ='./课程数据集/车牌/{}.bmp'.format(i)
        img = cv2.imdecode(np.fromfile(path_tem2,np.uint8),cv2.IMREAD_GRAYSCALE)
        img_resize = cv2.resize(img,(250,250))
        tem_pixel = vector(img_resize)
        template_list2.append(tem_pixel)
    return template_list2

#计算欧式距离
def Euclidean_distance(x,y):
    tem = np.array(x).astype(np.float32)
    sam = np.array(y).astype((np.float32))
    num2 = np.square(tem-sam)
    return np.sqrt(np.sum(num2))

#template matching
if __name__ =="__main__":
    print('\n用手写体模板匹配\n')
    print('手写体数字匹配\n')
    template_list = write_template()
    number_list = []
    correct_num = 0
    for index in range(0,10):
        path_write = './课程数据集/手写数字/{}/'.format(index)
        sam_img = cv2.imdecode(np.fromfile(path_write + '5.bmp',np.uint8),cv2.IMREAD_GRAYSCALE)
        sam_resize = cv2.resize(sam_img,(250,250))
        sam_pixel = vector(sam_resize)
        ture_num = index
        number_list.append(index)

        #cal the Euclidean distance
        distance_list = []
        for tem in template_list:
            distance = Euclidean_distance(tem,sam_pixel)
            distance_list.append(distance)

        #cal the shortest distance
        short_dis = min(distance_list)
        short_index =distance_list.index(min(distance_list))
        if int(ture_num) == short_index:
            correct_num  += 1
        print('数字{}到模板的最短距离为:{},匹配到的类别为:{}\n'.format(ture_num,short_dis,short_index))
        distance_list.clear()
    n = len(number_list)
    print('共测试了{}个样本,正确匹配的个数为:{}'.format(n,correct_num))
    print('\n车牌数字匹配\n')
    car_num_list = []
    car_correct_num = 0
    for index in range(0,10):
        path_tem = './课程数据集/车牌/{}.1.bmp'.format(index)
        img_car_pic = cv2.imdecode(np.fromfile(path_tem,np.uint8),cv2.IMREAD_GRAYSCALE)
        img_car_pic_resize = cv2.resize(img_car_pic,(250,250))
        img_car_pixel = vector(img_car_pic_resize)
        car_ture_num = index
        car_num_list.append(index)

        #cal the Euclidean distance
        car_distance_list =[]
        for tem in template_list:
            car_distance = Euclidean_distance(tem,img_car_pixel)
            car_distance_list.append(car_distance)
        short_car_dis = min(car_distance_list)
        short_car_index = car_distance_list.index(min(car_distance_list))
        if int(car_ture_num) == int(short_car_index):
            car_correct_num +=1
        print('数字{}到模板的最短距离为:{},匹配到的类别为:{}\n'.format(car_ture_num,short_car_dis,short_car_index))
        car_distance_list.clear()
    m = len(car_num_list)
    print('共测试了{}个样本,正确匹配的个数为:{}'.format(m,car_correct_num))

    print('\n用车牌模板匹配\n')
    print('手写体数字匹配\n')
    template_list = car_template()
    number_list = []
    correct_num = 0
    for index in range(0,10):
        path_write = './课程数据集/手写数字/{}/'.format(index)
        sam_img = cv2.imdecode(np.fromfile(path_write + '5.bmp',np.uint8),cv2.IMREAD_GRAYSCALE)
        sam_resize = cv2.resize(sam_img,(250,250))
        sam_pixel = vector(sam_resize)
        ture_num = index
        number_list.append(index)

        #cal the Euclidean distance
        distance_list = []
        for tem in template_list:
            distance = Euclidean_distance(tem,sam_pixel)
            distance_list.append(distance)

        #cal the shortest distance
        short_dis = min(distance_list)
        short_index =distance_list.index(min(distance_list))
        if int(ture_num) == short_index:
            correct_num  += 1
        print('数字{}到模板的最短距离为:{},匹配到的类别为:{}\n'.format(ture_num,short_dis,short_index))
        distance_list.clear()
    n = len(number_list)
    print('共测试了{}个样本,正确匹配的个数为:{}'.format(n,correct_num))
    print('\n车牌数字匹配\n')
    car_num_list = []
    car_correct_num = 0
    for index in range(0,10):
        path_tem = './课程数据集/车牌/{}.1.bmp'.format(index)
        img_car_pic = cv2.imdecode(np.fromfile(path_tem,np.uint8),cv2.IMREAD_GRAYSCALE)
        img_car_pic_resize = cv2.resize(img_car_pic,(250,250))
        img_car_pixel = vector(img_car_pic_resize)
        car_ture_num = index
        car_num_list.append(index)

        #cal the Euclidean distance
        car_distance_list =[]
        for tem in template_list:
            car_distance = Euclidean_distance(tem,img_car_pixel)
            car_distance_list.append(car_distance)
        short_car_dis = min(car_distance_list)
        short_car_index = car_distance_list.index(min(car_distance_list))
        if int(car_ture_num) == int(short_car_index):
            car_correct_num +=1
        print('数字{}到模板的最短距离为:{},匹配到的类别为:{}\n'.format(car_ture_num,short_car_dis,short_car_index))
        car_distance_list.clear()
    m = len(car_num_list)
    print('共测试了{}个样本,正确匹配的个数为:{}'.format(m,car_correct_num))

以下内容为补充

模板匹配是图像处理的一个基础算法,在图像A中寻找到与图像B(模板)最相似的区域,opencv有相应的函数调用 cv.matchTemplate(img,template,参数)。函数不同参数的具体效果可以看看中文文档模板匹配 (apachecn.org),有趣的是cv.TM_CCOEFF_NORMED参数可以在一张图像上匹配多个对象。

你可能感兴趣的:(模式识别与机器学习,java,开发语言)