这里我们将红色家族标记为 Class-0,蓝色家族标记为 Class-1。还要再创建 25 个训练数据,把它们非别标记为 Class-0或者 Class-1。Numpy中随机数产生器可以帮助我们完成这个任务。
然后借助 Matplotlib 将这些点绘制出来。红色家族显示为红色三角蓝色家族显示为蓝色方块。
代码演示:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Feature set containing(x,y) values of 25 known/training data
trainData = np.random.randint(0,100,(25,2)).astype(np.float32)
# Labels each one either Red or Blue with numbers 0 and 1
responses = np.random.randint(0,2,(25,1)).astype(np.float32)
# Take Red families and plot them
red = trainData[responses.ravel()==0]
plt.scatter(red[:,0],red[:,1],80,'r','^')
# Take Bule families and plot them
blue = trainData[responses.ravel()==1]
plt.scatter(blue[:,0],blue[:,1],80,'b','s')
newcomers = np.random.randint(0,100,(1,2)).astype(np.float32)
plt.scatter(newcomer[:,0],newcomer[:,1],80,'g','o')
knn = cv2.ml.KNearest_create()
knn.train(trainData,cv2.ml.ROW_SAMPLE,responses)
ret,results,neighbours,dist = knn.findNearest(newcomer,3)
print ('result:{}'.format(results),'\n')
print ('neightbours:{}'.format(neighbours))
print ('distance:{}'.format(dist))
plt.show()
kNN 算法分类器的初始化,我们要传入一个训练数据集,以及与训练数据对应的分类来训练 kNN 分类器(构建搜索树)。
最后要使用 OpenCV 中的 kNN 分类器,我们给它一个测试数据,让它来进行分类。在使用 kNN 之前,我们应该对测试数据有所了解。我们的数据应该是大小为数据数目乘以特征数目的浮点性数组。然后我们就可以通过计算找到测试数据最近的邻居了。我们可以设置返回的最近邻居的数目。返回值包括:
下面是结果:
result:[[1.]]
neightbours:[[1. 1. 1.]]
distance:[[628. 697. 901.]]
OpenCV 安装包中有一副图片(digits.png), 其中有 5000 个手写数字(每个数字重复 500遍)。每个数字是一个 20x20 的小图。所以第一步就是将这个图像分割成 5000个不同的数字。我们在将拆分后的每一个数字的图像重排成一行含有400 个像素点的新图像。这个就是我们的特征集,所有像素的灰度值。这是我们能创建的最简单的特征集。我们使用每个数字的前 250 个样本做训练数据,剩余的250 个做测试数据。
代码演示:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('digits.png',0)
# Now we split the image to 5000 cells,each 20x20 size
cells = [np.hsplit(row,100) for row in np.vsplit(img,20)]
# Make it into a Numpy array It size will be(50,100,20,20)
x = np.array(cells)
# Now prepare train_data and test_data
train = x[:,:50].reshape(-1,400).astype(np.float32)# size = (2500,400)
test = x[:,50:100].reshape(-1,400).astype(np.float32)# size = (2500,400)
# Create labels for train and test data
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()
#Initiate Knn,train the data then test it with test data for k=1
knn = cv2.ml.KNearest_create()
knn.train(train,cv2.ml.ROW_SAMPLE,train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)
# Now we check the accuracy of classification
# For that ,compare the result with test_labels and check which are wrong
matches = result == test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100/result.size
print (accuracy)
85.28
为了避免每次运行程序都要准备和训练分类器,我们最好把它保留,这样在下次运行是时,只需要从文件中读取这些数据开始进行分类就可以了。Numpy 函数 np.savetxt,np.load 等可以帮助我们搞定这些。
# save the data
np.savez('knn_data.npz',train= train,train_labels=train_labels)
# Now load the data
with np.load('knn_data.npz') as data:
print (data.files)
train = data['train']
train_labels = data['train_labels']