KNN算法实现图片的识别
1、将5000份手写数字 切分出来,[00....200,...]1*400的数据,直接当作是数字的特征 将数据切分成训练集和测试集
2、数据展开成400列 [00....200,...] 0 [00....100,...] 2 [00....220,...] 3
3、添加y
4、knn算法训练
5、模型的好坏。
import numpy as np
import cv2 #3.1本身就自了机器学习的函数img = cv2.imread('digits.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度图
# 将原始图像分割成独立的数字,每个数字大小20*20,共15000个
# a = np.vsplit(gray,50)
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]#按照顺序来看代码,python列表
# 转成array,形状(50,100,20,20),50行,100列,每个图像20*20大小
x = np.array(cells)train = x[:, :50]# 划分为训练集和测试集,比例各占一半
test = x[:,50:100]# 将数据构造为符合KNN的输入,将每个数字的尺寸由20*20调整为1*400(一行*400个像素)
train_new = train.reshape(-1,400).astype(np.float32) # Size = (2500,400)
test_new = test.reshape(-1,400).astype(np.float32) # Size = (2500,400)# 分配标签,分别为训练数据、测试数据分配标签(图像对应的实际值)
k = np.arange(10)#0123456789
labels = np.repeat(k,250)#repeat重复数组中的元素,每个元素重复250次
train_labels = labels[:,np.newaxis]#np.newaxis是NumPy中的一个特殊对象,用于在数组中增加一个新的维度。
test_labels = np.repeat(k,250)[:,np.newaxis]# 模型构建+训练,sklearn knn... opencv里面也有knn
knn = cv2.ml.KNearest_create()#创建cv2的k-NN模型
knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)#cv2.ml.ROW_SAMPLE: 这是一个标志,告诉OpenCV训练数据是按行组织的,即每一行是一个样本。
ret,result,neighbours,dist = knn.findNearest(test_new,k=3) #knn.predict()
# ret: 表示查找操作是否成功。
# result: 浮点数组,表示测试样本的预测标签。
# neighbours: 这是一个整数数组,表示与测试样本最近的k个邻居的索引。这些索引对应于训练集中的样本,可以用来检查哪些训练样本对预测结果产生了影响。
# dist: 这是一个浮点数组,表示测试样本与每个最近邻居之间的距离。这些距离可以帮助理解预测结果的置信度;距离越近,预测通常越可靠。# 通过测试集校验准确率
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print("当前使用KNN识别手写数字的准确率为:%",format(accuracy))# #1、输入1张图片,得到这张图片的数字是几?
# #2、改成sklearn库来实现,突破性的功能。
一·读取数据然后转化为矩阵
img = cv2.imread('digits.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度图
在调试中可以看到这是一个1000*2000的矩阵
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]#按照顺序来看代码,python列表
# 转成array,形状(50,100,20,20),50行,100列,每个图像20*20大小
x = np.array(cells)
np.vsplit(gray, 50)
:将名为gray
的原始图像沿着垂直方向(vertical)分割成 50 个等大的子图像(行)- 然后对分割得到的每一行
row
,使用np.hsplit(row, 100)
沿着水平方向(horizontal)分割成 100 个等大的子图像(列) - 最终得到一个列表
cells
,结构是 50 行 100 列的二维列表,每个元素都是一个小型图像
train = x[:, :50]# 划分为训练集和测试集,比例各占一半
test = x[:,50:100]
二·展开
train_new = train.reshape(-1,400).astype(np.float32) # Size = (2500,400)
test_new = test.reshape(-1,400).astype(np.float32) # Size = (2500,400)
这两行代码将训练集`train`和测试集`test`重塑为二维数组(形状均为(2500, 400)),并转为32位浮点数类型。 - `reshape(-1, 400)`:自动计算行数(此处为2500),将每个20×20的图像展平为400个特征的一维向量。 - `astype(np.float32)`:适配模型对输入数据类型的要求,节省内存并提升计算效率。
三·添加结果Y
k = np.arange(10)#0123456789
labels = np.repeat(k,250)#repeat重复数组中的元素,每个元素重复250次
train_labels = labels[:,np.newaxis]#np.newaxis是NumPy中的一个特殊对象,用于在数组中增加一个新的维度。
test_labels = np.repeat(k,250)[:,np.newaxis]
1. `k = np.arange(10)`:生成数组`[0,1,2,3,4,5,6,7,8,9]`,共10个元素。 2. `labels = np.repeat(k,250)`:将`k`中每个元素重复250次,生成长度为2500的一维数组,元素顺序为0重复250次、1重复250次……9重复250次。 3. `train_labels = labels[:,np.newaxis]`:给`labels`增加一个新维度,从(2500,)变为(2500,1)的二维数组,用于符合训练数据的标签格式。 4. `test_labels = np.repeat(k,250)[:,np.newaxis]`:生成与`train_labels`结构相同的测试标签数组,形状为(2500,1)。 整体功能:创建结构一致的训练和测试标签,每个数字0-9各出现250次,且均为二维列向量形式。
四·knn算法训练
# 模型构建+训练,sklearn knn... opencv里面也有knn
knn = cv2.ml.KNearest_create()#创建cv2的k-NN模型
knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)#cv2.ml.ROW_SAMPLE: 这是一个标志,告诉OpenCV训练数据是按行组织的,即每一行是一个样本。
ret,result,neighbours,dist = knn.findNearest(test_new,k=3) #knn.predict()
# ret: 表示查找操作是否成功。
# result: 浮点数组,表示测试样本的预测标签。
# neighbours: 这是一个整数数组,表示与测试样本最近的k个邻居的索引。这些索引对应于训练集中的样本,可以用来检查哪些训练样本对预测结果产生了影响。
# dist: 这是一个浮点数组,表示测试样本与每个最近邻居之间的距离。这些距离可以帮助理解预测结果的置信度;距离越近,预测通常越可靠。
1. 创建模型:`knn = cv2.ml.KNearest_create()` 初始化KNN实例 2. 训练:`knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)` - 按行组织样本(每行一个样本) - 用训练数据和标签构建模型 3. 预测:`knn.findNearest(test_new, k=3)` - 返回四要素:操作状态(ret)、预测结果(result)、近邻索引(neighbours)、距离(dist) - k=3指定参考3个最近邻 核心:OpenCV的KNN通过存储训练样本,预测时计算待测样本与最近k个样本的距离,按多数原则分类。
五·模型的好坏
# 通过测试集校验准确率
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print("当前使用KNN识别手写数字的准确率为:%",format(accuracy))
这段代码用于计算KNN模型的预测准确率:
1. `matches = result == test_labels`:对比预测结果与真实标签,得到布尔数组(True表示预测正确)
2. `correct = np.count_nonzero(matches)`:统计正确预测的数量
3. `accuracy = correct * 100.0 / result.size`:计算准确率(正确数/总样本数×100%)
4. 打印准确率结果 核心逻辑:通过对比预测值与真实值,统计正确比例来评估模型性能。