K近邻算法(K-NN),即给定一个已训练的数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,则判定该输入实例同属此类。
1. OpenCV K近邻模块的使用
接下来通过一个例子,观察K近邻算法在OpenCV中的使用方法:
In [ ]:
%matplotlib inline
import cv2
import numpy as np
import matplotlib.pyplot as plt
通过随机数,创建训练数据集:
In [ ]:
rand1 = np.random.randint(0, 80, (20, 2)).astype(np.float32)
rand2 = np.random.randint(40, 100, (20, 2)).astype(np.float32)
train_data = np.vstack((rand1, rand2))
创建训练集结果:
In [ ]:
r1_label = np.zeros((20, 1)).astype(np.float32)
r2_label = np.ones((20, 1)).astype(np.float32)
td_label = np.vstack((r1_label, r2_label))
绘制训练集数据集和测试数据集:
In [ ]:
g = train_data[td_label.ravel() == 0]
b = train_data[td_label.ravel() == 1]
plt.scatter(g[:, 0], g[:, 1], 80, "g", "o")
plt.scatter(b[:, 0], b[:, 1], 80, "b", "s")
test = np.random.randint(0, 100, (1, 2)).astype(np.float32)
plt.scatter(test[:, 0], test[:, 1], 80, "r", "*")
plt.show()
训练K近邻算法:
In [ ]:
knn = cv2.ml.KNearest_create()
knn.train(train_data, cv2.ml.ROW_SAMPLE, td_label)
预测测试数据结果并打印结果:
In [ ]:
ret, results, neighbours, dist = knn.findNearest(test, 5)
print("当前随机可以判断的类型:", results[0][0])
print("距离最近的5个邻居是:", neighbours)
print("5个邻居的距离是:", dist)
2. K近邻图像匹配
KNN可以用做相似图像匹配算法来识别两个图像之间相似的内容。
本例中使用的例图如下:
图1
图2
代码实现如下:
In [ ]:
%matplotlib inline
import cv2
import matplotlib.pyplot as plt
按照灰度图像读入两张图片:
In [ ]:
img1 = cv2.imread("./emoji.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("./emoji2.jpg", cv2.IMREAD_GRAYSCALE)
检测关键点和特征描述:
- keypoint 是关键点的列表
- desc 检测到的特征的局部图的列表
In [ ]:
# 获取特征提取器对象
orb = cv2.ORB_create()
keypoint1, desc1 = orb.detectAndCompute(img1, None)
keypoint2, desc2 = orb.detectAndCompute(img2, None)
获得knn检测器:
- knn匹配可以返回k个最佳的匹配项
- bf返回所有的匹配项
In [ ]:
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.knnMatch(desc1, desc2, k=1)
绘制匹配结果:
In [ ]:
img3 = cv2.drawMatchesKnn(img1, keypoint1, img2, keypoint2, matches, img2, flags=2)
plt.imshow(img3)
plt.show()