通过识别手写的数字来练习KNN算法。再OpenCV中,可以直接调用cv2.KNearest()来实现K邻近算法。
本文目录:
[TOC]
整体流程
数据初始化
- 特征图像保存在
image
路径下 - 特征值一共有100个(0~9,每个数字有10个)
- 特征图像的行数(高度)、列数(宽度)。可以通过程序读取。在本例中,已经设置好了,是固定的特征,长和宽都是240行。
#读取样本(特征)图像的值
s='image\\' #图像所在路径
num=100 #共有样本数量
row=240 #每个数字图像的行数
col=240 #每个数字图像的列数
a=np.zeros((num,row,col)) #用来存储所有样本的数值
读取特征图像
将所有的特征图像读到变量a中,共有10个数字.可以采用嵌套循环来完成。
n=0 #用来存储当前图像的编号。
for i in range(0,10):
for j in range(1,11):
a[n,:,:]=cv2.imread(s+str(i)+'\\'+str(i)+'-'+str(j)+'.bmp',0)
n=n+1
提取图像的特征
提取特征值,可以是计算每个子块内黑色或白色像素点的个数。此处选用白色。
这里,把每幅图都划分成5X5的小块块。
#提取样本图像的特征
feature=np.zeros((num,round(row/5),round(col/5))) #用来存储所有样本的特征值
#print(feature.shape) #看看feature的shape长什么样子
#print(row) #看看row的值,有多少个特征(100)个
for ni in range(0,num):
for nr in range(0,row):
for nc in range(0,col):
if a[ni,nr,nc]==255:
feature[ni,int(nr/5),int(nc/5)]+=1
f=feature #简化变量名称
#将feature处理为单行形式
train = feature[:,:].reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
计算待识别图像的特征值
##读取图像值
o=cv2.imread('image\\test\\5.bmp',0) #读取待测图像
of=np.zeros((round(row/5),round(col/5))) #用来存储测试图像的特征值
for nr in range(0,row):
for nc in range(0,col):
if o[nr,nc]==255:
of[int(nr/5),int(nc/5)]+=1
test=of.reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
调用识别函数计算距离
#调用函数识别
knn=cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE, trainLabels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
输出结果
print("当前随机数可以判定为类型:", result)
print("距离当前点最近的5个邻居是:", neighbours)
print("5个最近邻居的距离: ", dist)
演示
import cv2
import numpy as np
#读取样本(特征)图像的值
s='image\\' #图像所在路径
num=100 #共有样本数量
row=240 #每个数字图像的行数
col=240 #每个数字图像的列数
a=np.zeros((num,row,col)) #用来存储所有样本的数值
#print(a.shape)
n=0 #用来存储当前图像的编号。
for i in range(0,10):
for j in range(1,11):
a[n,:,:]=cv2.imread(s+str(i)+'\\'+str(i)+'-'+str(j)+'.bmp',0)
n=n+1
#提取样本图像的特征
feature=np.zeros((num,round(row/5),round(col/5))) #用来存储所有样本的特征值
#print(feature.shape) #看看feature的shape长什么样子
#print(row) #看看row的值,有多少个特征(100)个
for ni in range(0,num):
for nr in range(0,row):
for nc in range(0,col):
if a[ni,nr,nc]==255:
feature[ni,int(nr/5),int(nc/5)]+=1
f=feature #简化变量名称
#将feature处理为单行形式
train = feature[:,:].reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
#print(train.shape)
#贴标签,需要注意range(0,100)不是range(0,101)
trainLabels = [int(i/10) for i in range(0,100)]
trainLabels=np.asarray(trainLabels)
#print(*trainLabels) #打印测试看看标签值
##读取图像值
o=cv2.imread('image\\test\\5.bmp',0) #读取待测图像
of=np.zeros((round(row/5),round(col/5))) #用来存储测试图像的特征值
for nr in range(0,row):
for nc in range(0,col):
if o[nr,nc]==255:
of[int(nr/5),int(nc/5)]+=1
test=of.reshape(-1,round(row/5)*round(col/5)).astype(np.float32)
#调用函数识别
knn=cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE, trainLabels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
print("当前随机数可以判定为类型:", result)
print("距离当前点最近的5个邻居是:", neighbours)
print("5个最近邻居的距离: ", dist)
结果:
当前随机数可以判定为类型: [[5.]]
距离当前点最近的5个邻居是: [[5. 3. 5. 3. 5.]]
5个最近邻居的距离: [[77185. 78375. 79073. 79948. 82151.]]