1. 首先把 .png格式的图片处理成标准化后的数组矩阵
编写图片转换
# png :为存储32x32的图片集
#txt :为存储每张图片标准化后的矩阵集
pngpath = './png/' #存放手写提数字图片
txtpath = './txt/' #保存转换后的数字矩阵文档
def png2txt(pngpath,txtpath):
'''将固定尺寸的手写体图片转换成0,1数组矩阵文件'''
pnglist = listdir(pngpath)
for i in pnglist:
fname = i.split(".")[0]
im = Image.open(pngpath+"/"+i)
fh = open(txtpath+"/"+fname+".txt","a")
for m in range(0,32): #像素高度
for n in range(0,32): #像素宽度
pix = im.getpixel((n,m)) #获取该图片的每个RGB像素点
pixs = pix[0]+pix[1]+pix[2]
if pixs==0:
fh.write("1") #若该像素点RGB为0的话,打印1
else:
fh.write("0") #该像素点不为0,即打印0
fh.write("\n")
fh.close()
注释:因为实现代码后,朋友问起RGB该问题。我觉得对于我这种新手还是解释一下为妙。也为查寻该资料的同行者少走弯路。
im = Image.open(pngpath+"/"+i) #这里是获取一张图片
如该行代码获取 一张显示为 9 的图
pix = im.getpixel((n,m)) #获取该图片的每个RGB像素点
如我们通过遍历获取到该图片坐标(0,0)的位置
该位置为白色,则:(R,G,B) = (255,255,255)
因为该图片是黑白组成,则可打印出一个由 0,1组成的32 × 32的标准化矩阵。
trainpath = './traindata/'
testpath = './testdata/'
#提取训练集和测试集
def shutildata():
"""将后缀为15的文件分拣出来作为测试集
其他文件作为训练集
"""
txt_list = listdir(txtpath)
for i in txt_list:
if(i.split('.')[0].split('_')[1]=='15'):
shutil.move(txtpath+'/'+i,testpath)
else:
shutil.move(txtpath +'/'+ i, trainpath)
def data2array(fname):
'''读取0,1组成的矩阵数据,把矩阵存放入列表中'''
arr = []
fh = open(fname)
for i in range(0,32):
thisline = fh.readline()
for j in range(0,32):
arr.append(int(thisline[j])) #
return arr
def traindata():
'''建立训练数据'''
labels = [] #建空列表存放标签
trainfile = listdir(trainpath) #获取训练集文件夹下的所有文件名
#先建立一个行数为训练样本数,列数为1024的0数组矩阵,1024为图片像素总和,即32*32。
trainarr = np.zeros((len(trainfile),1024))
#提取文件名的第一个数字为标签名
for i in range(0,len(trainfile)):
thislabel = trainfile[i].split(".")[0].split("_")[0]
if len(thislabel)!=0:
labels.append(int(thislabel)) #保存标签
# 将所有traindata文件下的标准化矩阵铺平组成了200x1024 大矩阵
trainarr[i,:] = data2array(trainpath+trainfile[i])
return trainarr,labels
def knn(k,testdata,traindata,labels):
traindatasize = traindata.shape[0] #获取训练集长度
#因为测试样本和训练集差异,需要扩展至与训练集相同(欧式距离)
#testdata 沿着Y轴复制200次:np.tile(data(Y,X))
dif = np.tile(testdata,(traindatasize,1)) - traindata
#计算距离
sqrdif = dif**2
sumsqdif = sqrdif.sum(axis=1) #按行求平方和
dsitance = sumsqdif**0.5
sorted_distance = dsitance.argsort() #返回按元素值从小到大排序,并返回元素的下标 len = 200
count = {} #存放投票结果
for i in range(0,k):
vote = labels[sorted_distance[i]]#提取索引多对应的标签值作为字典
count[vote] = count.get(vote,0) + 1
sorted_count = sorted(count.items(),key=lambda x:x[1],reverse=True) #按V值排序
return sorted_count[0][0]
def datatest():
trainarr,labels = traindata()
testfiles = listdir(testpath)
for i in range(0,len(testfiles)):
testpicname = testfiles[i].split("_")[0]
testarr = data2array(testpath+testfiles[i])
result = knn(2,testarr,trainarr,labels)
print("真正数字:"+testpicname+" "+"测试结果为:{}".format(result))
即测试集的单集(1,1024)减去训练集的全集(200,1024)的每一行。共减200次。再这200行中,把最小值的 index 根据 k 的个数进行提取。再通过 该下标提取训练集的标签(即全集与之对应的行下标)
摘自知乎https://zhuanlan.zhihu.com/p/51326751 (python数据分析入门)。