基于 OpenCV 与 sklearn 的数字识别:KNN 算法实践

在计算机视觉领域,数字识别是一个经典问题,广泛应用于邮政编码识别、车牌识别等场景。本文将介绍如何使用 OpenCV 进行图像处理,并结合 KNN(K 近邻)算法实现数字识别,同时对比 OpenCV 内置 KNN 与 scikit-learn 库中 KNN 的实现差异。

准备工作

首先,我们需要导入所需的库:

import numpy as np
import cv2
from sklearn.neighbors import KNeighborsClassifier

其中,numpy用于数值计算,cv2(OpenCV)用于图像处理,KNeighborsClassifier则是 scikit-learn 库中的 KNN 分类器。

图像读取与预处理

我们需要读取两张图像:一张包含大量数字样本的训练图像,另一张作为测试图像。

# 读取训练图像和测试图像
img = cv2.imread(r'D:\pythonProject11\class\aa.png')
c_img = cv2.imread(r'D:\pythonProject11\class\ccc.png')# 将彩色图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
c_gray = cv2.cvtColor(c_img, cv2.COLOR_BGR2GRAY)

彩色图像包含 RGB 三个通道,转换为灰度图像可以减少计算量,同时保留图像的主要特征。cv2.cvtColor函数用于颜色空间转换,COLOR_BGR2GRAY参数表示从 BGR 格式(OpenCV 默认的彩色图像格式)转换为灰度格式。

数据准备

图像分割

我们假设训练图像是一个包含 50 行 100 列数字的网格图像,每个数字占据一个 20×20 像素的区域。我们需要将这个大图像分割成多个小图像,每个小图像对应一个数字样本。

python

运行

# 先垂直分割成50行,再对每行水平分割成100列
cell = np.array([np.hsplit(row, 100) for row in np.split(gray, 50)])

这里使用了np.splitnp.hsplit两个函数:

  • np.split(gray, 50)将灰度图像垂直分割成 50 个等高度的子数组
  • np.hsplit(row, 100)将每个子数组水平分割成 100 个等宽度的子数组

最终得到的cell是一个形状为 (50, 100, 20, 20) 的数组,表示 50 行 100 列,每个元素是 20×20 像素的数字图像。

训练集和测试集划分

我们将前 50 列作为训练集,后 50 列作为测试集:

python

运行

# 划分训练集和测试集
train_ma = cell[:, :50]  # 前50列作为训练集
test_ma = cell[:, 50:100]  # 后50列作为测试集# 转换为二维数组(样本数×特征数)
train_ma = train_ma.reshape(-1, 400).astype(np.float32)  # 50×50=2500个样本,每个样本20×20=400个特征
test_ma = test_ma.reshape(-1, 400).astype(np.float32)

reshape(-1, 400)将每个 20×20 的图像转换为一个长度为 400 的一维数组,便于作为机器学习算法的输入。-1表示自动计算该维度的大小,这里计算结果为 2500(50×50)。

标签生成

我们需要为每个样本生成对应的标签(即该样本对应的数字)。假设图像中的数字是按 0-9 的顺序重复排列的:

python

运行

# 生成标签
kernel = np.arange(10)  # 生成0-9的数字
train_la = np.repeat(kernel, 250)[:, np.newaxis]  # 每个数字重复250次,形成2500个标签
test_la = np.repeat(kernel, 250)[:, np.newaxis]

np.repeat(kernel, 250)将 0-9 每个数字重复 250 次,得到一个长度为 2500 的数组,与我们的样本数量一致。[:, np.newaxis]将一维数组转换为二维列向量,以满足 OpenCV 中 KNN 算法对标签格式的要求。

测试图像预处理

我们需要对测试图像进行同样的预处理:

python

运行

# 预处理测试图像
c_test = np.array(c_gray).reshape(-1, 400).astype(np.float32)

使用 OpenCV 的 KNN 进行识别

OpenCV 库中内置了 KNN 算法的实现:

python

运行

# 创建并训练OpenCV的KNN模型
knn = cv2.ml.KNearest_create()
knn.train(train_ma, cv2.ml.ROW_SAMPLE, train_la)  # ROW_SAMPLE表示每行是一个样本# 预测
ret, results, neigh, dist = knn.findNearest(c_test, 4)  # 寻找4个最近邻
print("OpenCV KNN预测结果:", results)

cv2.ml.KNearest_create()创建一个 KNN 模型实例,train方法用于训练模型,findNearest方法用于预测。findNearest的第二个参数表示要寻找的最近邻数量 K。

使用 scikit-learn 的 KNN 进行识别

我们也可以使用 scikit-learn 库中的 KNN 实现:

python

运行

# 为scikit-learn准备标签(一维数组)
train_la = np.repeat(kernel, 250)
test_la = np.repeat(kernel, 250)# 创建并训练scikit-learn的KNN模型
knnl = KNeighborsClassifier(n_neighbors=5)  # K=5
knnl.fit(train_ma, train_la)# 评估模型准确率
a = knnl.score(test_ma, test_la)
print("模型准确率:", a)# 预测
b = knnl.predict(c_test)
print("scikit-learn KNN预测结果:", b)

scikit-learn 的 KNN 使用起来更加简洁,KNeighborsClassifiern_neighbors参数指定 K 值,fit方法用于训练,score方法用于评估模型准确率,predict方法用于预测。

总代码

import numpy as np
import cv2
from sklearn.neighbors import KNeighborsClassifier
img = cv2.imread(r'D:\pythonProject11\class\aa.png')
c_img = cv2.imread(r'D:\pythonProject11\class\ccc.png')
# c_img = cv2.imread('img_1.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转化为灰度图像
c_gray = cv2.cvtColor(c_img,cv2.COLOR_BGR2GRAY)
c_test = np.array(c_gray).reshape(-1,400).astype(np.float32)cell =np.array([np.hsplit(row,100) for row innp.split(gray,50)])
train_ma = cell[:,:50]
test_ma = cell[:,50:100]
train_ma = train_ma.reshape(-1,400).astype(np.float32)
test_ma = test_ma.reshape(-1,400).astype(np.float32)
kernel = np.arange(10)
train_la = np.repeat(kernel,250)[:,np.newaxis]#cv2的方法
test_la = np.repeat(kernel,250)[:,np.newaxis]
knn = cv2.ml.KNearest_create()
knn.train(train_ma,cv2.ml.ROW_SAMPLE,train_la)#cv2.mL.ROW_SAMPLE:这是一个标志,告诉0pencv训练数据是按行组织的,即每一行是一个样本。
ret, results, neigh, dist = knn.findNearest(c_test,4)
print(results)
train_la = np.repeat(kernel,250)#sklearn的方法
test_la = np.repeat(kernel,250)
knnl = KNeighborsClassifier(n_neighbors=5)
knnl.fit(train_ma,train_la)
a=knnl.score(test_ma,test_la)
b=knnl.predict(c_test)
print(a,b)

两种实现的对比

  1. 接口设计:OpenCV 的 KNN 接口更偏向于计算机视觉领域的使用习惯,而 scikit-learn 的接口则更符合机器学习的通用范式。

  2. 输入格式:OpenCV 的 KNN 要求标签是列向量,而 scikit-learn 的 KNN 要求标签是一维数组。

  3. 功能:scikit-learn 的 KNN 提供了更多的评估方法和参数设置,而 OpenCV 的 KNN 则更轻量,与图像处理功能结合更紧密。

  4. 结果:在相同的 K 值设置下,两种实现的预测结果应该是相似的,但可能会因为具体实现细节的不同而略有差异。

总结

本文介绍了如何使用 OpenCV 进行图像预处理,以及如何使用 KNN 算法实现数字识别。通过对比 OpenCV 和 scikit-learn 中 KNN 的实现,我们可以看到不同库在接口设计和使用方式上的差异。

在实际应用中,我们可以根据具体需求选择合适的库和算法。如果需要处理图像并进行简单的分类,OpenCV 的 KNN 可能是一个不错的选择;如果需要更复杂的机器学习功能和更全面的评估方法,scikit-learn 则更为适合。

此外,KNN 算法虽然简单易懂,但在处理大规模数据集时效率较低。在实际应用中,我们可能需要考虑使用更高效的算法,如 SVM、神经网络等,以获得更好的性能。

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

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

相关文章

利用径向条形图探索华盛顿的徒步旅行

利用径向条形图探索华盛顿的徒步旅行 import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np import pandas as pdfrom matplotlib.cm import ScalarMappable from matplotlib.lines import Line2D from mpl_toolkits.axes_grid1.inset_locator impor…

火狐浏览器中国特供版关闭,如何下载 Firefox 国际版?如何备份数据?

火狐浏览器中国特供版关闭,如何下载 Firefox 国际版?如何备份数据?各位火狐老用户注意了!7 月 27 日北京谋智火狐正式发布公告:2025 年 9 月 29 日 24:00 起,中国特供版账户服务将彻底关闭,所有…

C语言操作符详解:从基础到进阶

在C语言中,操作符是构建表达式的基础,掌握各类操作符的用法、优先级及特性,对写出高效且正确的代码至关重要。本文将系统梳理C语言操作符的核心知识点,包含实例代码与详细解析,助你彻底搞懂操作符。 1. 操作符的分类 C…

鸿蒙平台运行Lua脚本

1. 目标 使用 rust 在移动端实现 Lua 脚本的运行。 2. 核心步骤 [Rust Host App]│├── [mLua VM] (通过 mlua 或 rlua 库嵌入)│ ├── 独立Lua状态(隔离执行)│ ├── 受限标准库(禁用危险函数)│ └── 内存/CPU限…

【Ubuntu】发展历程

Ubuntu 是一个基于 Debian 的 Linux 发行版,由 Canonical 公司开发和维护。它以其易用性、稳定性和强大的社区支持而著称。以下是 Ubuntu 从发布以来的主要版本和发展历程:1. Ubuntu 4.10 "Warty Warthog" (2004)发布日期:2004年10…

k8s下springboot-admin 监控服务部署,客户端接入

踩坑及解决以下问题 1、客户端监控信息不显示,需要暴露监控检查接口路径 2、服务端不显示客户端日志,需要启用日志,并指定日志路径 3、解决在k8s下,客户端多实例注册id相同,如2个实例只显示一个 整体架构 springboot-admin 由服务端和客户端组成 服务端负责 1、提供 We…

git删除远程分支和本地分支

1. git删除远程分支 git push origin --delete [branch_name]2. 删除本地分支 2.1 git branch -d 会在删除前检查merge状态(其与上游分支或者与head)。 git branch -d [branch_name] 2.2 git branch -D 直接删除 git branch -D 是 git branch --delete…

Go 的时间包:理解单调时间与挂钟时间

Go 的时间包:理解单调时间与挂钟时间 📅 引言 Go 语言自版本 1.9 起在 time.Time 中同时支持 “挂钟时间(wall‑clock)” 和 “单调时间(monotonic clock)”,用于分别满足时间戳与时间间隔测量…

Android启动时间优化大全

1 修改Android mksh默认的列长度 不修改这个参数,adb shell后,输入超过80个字符,就不能看到完整的命令行。external/mksh/src/sh.h EXTERN mksh_ari_t x_cols E_INIT(80); EXTERN mksh_ari_t x_lins E_INIT(24);2 Kernel优化 2.1 内核驱动模块…

matplotlib.pyplot: 底层原理简析与进阶技巧

文章目录 1 底层实现原理 1.1 核心架构 1.1 渲染流程 2 基础用法 2.1 基本绘图 2.2 多子图系统 2.3 高阶用法 2.3.1 自定义Artist对象 2.3.2 高级动画技术 2.3.3 事件处理系统 2.3.4 混合渲染技术 3 性能优化技巧 4 扩展模块 5 总结 5.1 底层原理关键点 5.2 进阶技巧 1 底层实现…

深入理解现代前端开发中的 <script type=“module“> 与构建工具实践

引言:模块化开发的演进在早期的前端开发中,JavaScript 缺乏原生的模块化支持,开发者不得不依赖 IIFE(立即调用函数表达式)或第三方库(如 RequireJS)来实现代码组织。随着 ES6(ES2015…

yolo--qt可视化开发

qt5可能不支持我们的cuda版本,改用qt6 YOLO11QT6OpencvC训练加载模型全过程讲解_yolov11 模型转换成opencv c模型-CSDN博客 下面是qt5版本的案例,和yolo及cuda有冲突 安装qt 切换到虚拟环境,例如pyqt,conda activate pyqt pip …

SQL性能优化

show [session|global] status : 查看服务器状态 show global status like Com_ : 查看各种语句的执行次数 开启慢查询: 在 MySQL 配置文件(/etc/my.cnf)配置: #开启MySQL慢日志查询开关 slow_query_log1 #设置慢日志的时间为2秒,SQL语句执…

ctfshow pwn40

目录 1. 分析程序 2. 漏洞编写 3. 漏洞验证 1. 分析程序 首先检查程序相关保护,发现程序为32位且只开启了一个NX保护 checksec pwn 使用IDA进行逆向分析代码,查看漏洞触发点: 在main函数中,有一个ctfshow函数,这里…

SQL173 店铺901国庆期间的7日动销率和滞销率

SQL173 店铺901国庆期间的7日动销率和滞销率 SQL题解:店铺动销率与滞销率计算 关键:只要当天任一店铺有任何商品的销量就输出该天的结果,即使店铺901当天的动销率为0。 潜台词:​输出逻辑与店铺901的销售情况无关,只取…

PytorchLightning最佳实践基础篇

PyTorch Lightning(简称 PL)是一个建立在 PyTorch 之上的高层框架,核心目标是剥离工程代码与研究逻辑,让研究者专注于模型设计和实验思路,而非训练循环、分布式配置、日志管理等重复性工程工作。本文从基础到进阶&…

Apache Flink 实时流处理性能优化实践指南

Apache Flink 实时流处理性能优化实践指南 随着大数据和实时计算需求不断增长,Apache Flink 已经成为主流的流处理引擎。然而,在生产环境中,高并发、大吞吐量和低延迟的业务场景对 Flink 作业的性能提出了更高要求。本文将从原理层面深入解析…

ubuntu上将TempMonitor加入开机自动运行的方法

1.新建一个TempMonitor.sh文件,内容如下:#!/bin/bashcd /fjrobot/ ./TempMonitor &2.执行以下命令chmod x TempMonitor chmod x TempMonitor.sh rm -rf /etc/rc2.d/S56TempMonitor rm -rf /etc/init.d/TempMonitor cp /fjrobot/TempMonitor.sh /etc/…

速卖通自养号测评技术解析:IP、浏览器与风控规避的实战方案

一、速卖通的“春天”来了,卖家如何抓住机会?2025年的夏天,速卖通的风头正劲。从沙特市场跃升为第二大电商平台,到8月大促返佣力度升级,平台对优质商家的扶持政策越来越清晰。但与此同时,竞争也愈发激烈——…

adb: CreateProcessW failed: 系统找不到指定的文件

具体错误 adb devices * daemon not running; starting now at tcp:5037 adb: CreateProcessW failed: 系统找不到指定的文件。 (2) * failed to start daemon adb.exe: failed to check server version: cannot connect to daemon 下载最新的platform-tools-windows 下载最新…