手写体数字识别的两种方法

基于贝叶斯模型和KNN模型分别对手写体数字进行识别

首先,我们准备了0~9的训练集和测试集,这些手写体全部经过像素转换,用0,1表示,有颜色的区域为0,没有颜色的区域为1。实现代码如下:

# 图片处理
# 先将所有图片转为固定宽高,比如32*32,然后再进行处理
from PIL import Image as img

f = open('f:/result/weixin.txt', 'a')
im = img.open('f:/data/weixin.jpg')
# im.save('f:/data/weixin.bmp')
length = im.size[0]  # 长
width = im.size[1]  # 宽
# k=im.getpixel((1,9)) #获取图片某个像素的色素
for i in range(0, length):
    for j in range(0, width):
        RGB = im.getpixel((i, j))
        RGB_SUM = RGB[0] + RGB[1] + RGB[2]
        if RGB_SUM == 0:
            # 说明当前位置为黑色
            f.write('1')
        else:
            f.write('0')
    f.write('\n')
f.close()

手写数字体转换为0,1像素矩阵如下:
手写数字0像素矩阵
我们一共准备了1934个训练集和934个测试集,分别为0~9的手写体像素矩阵

基于贝叶斯模型对手写体数字进行识别

贝叶斯模型实现代码:

from numpy import *
from os import listdir


class Bayes:
    def __init__(self):
        self.length = -1  # 如果未进行训练,则length为-1
        self.labelcount = dict()
        self.vectorcount = dict()

    def fit(self, dataSet: list, labels: list):
        if (len(dataSet) != len(labels)):
            raise ValueError("输入的测试数组和类别数组不一致")
        self.length = len(dataSet[0])  # 测试数据特征值的长度
        labelsnum = len(labels)  # 所有类别数量
        no_repeat_lables = len(set(labels))  # 不重复类别的数量
        for item in range(no_repeat_lables):
            # 当前类别的数量占总类别数量的比例
            self.labelcount[item] = labels.count(item) / labelsnum
        for vector, label in zip(dataSet, labels):
            if (label not in self.vectorcount):
                self.vectorcount[label] = []
            self.vectorcount[label].append(vector)
        print('训练结束')
        return self

    def btest(self, TestData, labelSet):
        if (self.length == -1):
            raise ValueError("还未进行训练")
        # 计算当前testdata分别为各个类别的概率
        lbDict = dict()
        for thislb in labelSet:
            p = 1
            alllabel = self.labelcount[thislb]
            allvector = self.vectorcount[thislb]
            vnum = len(allvector)
            allvector = array(allvector).T
            for index in range(0, len(TestData)):
                vector = list(allvector[index])
                p = p * vector.count(TestData[index]) / vnum
            lbDict[thislb] = p * alllabel  # 当前标签的概率
        thislabel = sorted(lbDict, key=lambda x: lbDict[x], reverse=True)[0]
        return thislabel

之后,我们利用建立好的贝叶斯模型加载训练集、训练模型,实现代码如下:

# 加载数据
def dataToArray(filename):
    arr = []
    f = open(filename)
    for i in range(0, 32):
        thisline = f.readline()
        for j in range(0, 32):
            arr.append(int(thisline[j]))
    return arr
    
# 建立一个函数取文件名前缀
def seplabel(fname):
    filestr = fname.split(".")[0]
    label = int(filestr.split("_")[0])
    return label

# 建立训练数据
def traindata():
    labels = []
    trainfile = listdir("f:/data/traindata/")
    num = len(trainfile)
    # 长度1024(列),每一行存储一个文件
    # 用一个数组存储所有训练数据,行:文件总数,列:1024
    trainarr = zeros((num, 1024))
    for i in range(0, num):
        thisfname = trainfile[i]
        thislabel = seplabel(thisfname)
        labels.append(thislabel)
        trainarr[i, :] = dataToArray("f:/data/traindata/" + thisfname)
    return trainarr, labels

在对数据进行训练后,我们建立好的模型对测试数据中的手写体"8"进行测试,实现代码如下:

# 抽某一个测试文件出来进行试验
trainarr, labels = traindata()
thistestfile = "8_76.txt"
testarr = dataToArray("f:/data/testdata/" + thistestfile)
b = Bayes()
b.fit(trainarr, labels)
label = b.btest(testarr, labels)
print(label)

结果如下:
在这里插入图片描述
结果证明贝叶斯方法可以准确地识别出手写体“8”,接下来我们对贝叶斯方法的精度进行测试,这次我们对所有的测试集进行识别,实现代码如下:

# 识别多个手写体数据
testfile = listdir("f:/data/testdata/")
num = len(testfile)
count = 0
for i in range(0, num):
    this_file = testfile[i]
    this_label = seplabel(this_file)  # 正确的label
    test_arr = dataToArray("f:/data/testdata/" + this_file)
    result = b.btest(test_arr, labels_all)
    if (result == this_label):
        count += 1
    acc = count / num
    print(acc)

结果显示,最终精度为:
在这里插入图片描述
实验结果还不错,证明贝叶斯模型的确是一个较好的分类模型

基于KNN模型对手写体数字进行识别

接下来我们使用KNN对手写体数字进行识别,实验控制变量,继续采用之前的测试集和数据集。
首先,我们实现KNN模型:

from numpy import *
import operator
from os import listdir


def knn(k, testdata, traindata, labels):
    traindatasize = traindata.shape[0]
    dif = tile(testdata, (traindatasize, 1)) - traindata  # 扩展数组行
    sqdif = dif ** 2
    sumsqdif = sqdif.sum(axis=1)  # 行求和
    dis = sumsqdif ** 0.5  # 距离
    sort_dis = argsort(dis)  # 排序,返回的是索引
    count = {}
    for i in range(0, k):
        vote = labels[sort_dis[i]]  # 显示当前类
        count[vote] = count.get(vote, 0) + 1  # 统计各类别次数
    sortcount = sorted(count.items(), key=operator.itemgetter(1), reverse=True)  # 按照降序排列字典
    return sortcount[0][0]

然后,我们利用训练集创建KNN模型:

# 加载数据
def dataToArray(filename):
    arr = []
    f = open(filename)
    for i in range(0, 32):
        thisline = f.readline()
        for j in range(0, 32):
            arr.append(int(thisline[j]))
    return arr
    
# 取出文件前缀,获得label
def seplabel(filename):
    filestr = filename.split(".")[0]
    label = int(filestr.split("_")[0])
    return label

# 建立训练数据
def traindata():
    labels = []
    trainfile = listdir("f:/data/traindata/")
    num = len(trainfile)
    # 长度1024(列),每一行存储一个文件
    # 用一个数组存储所有训练数据,行:文件总数,列:1024
    trainarr = zeros((num, 1024))
    for i in range(0, num):
        thisfname = trainfile[i]
        thislabel = seplabel(thisfname)
        labels.append(thislabel)
        trainarr[i, :] = dataToArray("f:/data/traindata/" + thisfname)
    return trainarr, labels

最后,利用创建的KNN模型对测试集进行测试,同样是测试手写体“8”:

#抽某一个测试文件出来进行试验
trainarr,labels=traindata()
thistestfile="8_76.txt"
testarr=dataToArray("f:/data/testdata/"+thistestfile)
rknn=knn(3,testarr,trainarr,labels)
print(rknn)

结果为:
在这里插入图片描述
说明KNN模型也可以识别出手写体“8”,接下来我们利用所有测试集求出KNN模型的精度:

#用测试数据调用KNN算法去测试,看是否能够准确识别
def datatest():
    trainarr,labels=traindata()
    testlist=listdir("f:/data/testdata")
    tnum=len(testlist)
    count = 0
    for i in range(0,tnum):
        thistestfile=testlist[i]
        this_label = seplabel(thistestfile)
        testarr=dataToArray("f:/data/testdata/"+thistestfile)
        rknn=knn(3,testarr,trainarr,labels)
        if (rknn == this_label):
            count += 1
        acc = count / tnum
        print(acc)

结果为:
在这里插入图片描述
说明KNN也是一个较为良好的分类模型,而且比贝叶斯模型分类效果好。

  • 5
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言手写体数字识别是一种将手写数字图像转化为对应数字的技术。在这个任务中,使用神经网络来实现手写体识别。神经网络通过矩阵运算进行前馈计算,并使用交叉熵损失函数来评价整体误差。对于手写数字识别任务来说,校正值只有一个为1,其余为0,通过计算误差损失函数来衡量模型的准确性。 手写体数字识别属于文字识别和模式识别的范畴。在文字识别中,手写体识别是指联机手写体识别。这种识别任务可以分为脱机识别和联机识别两大类。 为了实现手写体数字识别,需要使用矩阵运算。首先需要实现神经网络的前馈计算。在C语言中,可以使用特定的矩阵操作库来实现这些计算。需要定义相关的数据类型和错误类型,并编写相应的代码来进行矩阵运算。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【C语言算法】前馈神经网络实现手写数字识别](https://blog.csdn.net/Ranchaun/article/details/129050251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [手写字迹识别C++代码](https://download.csdn.net/download/qq_42747705/12128826)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值