在OpenCV中,可以直接调用自带的模块函数。不需要再手动编写复杂的K邻近过程。本节介绍如何通过K邻近算法来确定一个坐标属于哪一组。本节介绍KNN的基本使用方法。
本文目录:
[TOC]
问题描述
有两组位于不同位置的用于训练的数据集,一组位于左小角,一组位于右上角,如下图所示。现随机生成一个数值,使用OpenCV中的K邻近模块判断该随机数属于哪一个分组。
问题分析
创建两组数据,每组包含20对随机数,一组X和Y的坐标值都在(0,30)范围内,另一组X和Y的坐标值都在(70,100)范围内。
将第一组随机数划分为类型0,标签为0;另一组随机数划分为类型1,标签为1。
再随机生成一个在(0,100)的随机数对。
最后使用K邻近模块判断生成的随机数是属于类型0还是类型1。
程序实现
import cv2
import numpy as np
import matplotlib.pyplot as plt
#用于训练的数据
#rand1数据位于(0,30)
rand1 = np.random.randint(0,30,(20,2)).astype(np.float32)
#rand2数据位于(70,100)
rand2 = np.random.randint(70,100,(20,2)).astype(np.float32)
#将rand1和rand2拼接为训练数据
trainData = np.vstack((rand1,rand2))
#数据标签,共两类:0和1
#r1Label对应着rand1的标签,为类型0
r1Label = np.zeros((20,1)).astype(np.float32)
#r2Label对应着rand2的标签,为类型1
r2Label = np.ones((20,1)).astype(np.float32)
tdLabel = np.vstack((r1Label,r2Label))
#使用绿色标注类型0
g = trainData[tdLabel.ravel()==0] #多维展平函数
plt.scatter(g[:,0],g[:,1],80,'g','o')
#使用蓝色标注类型1
b = trainData[tdLabel.ravel()==1] #多维展平函数
plt.scatter(b[:,0],b[:,1],80,'b','s')
# plt.show()
#生成一个随机数,该数值在0到100之间
test = np.random.randint(0,100,(1,2)).astype(np.float32)
plt.scatter(test[:,0],test[:,1],80,'r','*')
#调用OpenCV内的k邻近模块,并进行训练
knn = cv2.ml.KNearest_create() #创建KNN
knn.train(trainData,cv2.ml.ROW_SAMPLE,tdLabel)
#使用K邻近算法分类
ret,result,neighbours,dist = knn.findNearest(test,5)
#显示当前结果
print("随机数的坐标是:",test)
print('随机数判定的结果:',result)
print("距离当前最近的5个邻居点:",neighbours)
print("5个最近的邻居距离:",dist)
plt.show()
随机数的坐标是: [[10. 78.]]
随机数判定的结果: [[0.]]
距离当前最近的5个邻居点: [[0. 0. 0. 0. 0.]]
5个最近的邻居距离: [[2402. 2426. 2501. 2501. 2536.]]
知识补充:
1、np.vstack():按垂直方向(行顺序)堆叠数组构成一个新的数组,堆叠的数组需要具有相同的维度
2、ravel()多维数据展平函数
\>>> a = np.array([[1,2,3],[4,5,6]])
\>>> a
array([[1, 2, 3], [4, 5, 6]])
\>>> a.ravel()
array([1, 2, 3, 4, 5, 6])