使用k-近邻的手写识别系统算法实现步骤
- 收集数据
- 准备数据
- 分析数据
- 训练数据
- 测试算法
- 使用算法
首先还是按照书上的例子,将训练集和测试集下载到本地,
此次只是为了测试之前写的识别器的错误率,并没有实际对手写字体进行识别,不过看了学长的博客,也算是把识别的代码写了一些,把jpg格式的手写数字转换为txt格式的,其实就是求出图像相应灰度值,然后写上对应的asscii_char 01数字 如图
87的由于写的比较细,看起来效果不是太好
下面第一步(我没有添加到之前写的knn.py文件中,直接在jupyter交互环境下写的)
#手写数字识别系统的测试代码
from numpy import *
import knn
import operator
from os import listdir
filename2 = "数据集/trainingDigits"
testDigitFile = "数据集/testDigits"
import time
def img2vector(filename2):
returnVect = zeros((1,1024))
#returnVect?
fr = open(filename2)
for i in range(32):
linestr = fr.readline()
for j in range(32):
returnVect[0,32*i+j] = int(linestr[j])
return returnVect
# def classnumCut(filename)
#def hadwritingClassTest():
hwLabels = []
#将该含有训练集目录中所有需要训练的数据列出来
trainingFileList = listdir(filename2)
trainingFileList
#获取文件数量
m = len(trainingFileList)
m
#创建一个m行1024列的ndarray矩阵
trainingMat = zeros((m,1024))
trainingMat
for i in range(m):
#将文件目录中每个txt文件都导出来
if trainingFileList[i] ==".ipynb_checkpoints":
continue
fileNameStr = trainingFileList[i]
# print(fileNameStr)
fileStr = fileNameStr.split('.')[0]
#print(fileStr)
#为了将空行去掉 才能将字符型数字转化为int型数字
if fileStr:
classNumStr = int(fileStr.split('_')[0])
#print(classNumStr)
#将数字添加到数组中
hwLabels.append(classNumStr)
#print('数据集/trainingDigits/%s'%fileNameStr)
trainingMat[i,:] = img2vector('数据集/trainingDigits/%s'%fileNameStr)#将对应目录添加到矩阵中
#print(trainingMat)
#获取到测试集
testFileList = listdir(testDigitFile)
#print(testFileList)
#统计错误率
errorCount = 0.0
mTest = len(testFileList)
#print(mTest) #'''获取到的测试集的数据长度 946'''
t1 = time.time()
for i in range(mTest):
fileNameStr = testFileList[i]
# print(fileNameStr)
fileStr = fileNameStr.split('.')[0]
#print(fileStr)
classNumStr = int(fileStr.split('_')[0])
#print(classNumStr)
vectorUnderTest = img2vector('数据集/testDigits/%s' % fileNameStr)
#使用分类器进行分类
classifierResult = knn.classify(vectorUnderTest,trainingMat,hwLabels,3)
#print("分类器测试的结果是:",classifierResult,"真正的结果是:",classNumStr)
if (classifierResult != classNumStr):
errorCount += 1.0
t2 = time.time()
print("分类器分类的错误个数是%s"%errorCount)
print("手写字体识别错误率是:%f" % (errorCount/float(mTest)))
print("所花费的时间为:%.2fmin,%.4fs" % ((t2-t1)//60,(t2-t1)%60))
#结果
'''
分类器分类的错误个数是10.0
手写字体识别错误率是:0.010571
所花费的时间为:0.00min,21.5465s
主要原因是7和9,7和1之间不好判断
可以改变k的值重新调整错误率,也可以使用交叉验证法修改测试集来验证
缺点,:效率太低,耗时长,每个测试向量计算月2000次欧式距离,每个距离计算1024个维度浮点运算,全部测试赝本有946次
所以耗时才那么长
'''
至于分类器代码,就不再这在写一遍了,之前我写的改进约会网站的配对实例里面都有的。
下面是对手写数字进行jpg图像转换为txt格式的,
#将手写数字 jpg格式的转化为只有0和1表示的txt文档表示
from PIL import Image
import argparse
#代码核心的思想是怎样求出对应图片灰度值后填充自己规定的ascii_char
ascii_char = '10'
#核心代码,按照灰度值转化成ascii_char值
def select_ascii_char(r,g,b):
#获取灰度值
gray = int((19595 * r + 38469 *g + 7472 * b)>> 16)#位运算 右移一位相当于除以2
unit = 256.0/len(ascii_char)
#print(gray)
return ascii_char[int(gray/unit)]
#将原图自定义大小
def preimg(img_name, width, height):
img = Image.open(img_name)
print(img.size)
img = img.resize((width, height), Image.NEAREST)
print(img.size)
#将图像灰度化
img.convert('L')
return img
#将图像转换为矩阵格式
def img2char(img):
res = ''
width, height = img.size
for h in range(height):
for w in range(width):
res += select_ascii_char(*img.getpixel((w,h))[:3])
res += '\n'
return res
if __name__ == '__main__':
img_name='87.png'
image = Image.open(img_name)
width = 80
height = 50
file = 'test.txt'
img = preimg(img_name, width, height)
#img.show()
pic_str = img2char(img)
print(pic_str)
代码主要还是看学长的,然后自己分析了一下,加上了一点自己的理解。
http://blog.csdn.net/qq_33638791/article/details/54578560
学长写的还是要比我强的多的,其实这里面有些我还是不太明白,不过这都是次要的,用opencv搞着应该是比较容易的,回头学一下opencv