首页 > 编程语言 >《机器学习》——利用OpenCV库中的KNN算法进行图像识别

《机器学习》——利用OpenCV库中的KNN算法进行图像识别

时间:2024-12-27 21:57:59浏览次数:9  
标签:KNN test labels cv2 OpenCV train result 库中 np

文章目录

KNN算法介绍

  • 一、KNN算法的基本要素
    • K值的选择:K值代表选择与新测试样本距离最近的前K个训练样本数,通常K是不大于20的整数。K值的选择对算法结果有重要影响,需要通过交叉验证等方法来确定最优的K值。
    • 距离度量:常用的距离度量方式包括闵可夫斯基距离、欧氏距离、曼哈顿距离、切比雪夫距离、余弦距离等。其中,欧氏距离在KNN算法中最为常用。
    • 分类决策规则:一般采用多数投票法,即选择K个最相似数据中出现次数最多的类别作为新数据的分类。
  • 二、KNN算法的工作流程
    • 准备数据:对数据进行预处理,包括收集、清洗和归一化等步骤,以确保所有特征在计算距离时具有相等的权重。
    • 计算距离:计算测试样本点到训练集中每个样本点的距离。
    • 排序与选择:根据距离对样本点进行排序,并选择距离最小的K个样本点作为测试样本的邻居。
    • 分类决策:根据K个邻居的类别信息,采用多数投票法确定测试样本的类别。

下载OpenCV库

pip install opencv-python
# 后面可以加上指定版本,和镜像文件
#如:
pip install opencv-python==4.10.0.84
  • 调用包和其他包有所不同:
import cv2

实验内容

  • 实验目的
    • 通过OpenCV库中的KNN算法对数据进行分类,并验证。
  • 实验流程
    • 下面是一张已经经过一些初步处理过的图片,其中含有0~9的手写数字,且每一个数字都是5行,100列,共有5000个数字。
    • 本次通过对这张分辨率为2000*1000的图片进行切分。
    • 将其划分成独立的数字,每个数字大小为20*20像素,共计5000个;并平均切分为左右两个等份,一份作为训练集,一份作为测试集
    • 将训练集放到模型中训练后,再传入测试集进行测试,得到结果后,通过与正确结果比较得出准确率。
    • 最后自己手写一些数字,放入实验项目下,并处理后放入模型,测试出结果。
      在这里插入图片描述
  • 实验步骤
    • 1、获取数据
    • 2、处理数据
    • 3、分配标签
    • 4、模型构建和训练
    • 5、测试
    • 6、通过测试集校验准确率
  • 1.获取数据
    本实验数据已经提供了,只需要将图片拉入到项目目录中,再用以下代码进行读取:
# 通过opencv中的cv2.imread()方法进行读取:
img =cv2.imread('shu_zi.png')
  • 2.处理数据
    通常在实验项目中,获取数据和处理数据通常需要花费很长时间,在此实验中要进行一下数据处理:
    • 首先给的图片是一个黑底白字的图片,但是图片是一个三通道彩色图片,为了简化图像数据和计算量,故此我们要将图片转换成灰度图。
    • 再对图片进行切分,分别首先将切分成50份每一份20个像素值,再将切分过一次的数据进行一次对的切分,切分100份每一份20个像素值。
    • 将切分得到的数据转化成数组
    • 划分训练集测试集,对得到的数组进行划分,从中间一分为二,一份为训练集一份为测试集。
    • 训练集测试集中的数据构造为符合KNN的输入,将每个数字的尺寸由20*20调整为1*400。
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[:,:50]
test =x[:,50:100]

# 将数据构造为符合KNN的输入,将每个数字的尺寸由20*20调整为1*400
train_new = train.reshape(-1,400).astype(np.float32)
test_new = test.reshape(-1,400).astype(np.float32)

注意:.astype(np.float32): 是为了将reshape后的数组的数据类型转换为np.float32,即32位浮点数。这是因为在机器学习或深度学习中,通常会使用浮点数来表示特征或标签,而np.float32相比于64位浮点数(np.float64)可以节省内存,同时对于大多数应用来说,其精度已经足够。

  • 3.分配标签
    • 分别为训练集、测试集分配标签。
# 分配标签:分别为训练数据、测试数据分配标签
k = np.arange(10)
labels = np.repeat(k,250)
train_labels = labels[:,np.newaxis] # np.newaxis是numpy库中一个特殊对象用于增加一个新的维度
test_labels = np.repeat(k,250)[:,np.newaxis]

  • 4.模型构建和训练
# # # 构建+训练
knn =cv2.ml.KNearest_create() # 通过cv2创建一个knn模型
knn.train(train_new,cv2.ml.ROW_SAMPLE,train_labels)
# cv2.ml.ROW_SAMPLE是用来告诉模型,一行是一组数据,每一列是一个特征。
  • 5.测试
    • 传入训练集,并指定K的值,可以更改不同的K值来找到最佳的测试结果
# findNearest测试方法
ret,result,neighbours,dist=knn.findNearest(test_new,k=3)
# # ret:表示查找操作是否成功
# # result:浮点数数组,表示测试样本的预测标签
# # neighbours:这是一个整数数组,表示与测试样本最近的k个索引。
# # dist:这是一个浮点数组,表示测试样本与每一个最近邻居之间的距离。
  • 6、通过测试集校验准确率
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print("当前图片的准确率为:",accuracy)
  • matches = result == test_labels:这行代码通过比较result(KNN算法预测的结果)和test_labels(测试集的真实标签)来生成一个布尔数组matches。如果result中的某个预测值与test_labels中对应的真实标签相等,则matches中对应位置的值为True,否则为False。
  • correct = np.count_nonzero(matches):这行代码使用np.count_nonzero函数计算matches数组中True的数量,即正确预测的数量。np.count_nonzero函数会统计数组中所有非零元素(在这个场景下,即True)的数量。
  • accuracy = correct * 100.0 / result.size:这行代码计算准确率。首先,将正确预测的数量correct乘以100.0(为了得到百分比),然后除以result.size(即预测结果的总数,也就是测试集的大小)。这样得到的accuracy就是准确率,以百分比形式表示。
  • print(“当前使用KNN识别手写数字的准确率为:”, accuracy):最后,这行代码将计算得到的准确率打印出来。

实验结果

  • 打印准确率
    在这里插入图片描述

完整代码

import numpy as np
import cv2
img =cv2.imread('shu_zi.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[:,:50]
test =x[:,50:100]
# 将数据构造为符合KNN的输入,将每个数字的尺寸由20*20调整为1*400
train_new = train.reshape(-1,400).astype(np.float32)
test_new = test.reshape(-1,400).astype(np.float32)

# 分配标签:分别为训练数据、测试数据分配标签
k = np.arange(10)
labels = np.repeat(k,250)
train_labels = labels[:,np.newaxis] # np.newaxis是numpy库中一个特殊对象用于增加一个新的维度
test_labels = np.repeat(k,250)[:,np.newaxis]
knn =cv2.ml.KNearest_create() # 通过cv2创建一个knn模型
knn.train(train_new,cv2.ml.ROW_SAMPLE,train_labels)
ret,result,neighbours,dist=knn.findNearest(test_new,k=3)
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print("当前使用KNN识别手写数字的准确率为:",accuracy)

手写数字传入模型训练

  • 下图是通过电脑自带的画图工具,写出的三个数字,并且已经将大小调整为20*20像素大小的图片
    在这里插入图片描述
  • 将图片经过与实验中相同的处理方法,加以处理并传入到模型中进行测试
import numpy as np
import cv2
from numpy.ma.core import array
img = cv2.imread('shu_zi.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[:, :50]
train_new = train.reshape(-1, 400).astype(np.float32)
i = ('a2.png', 'a1.png', 'a3.png')
# wary = (1,3,9)
# for n in wary:
for w in i:
        a1 = cv2.imread(w)
        a2 = cv2.cvtColor(a1, cv2.COLOR_BGR2GRAY)
        a3 = a2.reshape(-1, 400).astype(np.float32)
        k = np.arange(10)
        labels = np.repeat(k, 250)
        train_labels = labels[:, np.newaxis]  # np.newaxis是numpy库中一个特殊对象用于增加一个新的维度
        knn = cv2.ml.KNearest_create()  # 通过cv2创建一个knn模
        knn.train(train_new, cv2.ml.ROW_SAMPLE, train_labels)
        ret, result, neighbours, dist = knn.findNearest(a3, k=3)

        matches = result ==int(input('请输入猜测的数字:'))
        correct = np.count_nonzero(matches)
        accuracy = correct * 100.0 / result.size
        print(f"当前使用KNN识别手写数字{w}的准确率为:", accuracy)
  • 结果:
    在这里插入图片描述

  • 由此可以看出,此次实验的模型还是相对比较准确的

标签:KNN,test,labels,cv2,OpenCV,train,result,库中,np
From: https://blog.csdn.net/lou0720/article/details/144776634

相关文章

  • 《机器学习》KNN算法实现手写数字识别
    目录 一、项目介绍二、数据集介绍三、需要解决的问题四、代码实际展示代码展示实验结果五、使用自己的数据进行测试代码展示结果展示六、总结 一、项目介绍通过对一张2000*1000像素写满0-9手写数字的图片进行处理。分割出训练集和测试集使用KNN算法进行训练并......
  • C#调用C++代码,以OpenCV为例
    前言使用C#调用C++代码是一个很常见的需求,因此本文以知名的C++机器视觉库OpenCV为例,说明在C#中如何通过使用P/Invoke(平台调用)来调用C++代码。只是以OpenCV为例,实际上在C#中使用OpenCV可以使用OpenCVSharp这个项目,这是一个很优秀的项目,GitHub地址:https://github.com/shimat/opencv......
  • OpenCV 入门
    OpenCV_Python入门创建/显示窗口方法说明参数返回namedWindow创建一个窗口窗口名称,WINDOW_NORMAL(窗口属性)resizeWindow设置窗口大小窗口名称,宽,高imshow显示窗口窗口名称,要显示的图像destroyAllWindows关闭所有窗口waitKey延时监听键盘按下0无限/单位毫秒键盘按下......
  • OpenCV-Python实战(7)——阈值处理
    一、cv2.threshold()res,dst=cv2.threshold(src=*,thresh=*,maxval=*,type=*) res:函数返回的阈值。dst:阈值处理后的函数。src:要处理的图像。thresh:阈值。maxval:设定像素最大值。type:阈值函数处理方法,常见方法如下表所示:方法值解释THRESH_BINARY0大于阈值取最大值,......
  • Git 从仓库中彻底删除文件或文件夹
    软件版本要求python3>=3.5git>=2.22.0如果git版本低,则需要安装新版本的git安装git-filter-repopython3-mpipinstallgit-filter-repo删除指定的文件或文件夹gitfilter-repo--pathdeploy--invert-paths这里删除的是deploy文件夹,请根据实际情况修改注意:命令执行......
  • GaussDB数据库中逻辑对象关系简析
    初次接触openGauss或GaussDB数据库的逻辑对象,被其中的表空间、数据库、schema和用户之间的关系,以及授权管理困惑住了,与熟悉的MySQL数据库的逻辑对象又有明显的不同。本文旨在简要梳理下GaussDB数据库逻辑对象之间的关系,以加深理解。1、GaussDB数据库逻辑对象1.1表空间、Databas......
  • LLVM技术在GaussDB等数据库中的应用
    万物互联的态势下,数据量的激增使得“如何提升数据处理性能”成为各家数据库共同面临的挑战。作为编译优化技术的代表,基于LLVM的CodeGen技术,能为每个查询生成定制的机器码替代原本的通用函数,减少实际查询时冗余的条件逻辑判断、虚函数调用并提高数据局域性,从而达到提升查询整体性能......
  • Opencv项目实战:25 车道线检测
    1、项目介绍本项目的主要目标是通过视频输入流实时检测并显示车道线。通过在GUI界面中集成OpenCV图像处理功能,用户可以加载视频,启动检测过程,并在窗口中查看每帧图像的处理结果。2、效果演示3、项目搭建文件夹videofiles放置视频检测文件,lane.ui为PyQt设计的ui文件,lane.py......
  • OpenCV计算机视觉 03 椒盐噪声的添加与常见的平滑处理方式(均值、方框、高斯、中值)
    上一篇文章:OpenCV计算机视觉02图片修改图像运算边缘填充阈值处理添加椒盐噪声defadd_peppersalt_noise(image,n=10000):  result=image.copy()  h,w=image.shape[:2]  #获取图片的高和宽  foriinrange(n):  #生成n个椒盐噪声  ......
  • 使用 OpenCV 绘制线条和矩形
    OpenCV是一个功能强大的计算机视觉库,它不仅提供了丰富的图像处理功能,还支持图像的绘制。绘制简单的几何图形(如线条和矩形)是OpenCV中常见的操作。在本篇文章中,我们将介绍如何使用OpenCV在图像上绘制线条和矩形。绘制线条在OpenCV中,可以使用cv2.line()函数来绘制直线......