opencv - py_ml - py_knn k-最近邻算法

文章目录

  • 1.理解 k-最近邻算法
    • 目标
    • 理论
    • OpenCV 中的 kNN
    • 其他资源
  • 2.使用 kNN 对手写数据进行 OCR
    • 目标
    • 手写数字的 OCR
    • 英文字母的 OCR
    • 其他资源

1.理解 k-最近邻算法

目标

在本章中,我们将理解 k-最近邻算法 (kNN) 的概念。

理论

kNN 是监督学习中最简单的分类算法之一。其思想是在特征空间中搜索测试数据的最接近匹配项。我们将通过下图来研究它。
在这里插入图片描述

在图像中,有两个家庭:蓝色方块和红色三角形。我们将每个家庭称为。他们的房子显示在城镇地图上,我们称之为特征空间。您可以将特征空间视为所有数据投影的空间。例如,考虑一个 2D 坐标空间。每个数据都有两个特征,一个 x 坐标和一个 y 坐标。您可以在 2D 坐标空间中表示此数据,对吗?现在想象一下有三个特征,您将需要 3D 空间。现在考虑 N 个特征:您需要 N 维空间,对吗?这个 N 维空间是它的特征空间。在我们的图像中,您可以将其视为具有两个特征的 2D 情况。

现在考虑如果一个新成员进入城镇并创建一个新家,会发生什么,该新家显示为绿色圆圈。他应该被添加到其中一个蓝色或红色家庭(或)。我们将该过程称为分类。这个新成员究竟应该如何分类?既然我们在处理 kNN,让我们应用该算法。

一个简单的方法是检查谁是他的最近邻居。从图像中可以清楚地看出,他是红三角家族的成员。所以他被归类为红三角。这种方法简称为最近邻居分类,因为分类仅取决于最近邻居

但这种方法有一个问题!红三角可能是最近的邻居,但如果附近也有很多蓝色方块怎么办?那么蓝色方块在那个地方的强度比红三角更大,所以仅仅检查最近的一个是不够的。相反,我们可能想要检查一些k个最近的家庭。那么无论哪个家庭是其中的多数,新来的人都应该属于那个家庭。在我们的图像中,我们取 k=3,即考虑 3 个最近的邻居。新成员有两个红色邻居和一个蓝色邻居(有两个等距的蓝色邻居,但由于 k=3,我们只能取其中一个),因此他应该再次被添加到红色家族。但是如果我们取 k=7 呢?那么他有 5 个蓝色邻居和 2 个红色邻居,应该被添加到蓝色家族。结果将随着所选的 k 值而变化。请注意,如果 k 不是奇数,我们可能会得到平局,就像上面 k=4 的情况一样。我们会看到我们的新成员有 2 个红色邻居和 2 个蓝色邻居作为他的四个最近邻居,我们需要选择一种方法来打破平局以进行分类。因此重申一下,这种方法称为 k-最近邻居,因为分类取决于 k 个最近邻居

同样,在 kNN 中,我们确实在考虑 k 个邻居,但我们对所有邻居都给予同等重视,对吗?这合理吗?例如,以 k=4 的并列情况为例。我们可以看到,2 个红色邻居实际上比其他 2 个蓝色邻居更接近新成员,因此他更有资格加入红色家庭。我们如何从数学上解释这一点?我们根据每个邻居与新来者的距离赋予他们一些权重:那些离他较近的人获得更高的权重,而那些离他较远的人获得较低的权重。然后我们分别添加每个家庭的总权重,并将新来者归类为获得更高总权重的家庭的一部分。这称为修改的 kNN加权 kNN

那么你在这里看到的一些重要的东西是什么?

  • 因为我们必须检查新来者与所有现有房屋的距离以找到最近的邻居,所以你需要掌握镇上所有房屋的信息,对吗?如果有很多房屋和家庭,则需要大量内存,计算时间也会更长。
  • 几乎没有时间进行任何类型的“训练”或准备。我们的“学习”只涉及记忆(存储)数据,然后进行测试和分类。

现在让我们看看这个算法在 OpenCV 中的工作原理。

OpenCV 中的 kNN

我们将在这里做一个简单的例子,有两个家族(类),就像上面一样。然后在下一章中,我们将做一个更好的例子。

所以在这里,我们将红色家族标记为 Class-0(因此用 0 表示),将蓝色家族标记为 Class-1
(用 1 表示)。我们创建 25 个邻居或 25 个训练数据,并将它们中的每一个标记为 Class-0 或 Class-1 的一部分。
我们可以借助 NumPy 的随机数生成器来完成此操作。

然后我们可以借助 Matplotlib 绘制它。红色邻居显示为红色三角形,蓝色邻居显示为蓝色方块。

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt# Feature set containing (x,y) values of 25 known/training data 包含 25 个已知/训练数据的 (x,y) 值的特征集
trainData = np.random.randint(0,100,(25,2)).astype(np.float32)# Label each one either Red or Blue with numbers 0 and 1 用数字 0 和 1 将每个标签标记为红色或蓝色
responses = np.random.randint(0,2,(25,1)).astype(np.float32)# Take Red neighbours and plot them 找到红色邻居并绘制它们
red = trainData[responses.ravel()==0]
plt.scatter(red[:,0],red[:,1],80,'r','^')# Take Blue neighbours and plot them 找到蓝色邻居并绘制它们
blue = trainData[responses.ravel()==1]
plt.scatter(blue[:,0],blue[:,1],80,'b','s')plt.show()

您将获得类似于第一幅图像的图像。由于您使用的是随机数生成器,因此每次运行代码时,您都会获得不同的数据。

接下来启动 kNN 算法并传递 trainData 和 responses 来训练 kNN。(在底层,它构建了一个搜索树:有关此内容的更多信息,请参阅下面的其他资源部分。)

然后,我们将引入一个新来者,并在 OpenCV 中的 kNN 的帮助下将其归类为属于一个家庭。在运行 kNN 之前,我们需要了解一些有关测试数据(新来者的数据)的信息。我们的数据应该是一个浮点数组,大小为 n u m b e r o f t e s t d a t a × n u m b e r o f f e a t u r e s number \; of \; testdata \times number \; of \; features numberoftestdata×numberoffeatures。然后我们找到新来者的最近邻居。我们可以指定 k:我们想要多少个邻居。(这里我们使用了 3。)它返回:

  1. 根据我们之前看到的 kNN 理论给新来者的标签。如果您想要最近邻算法,只需指定 k=1。
  2. k-最近邻的标签。
  3. 新来者与每个最近邻居的相应距离。

让我们看看它是如何工作的。新来者用绿色标记。

newcomer = np.random.randint(0,100,(1,2)).astype(np.float32)
plt.scatter(newcomer[:,0],newcomer[:,1],80,'g','o')knn = cv.ml.KNearest_create()
knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
ret, results, neighbours ,dist = knn.findNearest(newcomer, 3)print( "result:  {}\n".format(results) )
print( "neighbours:  {}\n".format(neighbours) )
print( "distance:  {}\n".format(dist) )plt.show()

我得到了以下结果:

result:  [[ 1.]]
neighbours:  [[ 1.  1.  1.]]
distance:  [[ 53.  58.  61.]]

它说我们新来的人的 3 个最近的邻居都来自 Blue 家族。因此,他被标记为 Blue 家族的一部分。从下面的图中可以明显看出:

在这里插入图片描述
如果有多个新来者(测试数据),你可以直接以数组形式传递。相应的结果也是以数组形式获取的。

# 10 new-comers
newcomers = np.random.randint(0,100,(10,2)).astype(np.float32)
ret, results,neighbours,dist = knn.findNearest(newcomer, 3)
# The results also will contain 10 labels.

其他资源

  1. NPTEL 模式识别笔记,第 11 章
  2. 维基百科关于最近邻搜索的文章
  3. 维基百科关于 k-d 树的文章

2.使用 kNN 对手写数据进行 OCR

目标

在本章中:

  • 我们将使用我们在 kNN 方面的知识来构建一个基本的 OCR(光学字符识别)应用程序。
  • 我们将在 OpenCV 附带的数字和字母数据上尝试我们的应用程序。

手写数字的 OCR

我们的目标是构建一个可以读取手写数字的应用程序。为此,我们需要一些训练数据和一些测试数据。OpenCV 附带一个图像 digits.png(在文件夹 opencv/samples/data/ 中),其中包含 5000 个手写数字(每个数字 500 个)。每个数字都是一个 20x20 的图像。因此,我们的第一步是将此图像拆分成 5000 个不同的数字图像。然后,对于每个数字(20x20 图像),我们将其展平为一行,每行 400 个像素。这就是我们的特征集,即所有像素的强度值。这是我们可以创建的最简单的特征集。我们使用每个数字的前 250 个样本作为训练数据,将其他 250 个样本作为测试数据。所以让我们先准备好它们。

import numpy as np
import cv2 as cvimg = cv.imread('digits.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)# Now we split the image to 5000 cells, each 20x20 size 现在我们将图像分割成 5000 个单元格,每个单元格大小为 20x20
cells = [np.hsplit(row,100) for row in np.vsplit(gray,50)]# Make it into a Numpy array: its size will be (50,100,20,20)
x = np.array(cells)# Now we prepare the training data and test data
train = x[:,:50].reshape(-1,400).astype(np.float32) # Size = (2500,400)
test = x[:,50:100].reshape(-1,400).astype(np.float32) # Size = (2500,400)# Create labels for train and test data
k = np.arange(10)
train_labels = np.repeat(k,250)[:,np.newaxis]
test_labels = train_labels.copy()# Initiate kNN, train it on the training data, then test it with the test data with k=1
# 启动 kNN,在训练数据上进行训练,然后使用 k=1 的测试数据进行测试
knn = cv.ml.KNearest_create()
knn.train(train, cv.ml.ROW_SAMPLE, train_labels)
ret,result,neighbours,dist = knn.findNearest(test,k=5)# Now we check the accuracy of classification 现在我们检查分类的准确性
# For that, compare the result with test_labels and check which are wrong
# 为此,将结果与 test_labels 进行比较,检查哪些是错误的
matches = result==test_labels
correct = np.count_nonzero(matches)
accuracy = correct*100.0/result.size
print( accuracy )

因此,我们的基本 OCR 应用程序已准备就绪。此特定示例使我的准确率达到 91%。提高准确率的一个选项是添加更多数据进行训练,尤其是对于错误较多的数字。

与其每次启动应用程序时都查找这些训练数据,不如保存它,以便下次可以直接从文件中读取这些数据并开始分类。这可以借助一些 Numpy 函数(如 np.savetxt、np.savez、np.load 等)来完成。请查看 NumPy 文档了解更多详细信息。

# Save the data
np.savez('knn_data.npz',train=train, train_labels=train_labels)# Now load the data
with np.load('knn_data.npz') as data:print( data.files )train = data['train']train_labels = data['train_labels']

在我的系统中,它占用大约 4.4 MB 的内存。由于我们使用强度值(uint8 数据)作为特征,因此最好先将数据转换为 np.uint8,然后保存。在这种情况下,它仅占用 1.1 MB。然后在加载时,您可以转换回 float32。

英文字母的 OCR

接下来,我们将对英文字母进行同样的操作,但数据和特征集略有变化。在这里,OpenCV 附带了一个数据文件 letter-recognition.data,而不是图像,位于 opencv/samples/cpp/ 文件夹中。如果打开它,您将看到 20000 行,乍一看,这些行可能看起来像垃圾。实际上,在每一行中,第一列是一个字母,它是我们的标签。接下来的 16 个数字是不同的特征。这些特征是从 UCI 机器学习
存储库 获得的。您可以在 此
页 中找到这些特征的详细信息。

有 20000 个样本可用,因此我们将前 10000 个样本作为训练样本,将剩余的10000 个样本作为测试样本。我们应该将字母更改为 ASCII 字符,因为我们无法直接处理字母。

import cv2 as cv
import numpy as np# Load the data and convert the letters to numbers
data= np.loadtxt('letter-recognition.data', dtype= 'float32', delimiter = ',',converters= {0: lambda ch: ord(ch)-ord('A')})# Split the dataset in two, with 10000 samples each for training and test sets
train, test = np.vsplit(data,2)# Split trainData and testData into features and responses
responses, trainData = np.hsplit(train,[1])
labels, testData = np.hsplit(test,[1])# Initiate the kNN, classify, measure accuracy
knn = cv.ml.KNearest_create()
knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
ret, result, neighbours, dist = knn.findNearest(testData, k=5)correct = np.count_nonzero(result == labels)
accuracy = correct*100.0/10000
print( accuracy )

它给了我 93.22% 的准确率。同样,如果你想提高准确率,你可以迭代地添加更多数据。

其他资源

  1. 维基百科关于光学字符识别的文章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/56584.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【js逆向专题】12.RPC技术

目录 一. websocket1. 什么是websocket2. websocket的原理3. websocket实现方式1. 客户端2.服务端3. 实际案例1. 案例目标2. 解析思路 二. RPC1. RPC 简介2.Sekiro-RPC1. 使用方法1. 执行方式2.客户端环境3.使用参数说明 2. 测试使用1. 前端代码2. SK API3.python调用代码 三.项…

C++,STL 042(24.10.21)

内容 一道练习题。 (涉及list,sort) 题目(大致) 将Person自定义类型进行排序(Person中属性有姓名、年龄、身高),按照年龄进行升序,如果年龄相同则按照身高进行降序。 …

openpnp - 解决“底部相机高级校正成功后, 开机归零时,吸嘴自动校验失败的问题“

文章目录 openpnp - 解决"底部相机高级校正成功后, 开机归零时,吸嘴自动校验失败的问题"概述笔记问题现象1问题现象2原因分析现在底部相机和吸嘴的位置偏差记录修正底部相机位置现在再看看NT1在底部相机中的位置开机归零,看看是否能通过所有校…

HarmonyOS鸿蒙- 一行代码自动换行技巧

DevEco Studio 编辑器设置 一行代码自动换行显示。 一、代码自动换行设置方式路径:File > Editor > General 如图: 二、找到标题:Soft Wraps 勾选《Soft-wrap these files:》,然后在后面添加*.ets 然后保存即可。添加后&#xff0c…

LangSplat和3D language fields简略介绍

LangSplat: 3D Language Gaussian Splatting 相关技术拆分解释: 3dgs:伟大无需多言SAM:The Segment Anything Model,是图像分割领域的foundational model,已经用在很多视觉任务上(如图像修复、物体追踪、图…

支持国密算法的数字证书-国密SSL证书详解

在互联网中,数字证书作为标志通讯各方身份信息的数字认证而存在,常见的数字证书大都采用国际算法,比如RSA算法、ECC算法、SHA2算法等。随着我国加强网络安全技术自主可控的大趋势,也出现了支持国密算法的数字证书-国密SSL证书。那…

软件设计师:软件工程

文章目录 一、开发模型(1)瀑布模型(需求明确)(2)增量模型(快速构建)(3)演化模型(迭代模型)(3.1)原型模型&…

【Docker】docker | 部署nginx

一、概述 记录下nginx的部署流程;将conf配置文件映射到宿主机 前提依赖:自行准备nginx的镜像包 二、步骤 1、运行、无映射 docker run --name nginx -p 80:80 -d nginx:1.18.0-alpine 80:80,前面是宿主机端口;如果冲…

IPsec简单介绍

VPN相关介绍 VPN:虚拟私有网络 例如:像这种不加密的 PPTPL2TP ------- 一般用在windows server 服务端(但是大多数企业不用这个) 假如总公司内部的PC1要去访问分公司内部的PC2(一般用在公司服务器有内网的服务&#…

Oracle 使用位图索引 Cost降低200倍! 探讨位图索引的利与弊

一.简介 位图索引(Bitmap Index) 是 Oracle 数据库中一种特殊类型的索引,适用于低基数(Low Cardinality)列,即那些列中可选值相对较少的情况下使用。它与常规的 B-tree 索引不同,位图索引通过位…

003:无人机概述

摘要:本文介绍无人机的定义和分类、无人机系统定义、民用无人机驾驶员分类和应用领域。 一、无人机的定义和分类 1.无人机定义 无人机是一种能够在无人驾驶的条件下完成复杂空中飞行任务和各种负载任务的飞行器,可以被视为“空中机器人”。它利用先进的…

(48)MATLAB使用firls函数设计均衡器

文章目录 前言一、频域均衡器的设计二、MATLAB源代码1.firls函数与freqz函数2.MATLAB仿真源代码3.代码说明 三、仿真结果画图 前言 利用MATLAB的firls函数,根据所要求的频率向量和频响幅度向量,设计出所需的均衡器,使得包括滤波器在内的系统…

qt 构建、执行qmake、运行、重新构建、清除

qt右键功能有 构建、执行qmake、运行、重新构建、清除,下面简单介绍一下各个模块的作用。 1. 执行qmake qmake是一个工具, 它根据pro文件生成makefile文件,而makefile文件中则定义编译与连接的规则。pro文件中定义了头文件,源文件…

Spring Cache Caffeine 高性能缓存库

​ Caffeine 背景 Caffeine是一个高性能的Java缓存库,它基于Guava Cache进行了增强,提供了更加出色的缓存体验。Caffeine的主要特点包括: 高性能:Caffeine使用了Java 8最新的StampedLock乐观锁技术,极大地提高了缓存…

k8s部署使用有状态服务statefulset部署eureka集群,需登录认证

一、构建eureka集群镜像 1、编写dockerfile文件,此处基础镜像为arm版本,eureka目录中文件内容:application-dev.yml、Dockerfile、eureka-server-1.0-SNAPSHOT.jar(添加登录认证模块,文章最后附上下载连接) FROM mdsol/java8-j…

Go使用exec.Command() 执行脚本时出现:file or directory not found

使用 Go 提供的 exec.Command() 执行脚本时出现了未找到脚本的 bug,三个排查思路 : exec.Command(execName, args…) 脚本名字不允许相对路径 exec.Command(execName, args…) execName 只能有脚本名,不允许出现参数 如果你是使用 Windows …

为什么要使用网络IO内存数据库?

1.摘要 学习Redis的时候,我有个疑问:Redis缓存是内存数据库,但是它部署在独立的一个服务器上,那么应用服务器访问redis不是要通过网络吗,那么是不是还不如从本地服务器读取数据库的效率 ?结论是&#xff1a…

[图像处理] 基于CleanVision库清洗图像数据集

CleanVision是一个开源的Python库,旨在帮助用户自动检测图像数据集中可能影响机器学习项目的常见问题。该库被设计为计算机视觉项目的初步工具,以便在应用机器学习之前发现并解决数据集中的问题。CleanVision的核心功能包括检测完全重复、近似重复、模糊…

ML 系列:机器学习和深度学习的深层次总结(17)从样本空间到概率规则概率

一、说明 概率是支撑大部分统计分析的基本概念。从本质上讲,概率提供了一个框架,用于量化不确定性并对未来事件做出明智的预测。无论您是在掷骰子、预测天气还是评估金融市场的风险,概率都是帮助您驾驭不确定性的工具。本篇将讲授概率的原理和…

论文阅读:Guided Linear Upsampling

今天介绍一篇有趣的文章,Guided Linear Upsampling,基于引导的线性上采样,这是发表在 ACM transaction on Graphic 的一篇工作。 Abstract 引导上采样是加速高分辨率图像处理的一种有效方法。在本文中,文章作者提出了一种简单而…