OpenCV-Python官方教程-29- K 近邻(k-Nearest Neighbour)

  • kNN 可以说是最简单的监督学习分类器了。想法也很简单,就是找出测试数据在特征空间中的最近邻居。

1.1 Opencv中的kNN

这里我们将红色家族标记为 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 之前,我们应该对测试数据有所了解。我们的数据应该是大小为数据数目乘以特征数目的浮点性数组。然后我们就可以通过计算找到测试数据最近的邻居了。我们可以设置返回的最近邻居的数目。返回值包括:

  1. 由 kNN 算法计算得到的测试数据的类别标志(0 或 1)。如果你想使用最近邻算法,只需要将 k 设置为 1,k 就是最近邻的数目。
  2. k个最近邻居的类别标志。
  3. 每个最近邻居到测试数据的距离。

下面是结果:

result:[[1.]]
neightbours:[[1. 1. 1.]]
distance:[[628. 697. 901.]]

OpenCV-Python官方教程-29- K 近邻(k-Nearest Neighbour)_第1张图片

1.2 使用 kNN 对手写数字 OCR

OpenCV 安装包中有一副图片(digits.png), 其中有 5000 个手写数字(每个数字重复 500遍)。每个数字是一个 20x20 的小图。所以第一步就是将这个图像分割成 5000个不同的数字。我们在将拆分后的每一个数字的图像重排成一行含有400 个像素点的新图像。这个就是我们的特征集,所有像素的灰度值。这是我们能创建的最简单的特征集。我们使用每个数字的前 250 个样本做训练数据,剩余的250 个做测试数据。

digits.png:
OpenCV-Python官方教程-29- K 近邻(k-Nearest Neighbour)_第2张图片

代码演示:

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']

你可能感兴趣的:(kNN)