KNN(K-Nearest Neighbors,K最近邻)算法是一种简单而有效的分类算法,也可以用于图像识别。它的基本思想是通过计算样本之间的距离,将待分类的样本归为其在训练集中最相近的K个样本所属的类别中最常见的类别
[1. 准备工作](#1. 准备工作)
[2. 图像预处理](#2. 图像预处理)
[3. 数据处理与分割](#3. 数据处理与分割)
[4. 标签准备](#4. 标签准备)
[5. 训练与测试KNN模型](#5. 训练与测试KNN模型)
1. 准备工作
首先,我们需要一个图像数据集。
以此图像为例
该图像应当包含一个50x100的网格,每个单元格中包含一个手写数字(0-9),所以总共有5000个数字样本如何将数据样本提取出来呢。
2. 图像预处理
我们将图像加载为灰度图像并进行分割:
python
import numpy as np
import cv2
img = cv2.imread('图片位置')#读取图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #图像灰度化
cells = [np.hsplit(row, 100) for row in np.vsplit(gray, 50)]
# 将图像分割成50x100的网格
我们使用np.vsplit
将图像按行分割成50个部分,然后对每个部分使用np.hsplit
按列分割成100个单元格。这样,我们得到了一个包含5000个单元格的数组,每个单元格中包含一个手写数字的图像。在调试过程中可以看到已经分割成功
我们可以查看是如何保存的
3. 数据处理与分割
接下来,我们将图像数据整理成训练和测试数据:
python
x = np.array(cells)
train = x[:, :50]
test = x[:, 50:100]
# 将图像数据展平以适应KNN输入
train_new = train.reshape(-1, 400).astype(np.float32)
test_new = test.reshape(-1, 400).astype(np.float32)
这里,我们将每个数字图像展平成一个400维的向量(20x20的图像)。这些展平的向量作为KNN算法的输入特征
4. 标签准备
我们需要准备训练和测试标签,以便模型可以学习和评估:
python
k = np.arange(10)
labels = np.repeat(k, 250)
train_labels = labels[:, np.newaxis]
test_labels = np.repeat(k, 250)[:, np.newaxis]
在这里,np.repeat(k, 250)
生成了每个数字(0-9)出现250次的标签数组。每个训练和测试样本都有对应的标签。
5. 训练与测试KNN模型
我们使用OpenCV的KNN算法来训练和测试我们的模型:
python
knn = cv2.ml.KNearest_create()#创建训练
knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)#进行训练
ret, result, neighbours, dist = knn.findNearest(test_new, k=5)#设置k值
在这段代码中,我们创建了一个KNN模型,并用训练数据进行训练。之后,使用findNearest
方法来对测试数据进行预测
6.检验测试结果:
python
print(result2)
matches = result == test_labels
correct = np.count_nonzero(matches)
accuracy = correct * 100.0 / result.size
print(accuracy)
通过对比预测结果与实际标签,我们可以计算模型的准确率。准确率表示模型正确分类的测试样本占总测试样本的比例
7.我们可以输入自己的一些例子再来测试训练的如何。
我们输入的图片格式要和训练数据的图片大小相同
python
img2 = cv2.imread('你的图片位置')#读取图片
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)#图像灰度化
x2 = np.array(gray2)#只输入一个数据,所以可以直接处理
test2 =x2[:,:]
test2_new = test2.reshape(-1,400).astype(np.float32)
ret2, result2, neighbours2, dist2 = knn.findNearest(test2_new, k=5)#设置k值进行预测
print(result2)#输出结果
全代码
python
import numpy as np
import cv2
img = cv2.imread('图片位置')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.imread('你的图片位置')
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
cells = [np.hsplit(row, 100) for row in np.vsplit(gray, 50)]
x = np.array(cells)
x2 = np.array(gray2)
train = x[:, :50]
test = x[:, 50:100]
test2 =x2[:,:]
train_new = train.reshape(-1, 400).astype(np.float32)
test_new = test.reshape(-1, 400).astype(np.float32)
test2_new = test2.reshape(-1,400).astype(np.float32)
k = np.arange(10)
labels = np.repeat(k, 250)
train_labels = labels[:, np.newaxis]
test_labels = np.repeat(k, 250)[:, np.newaxis]
knn = cv2.ml.KNearest_create()
knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)
ret, result, neighbours, dist = knn.findNearest(test_new, k=5)
ret2, result2, neighbours2, dist2 = knn.findNearest(test2_new, k=11)
print(result2)
matches = result == test_labels
correct = np.count_nonzero(matches)
accuracy = correct * 100.0 / result.size
print(accuracy)
我们可以设置不同的k值来是预测结果更加精确
总结
通过以上步骤,我们使用OpenCV和KNN算法实现了一个简单的手写数字识别系统。尽管这个示例相对简单,但它展示了如何从数据预处理、模型训练到性能评估的完整流程。在实际应用中,我们可以进一步优化模型,尝试更多先进的算法,或使用更复杂的数据集以提升性能。