《机器学习》KNN算法搭配OpenCV训练模型、识别图片 No.2

目录

一、使用KNN算法识别数字

1、明确目的:

2、获取数据

3、明确操作流程

3.1 什么是灰度图

3.2 ret、result、neighbours、dist 解析

4、代码实现

4.1 导包

4.2 完整代码如下:

二、手写数字进行识别

1、在画图板中手绘数字

2、实操代码


一、使用KNN算法识别数字

1、明确目的:

        有一张图片,其中有一份数据,其中共有0-9的不同写法的数字,共5000条,现在想要对这张图片中的数据进行训练,以完成当输入一张图片,图片内为手写的数字,能自动识别其数字的值为多少,从而完成训练。

2、获取数据

首先看下面一张图:

它的像素点为1000 x 2000,其中长有100个数据。宽有50个数据,共5000个数据 

可能你看不清楚什么样的,那么不妨方法一下,其竖直方向排布如下:

  

3、明确操作流程

        首先导入这张图片,将这张图片转换成灰度图(3.1解析灰度图),然后将这张图片中的每个数字提取出来,这张图片中的每个数字都是由20x20=400个像素点组成,将这每一个单独的数字存放的列表中,然后将列表使用np.reshape()函数转换成二维数组的形式,以便于后面的切分操作。

        对存放所有数据的二维数组进行切分,前一半当做训练集后一半当做测试集,这张图中0-9对应的每个数字都为5行100列,成上下排布,我们只对列作切半处理,不对行进行切分,由此来得到训练集和测试集的数据,但是这个数据还不能直接拿来训练,还需要将每单个数字中的20x20的像素点转变成一行,此时可以使用np.reshape()将其转变成1x400像素值的状态,以便于对其进行训练和测试。

        接下来有了训练集和测试集,但是却没有标签集,此时可以生成一个0-9的数组,然后因为训练集中每个单个数据都有250个,即一共2500个,那么就要设置2500个标签用来对应这2500个数字,即可以使用np.repeat()来将0-9每个数字都复制250遍,然后再使用np.newaxis将这个一维数组生高成二维数组,以满足和训练集同样的维度。

        最后就是开始训练数据了,这里使用OpenCV中的包cv2.ml的方法KNearest_Create() 创建一个knn算法的分类器对象,并对其进行初始化,然后导入训练集以及训练标签,并使用cv2.ml.ROW_SAMPLE表示对每一行数据进行训练,接下来就是导入数据进行测试,使用knn.finNearest()导入数据并指定邻居个数,返回四个值ret、result、neighbours、dist,其解释在下列3.2。此时即完成全流程的解说。

3.1 什么是灰度图

        灰度图是一种图像的表示方式,相比于彩色图像,灰度图仅包含一个灰度通道,即每个像素只有一个灰度级灰度级通常用一个8位整数表示,范围从0(黑色)到255(白色)表示不同的亮度值

        在灰度图中,每个像素表示图像中某一点的亮度级别。亮度级别越,该点在图像中就越;亮度级别越,该点在图像中就越。因此,灰度图能够表示图像的明暗程度

        灰度图常用于图像处理领域和计算机视觉任务中。通过对灰度图进行处理,可以实现诸如图像增强、边缘检测、目标检测、人脸识别等功能。例如,对于目标检测任务,可以将灰度图作为输入,通过检测明暗程度变化或者轮廓来识别目标物体。

        为了生成灰度图,可以将彩色图像转换为灰度图。一种常见的方法是使用加权平均法,根据红色、绿色和蓝色通道的亮度对应比例,计算出每个像素的灰度值。另外,还可以使用其他方法,如取最大值、取最小值等来生成灰度图。例如可以使用OpenCV中的方法:

import cv2

# 读取彩色图像
image = cv2.imread('color_image.jpg')

# 转换为灰度图
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 显示灰度图
cv2.imshow('Gray Image', gray_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

         在以上代码中,首先使用cv2.imread()函数读取彩色图像,将图像保存在image变量中。然后,使用cv2.cvtColor()函数将彩色图像转换为灰度图,将灰度图保存在gray_image变量中。最后,使用cv2.imshow()函数显示灰度图窗口,并通过cv2.waitKey()和cv2.destroyAllWindows()函数等待关闭窗口。

        注意,cv2.COLOR_BGR2GRAY参数表示将BGR格式的图像转换为灰度图。如果你的图像不是BGR格式,你可能需要根据实际情况选择不同的颜色空间转换函数。

3.2 ret、result、neighbours、dist 解析
  • ret: 返回值,表示操作是否成功(通常是 0 表示成功)。
  • result: 每个测试样本的预测标签。是对 test_new 中每一行数据的预测结果。
  • neighbours: 最近邻的标签的矩阵,表示每个测试样本的最近 K 个邻居的标签。
  • dist: 最近邻的距离矩阵,表示每个测试样本到其最近 K 个邻居的距离。

4、代码实现

4.1 导包
#后面等于号为指定版本号,防止和有些包使用发生冲突
pip install opencv_python==3.4.17.61
4.2 完整代码如下:
import numpy as np
import cv2

# 导入图片
img = cv2.imread('digits.png')
# 将图片转化成灰度图
grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 将这个图片中的每一个数字分隔出来然后插入列表
cells = []
for row in np.vsplit(grey,50):
    cells.append(np.hsplit(row,100))

# 将列表数据转化成矩阵类型
x = np.array(cells)

# 取前一半数据当做训练集,后一半数据当做测试集
# 取出矩阵x的行列,行为所有的行,列为0到50列,但是不包含第50列,当做训练集
train = x[:,:50]
# 即所有的行,以及后50列
test = x[:,50:100]

# 将每一个数字数据的像素点由20x20像素的转换成1*400像素的,即转换成一行像素点数据
# -1为自动判断样本数
train_new = train.reshape(-1,400).astype(np.float32)
test_new = test.reshape(-1,400).astype(np.float32)

# 定义标签列,便签值为0~9,将其生成一个0-9的数组
y = np.arange(10)
# 将0-9的一维数组中的每个元素复制250次得到一个新的一维数组,其内有10x250个数据
labels = np.repeat(y,250)
# 将上述充满0-9数字的2500条数据的一维数组,增加其维度到二维数组,即每单个值为一个一维数组
train_label = labels[:,np.newaxis]
test_label = np.repeat(y,250)[:,np.newaxis]

# 使用OpenCV中的包cv2.ml的用法KNearest_create创建一个knn分类器对象,用于初始化模型
knn = cv2.ml.KNearest_create()
# cv2.ml.ROW_SAMPLE表示每一行的数据,即导入train_new的每一行数据用来训练,同时插入标签列train_label
knn.train(train_new,cv2.ml.ROW_SAMPLE,train_label)

# 导入测试数据进行测试,并指定最近邻的个数为5,其返回值为ret:表示测试的正确性,正确返回1,错误返回0,result返回测试结果,
# neighbors 表示最近邻的标签的矩阵,表示每个测试样本的最近k个邻居的标签
# dist 表示每个测试样本到其最近k个令居的距离
ret,result,neighbours,dist = knn.findNearest(test_new,k=5)
print(result)

# 判断语句,判断测试结果是否与测试数据的标签相等,返回true或false
maches = result==test_label
# 统计非空数据的和,表示判断为1的个数
count = np.count_nonzero(maches)
# 计算正确率,即为1的个数除以测试结果的总条数
person = count*100/len(result)
print(person)

二、手写数字进行识别

1、在画图板中手绘数字

如下图所示流程:

2、实操代码

import numpy as np
import cv2

img = cv2.imread('digits.png') # 导入图片数据
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转变为灰度图

cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)] #将 每个数字都存放到列表中

x = np.array(cells) # 将数据转换成矩阵类型

train = x[:,:] #将整个图片的数据当做训练集

train_new = train.reshape(-1,400).astype(np.float32) # 将每单个数据对应的像素点转变成一行的状态

k = np.arange(10)
labels = np.repeat(k,500)
train_labels = labels[:,np.newaxis]

knn = cv2.ml.KNearest_create()  # 创建一个knn分类器,并初始化模型
knn.train(train_new,cv2.ml.ROW_SAMPLE,train_labels) # 导入数据进行训练

testt = cv2.imread('4.png')   # 导入刚刚保存的图片
gray2 = cv2.cvtColor(testt,cv2.COLOR_BGR2GRAY) # 将图片转变成灰度图
x1 = np.array(gray2) # 将数据转变成矩阵类型
test_new1 = x1.reshape(-1,400).astype(np.float32)  # 将每个数据转变成单独的一行

ret,result,neighbours,dist = knn.findNearest(test_new1,k=3)  # 将数据输入进行测试
print(result)

测试结果为:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜就多练_0828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值