机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)

Python实现KNN手写数字图片识别

    • 1.数据集格式
    • 2.把自己图片转化为数据集格式(把宽高是32像素x32像素的黑白图像转换为文本格式)
    • 3.用数据集实现
    • 4.运行结果
    • 4.代码下载地址

KNN是最简单的机器学习方法之一,很适合新手入门。不过我在网上搜索这个方法时,都是用网上的数据集,并没有人教怎样把自己的图片转化为算法可以识别的。作为一个小白好不容易研究出来了,在这里分享给大家。

1.数据集格式

机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第1张图片

2.把自己图片转化为数据集格式(把宽高是32像素x32像素的黑白图像转换为文本格式)

原始图片-自己用电脑自带画图软件画的图,命名为3,并保存为PNG格式,放到文件夹下。
机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第2张图片
代码(Python):

// An highlighted block
from PIL import Image
import matplotlib.pylab as plt
import numpy as np 

def picTo01(filename):
    #读取图片
    img=Image.open(filename).convert('RGBA')
    raw_data=img.load()
    #根据图片的RGBA值进行降噪
    for y in range(img.size[1]):
       for x in range(img.size[0]):
           if raw_data[x,y][0]<90:
               raw_data[x,y]=(0,0,0,255)
 
    for y in range(img.size[1]):
       for x in range(img.size[0]):
           if raw_data[x,y][1]<136:
               raw_data[x,y]=(0,0,0,255)

    for y in range(img.size[1]):
       for x in range(img.size[0]):
           if raw_data[x,y][2]>0:
               raw_data[x,y]=(255,255,255,255)
# 把图片转化为32x32
    img=img.resize((32,32),Image.LANCZOS)
#把处理后的图片进行保存,便于对比
    img.save('test'+filename.split('.')[0]+'.png')
#根据公式把图片黑的地方变成1,白的地方变成0
    array=plt.array(img)
    gray_array=np.zeros((32,32))
    for x in range(array.shape[0]):
       for y in range(array.shape[1]):
           gray=0.299*array[x][y][0]+0.587 * array[x][y][1] + 0.114 * array[x][y][2]
           #white
           if gray==255:
               gray_array[x][y]=0
            #black
           else:
                gray_array[x][y]=1
    #把txt文件命名为此数字并保存
    name01=filename.split('.')[0]
    name01=name01+'.txt'
    np.savetxt(name01,gray_array,fmt='%d',delimiter='')
#执行
picTo01('3.PNG')


降噪后的图片:
机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第3张图片
最后生成的TXT文件:
机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第4张图片

3.用数据集实现

把testDigits和trainDigits数据集保存在名为Recognize的文件夹下,并分别创建test.py和train.py
train.py:

import os.path
import numpy as np
#把 32*32 转化为 1*1024
def img32to1024(filename):
    returnVect=np.zeros((1,1024))
    fr=open(filename,'r')
    for i in range(32):
        lineStr=fr.readline()
        for j in range(32):
            returnVect[0,32*i+j]=int(lineStr[j])
    return returnVect

#整理train data 和 labels(文件名为label)
hwLabels=[]
trainingFileList=os.listdir('trainingDigits')
m=len(trainingFileList)
trainingMat=np.zeros((m,1024))
for i in range(m):
    fileNameStr=trainingFileList[i]
    fileStr=fileNameStr.split('.')[0]
    classNumStr=int(fileStr.split('_')[0])
    hwLabels.append(classNumStr)
    trainingMat[i,:]=img32to1024('trainingDigits/%s' % fileNameStr)

test.py:

import os.path
import numpy as np
import train as tr
def classify(inX,k):
    dataSetSize=tr.m
    diffMat=inX-tr.trainingMat
    sqDiffMat=diffMat**2
    sqDistances=sqDiffMat.sum(axis=1)
    distances=sqDistances**0.5
    #get the rank
    sortedDistances=distances.argsort()
    classCount={}
    for i in range(k):
        voteIlabel=tr.hwLabels[sortedDistances[i]]
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
    sortedClassCount=sorted(classCount.items(),reverse=True)
    return sortedClassCount[0][0]



#test
testFileList=os.listdir('testDigits')
errorCount=0.0
mTest=len(testFileList)
realLabel=[]
testLabel=[]
for i in range(mTest):
    fileNameStr=testFileList[i]
    fileStr=fileNameStr.split('.')[0]
    classNumStr=int(fileStr.split('_')[0])
    vectorUnderTest=tr.img32to1024('testDigits/%s' % fileNameStr)
    testLabel=classify(vectorUnderTest,3)
    print("the classifier came back with:%s, the real answer is:%s" %(testLabel,classNumStr))
    if(testLabel!=classNumStr):
        errorCount+=1.0

print(errorCount/mTest)

4.运行结果

执行python test.py
机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第5张图片
机器学习入门-用KNN实现手写数字图片识别(包含自己图片转化)_第6张图片
可以看到错误率为0.1

4.代码下载地址

代码及数据集下载

你可能感兴趣的:(机器学习)