研一的课程结束了,抓住暑假最后的尾巴,将模式识别与机器学习课程上的作业整理出来,当做是一次复习。
模板匹配
模板是已知的、带标签的,将未知的样本和所有模板进行匹配,计算相似度。相似度如何计算呢,我们的研究对象是图像,可以计算图像和模板特征向量之间的距离(欧式距离)。
作业要求为:使用模板匹配对手写数字,和车牌数字进行识别。数据集提供大家参考(提取码:roz1)
思路也挺简单的:
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参数可以在一张图像上匹配多个对象。