zoukankan      html  css  js  c++  java
  • 基于模板匹配的手写数字识别

    【实验项目名称】

    手写数字特征提取方法与实现

    【实验目的】

    通过手写数字特征的提取,了解数字的特征提取方法,掌握特征匹配准则。

    【实验原理】

    读取标准化后的数字0~9,二值化,对每个数字进行等分区域分割,统计每个区域内的黑色像素点的个数,即为特征初值。采用欧式距离的模板匹配法判断数字。

    【实验要求】

    给定数字0-9的原始样本集合,每个数字都有100个大小为28*28的样本图像。要求如下:

    1、将上述图像切分成标准图像库,存储为文件。

    2、对每个数字进行等分区间分割。

    3、给出统计结果:每个区域内的黑色像素点个数值以及占总量的百分比,显示出计算结果。

    4、采用欧氏距离模板匹配法,给出识别结果。

    5、从统计意义上,给出每个数字的识别率。


    1.Python库的相关配置:OpenCV 

    2.实验流程图:

    3.实验步骤分析(包含有train图片集、test图片集):

      1.图片预处理,该实验使用图片均已做过预处理,均为二值化的图像(0 和 255),黑底白字,28*28大小,如下图所示;

                      

      2.对所有train图片进行数据压缩,设计为28*28->7*7,也就是,每一个小方块中含有4*4=16个像素点,通过统计小方块中的像素值,分别给小方块标记为0或1(其中当白点超过16/2 = 8 个时,记该小方块为1,反之,记为0。可以知道,每一张图片可以被49个0_1字符串刻画。

      3.对train图片集中所有图片进行上述处理,并将其字符串数据进行存储(可以设计为存储在一个txt文档,,称为模板库)。然后对test图片集中的每一张图片进行字符串转化,同样可以得到49个字符串的0_1数据,然后将其与模板库中的字符串数据进行对比,其中,欧氏距离最小的即认为是和该测试图片是同一类数字。以此分辨手写数字图片。

      4.关于各种统计率的计算:[正确率]--(最小距离唯一,且两个图片数字属于同一类)或者(存在多个最小距离,但是均属于同一类数字);

                  [拒绝识别率]--(存在多个最小距离,并且不全部属于同一类数字,无法正常分类);

                  [错误率]--(最小距离唯一,并且两个图片不属于同一类数字);

      5.为了更好地判断两个图片是否属于同一类数字,故一般在其49个字符数据前加上一些标记符号,用来表示该字符串属于哪个数字。

    4.Python实现(其中路径绝对方式给出

    one_test.py文件:(该文件中代码复杂主要在于三种识别率的计算,其中关于每类识别得统计判断有点繁杂,需耐心)

    Function.Image_Compression(root_dir) -------图像压缩,返回压缩数据流

    Function.Distance(test_str, train_str)--------计算样本间距

     1 # 基于模板的手写数字识别
     2 import os
     3 import cv2
     4 import Function     # 关于该实验中需要调用的函数
     5 # 1.样本特征,不需预处理
     6 # 2.图像压缩表示,28*28——7*7,存储于(E:PatternRecognitionpicture7_7.txt)
     7 root_dir = "E:/train-images"           # 训练数据集
     8 file7_7 = open("E:/PatternRecognition/picture7_7.txt", 'w')     # 覆盖写模式
     9 for fl in os.listdir(root_dir):      # 循环处理所有train图片
    10     img_str = fl[0:-4] + ":" + Function.Image_Compression(root_dir + '/' + fl)      # 图像压缩,返回压缩数据流
    11     file7_7.write(img_str + '
    ')      # 压缩后的图像数据写入文本存储
    12 file7_7.close()
    13 # 3.待测样本的相似性比较,根据最近距离判断
    14 # 4.根据相似性比较给出识别结果,并给出统计意义上的正确率,错误率,拒绝识别率
    15 file7_7 = open("E:/PatternRecognition/picture7_7.txt", 'r')     # 只读模式
    16 root_dir = "E:/test-images"          # 测试test-images数据集
    17 Correct_rate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    18 Error_rate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    19 Rejection_rate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    20 ############
    21 for fl in os.listdir(root_dir):      # 循环处理所有test图片
    22     # 一些必备的基础数据变量
    23     Same_dist_number = 0    # 用于记录最小距离时,是否存在多个标准样本,并标记个数
    24     Same_class = -1         # 当有多个相同距离时,如果他们均为同一类别,则标记为该类别;-1表示可直接判断。
    25     min_dist = 7            # 用于存储判断最小距离
    26     dist_img = ""           # 用于标记当前最小距离时,属于哪个数字图片
    27     # 开始处理test图片的匹配识别
    28     test_img_str = Function.Image_Compression(root_dir + '/' + fl)      # test图片数据
    29     while True:
    30         line = file7_7.readline()
    31         if not line:        # 已读完整个文档,光标返回开头,结束此次匹配
    32             file7_7.seek(0)
    33             break
    34         train_str = line[-50:-1]        # train图片数据
    35         temp_dist = Function.Distance(test_img_str, train_str)      # 计算样本间距
    36         if temp_dist < min_dist:        # 更新min_dist/dist_img/Same_dist_number
    37             min_dist = temp_dist
    38             dist_img = line[0:-51]      # 提取最小距离的图片名称,即属于哪个数字
    39             Same_dist_number = 0        # 出现最小距离,个数归零
    40             Same_class = -1             # 出现最小距离,不需要类别判断
    41         elif temp_dist == min_dist:
    42             Same_dist_number += 1       # 表示具有相同距离的数字
    43             if dist_img[0:1] == line[0:1]:      # 样本间距相等,同时是同一类的样本
    44                 Same_class = eval(line[0:1])    # 记录同一类别
    45             else:
    46                 Same_class = -1         # 表明,同时具有不同类的数字样本与测试数字距离相等
    47     # 识别结果 以及 识别结果的数据统计
    48     # a.Same_dist_number = 0 ,表明可以直接识别出来,但不保证正确率
    49     # b.Same_dist_number != 0 and Same_class = -1 ,拒绝识别,同时有不同数字与其距离相等
    50     # c.Same_dist_number != 0 and Same_class ,可以识别,表示同一类数字中多个样本与其距离相等
    51     if Same_dist_number == 0:           # 该数字可以识别
    52         print("测试数字:", fl[0:-4], "  --  识别出来的结果:", dist_img)    # 数字的识别结果
    53         if fl[0] == dist_img[0]:
    54             Correct_rate[eval(fl[0])] += 1        # 正确识别
    55         else:
    56             Error_rate[eval(fl[0])] += 1          # 识别错误
    57     elif Same_class == -1:              # 拒绝识别
    58         print("测试数字:", fl[0:-4], "  --  该数字拒绝识别!")
    59         Rejection_rate[eval(fl[0])] += 1      # 拒绝识别
    60     else:                               # 同一类数字中多个样本与其距离相等
    61         print("测试数字:", fl[0:-4], "  --  识别出来的结果(类):", Same_class)
    62         if eval(fl[0]) == Same_class:
    63             Correct_rate[eval(fl[0])] += 1  # 正确识别
    64         else:
    65             Error_rate[eval(fl[0])] += 1  # 识别错误
    66 file7_7.close()
    67 print("------------------------------------------------")
    68 for i in range(10):
    69     print("数字 {:d} 识别的正确率 = {:.2f}% ,错误率 = {:.2f}% ,拒绝识别率 = {:.2f}%".format(i, Correct_rate[i]*5, Error_rate[i]*5, Rejection_rate[i]*5))
    70 print("success!")
    View Code

      <<----------------------数据流显示

    5.两个函数:

    Function.py文件:(包含两个需要常调用的函数)

    Image_Compression(img_path)

     1 import cv2
     2 
     3 #######################
     4 # 实现图像压缩,28*28——7*7,并以49数据流返回,img_path--图片路径
     5 # 划分为4*4的像素矩阵,其中八个及以上的像素点超过127即记为1,反之为0
     6 # 参数img_path,必须为完成的图片路径
     7 #######################
     8 def Image_Compression(img_path):
     9     # 数据按行存储
    10     img_str = ""        # 存数据流
    11     img = cv2.imread(img_path)
    12     # print("图像的形状,返回一个图像的(行数,列数,通道数):", img.shape)
    13     x = y = 0           # img像素点坐标表示img[x][y]
    14     for k in range(1, 50):      # k的范围1-49
    15         totle_img = 0           # 统计满足要求的像素点数目
    16         for i in range(4):
    17             for j in range(4):
    18                 if img[x + i - 1][y + j - 1][0] > 127:
    19                     totle_img += 1
    20         y = (y + 4) % 28
    21 # 一个矩形阵中包含16个像素点,其中像素值大于127的点超过八个记为1,反之记为0
    22         if totle_img >= 8:
    23             img_str += '1'
    24         else:
    25             img_str += '0'
    26         if k % 7 == 0:      # 控制x,y的变化
    27             x = x + 4
    28             y = 0
    29     return img_str
    View Code

     Distance(test_str, train_str)

     1 #######################
     2 # 计算测试样本与标准样本之间的距离,返回以距离,test_str--测试,train_str--标准
     3 # 其中test_str,train_str均必须保证为49个字符串形式的数字
     4 # 返回一个double类型的数据
     5 #######################
     6 def Distance(test_str, train_str):
     7     len_str = len(train_str)        # 数据长度
     8     dist = 0.0
     9     for i in range(len_str):        # 计算距离
    10         dist += (eval(test_str[i:i+1]) - eval(train_str[i:i+1]))**2
    11     dist **= 0.5
    12     return dist
    View Code

    6.1匹配结果:(test是从train里面提取出来的若干图片合集)

         

    数字 0 识别的正确率 = 100.00% ,错误率 = 0.00% ,拒绝识别率 = 0.00%

    数字 1 识别的正确率 = 45.00% ,错误率 = 0.00% ,拒绝识别率 = 55.00%

    数字 2 识别的正确率 = 85.00% ,错误率 = 0.00% ,拒绝识别率 = 15.00%

    数字 3 识别的正确率 = 80.00% ,错误率 = 0.00% ,拒绝识别率 = 20.00%

    数字 4 识别的正确率 = 90.00% ,错误率 = 0.00% ,拒绝识别率 = 10.00%

    数字 5 识别的正确率 = 80.00% ,错误率 = 0.00% ,拒绝识别率 = 20.00%

    数字 6 识别的正确率 = 90.00% ,错误率 = 0.00% ,拒绝识别率 = 10.00%

    数字 7 识别的正确率 = 95.00% ,错误率 = 0.00% ,拒绝识别率 = 5.00%

    数字 8 识别的正确率 = 100.00% ,错误率 = 0.00% ,拒绝识别率 = 0.00%

    数字 9 识别的正确率 = 85.00% ,错误率 = 0.00% ,拒绝识别率 = 15.00%

    6.2匹配结果:(其他方式构建的图片)

     暂无

    7.总结:

      实验可以通过特征压缩的方式来适当减少特征值的数量,然后再进行模板匹配,需要注意的是,特征值得压缩需要处于适当的范围。特征值过多会导致计算数据多大,匹配速度较慢,反之,特征值过少,对数据的判别存在较大的误差。总的来说,对于模板匹配识别方式,计算量较大,匹配速度较慢。

    2021-04-29

  • 相关阅读:
    Silverlight的OOB特性 (转)
    B/S安全退出
    判断滚动条是否到达页面的尾部
    通过XmlSerializer序列化(对象)和反序列化(xml文件)
    SQL Server与ADO.Net数据类型对照
    在C#里使用属性,如Obsolete,Serializable,XmlRoot
    SQL求往年的工资和
    通过使用partition by 过滤重复项
    委托的协变与逆变代码
    Routing
  • 原文地址:https://www.cnblogs.com/2015-16/p/14720111.html
Copyright © 2011-2022 走看看