opencv实现KNN算法识别图片数字

news2025/1/3 4:48:12

KNN算法实现识别图片数字

目录

  • KNN算法实现识别图片数字
    • 图片基本情况
      • 图片
      • 数据
    • 图片数字识别
      • 图片数据处理及预测
      • 其它数字图片正确率预测

图片基本情况


图片

在这里插入图片描述

数据

图片像素是2000x1000,即高(行)1000,宽(列)2000,每个数字区域为20*20,每5行都是同一个数字,每行数字有50个,每列数字有100个
在这里插入图片描述

图片数字识别


图片数据处理及预测

  • hsplit(矩阵,n)
    竖向切分切n个
  • vsplit(矩阵,n)
    横向切分切n个
  • reshape(-1,n)
    重构二维矩阵,-1表示所有,n表示列

400列即20*20每一个数字区域,每列为一个特征数据,占一个维度

  • astype(n)
    设置数据类型
  • cv2.ml.KNearest_create()
    创建knn算法
  • train(x,cv2.ml.ROW_SAMPLE,y)
    训练模型,x为特征数据,y为结果类别,cv2.ml.ROW_SAMPLE设置按行处理数据
  • ret,result,neighbors,dist = knn.findNearest(x,k=3)
    x为特征数据,k为范围,ret bool值,result数据预测结果,neighbors邻居,dist距离
  • 矩阵==矩阵
    返回矩阵,值为bool值,如果矩阵一一对应的值相等为T,否则F
  • np.count_nonzero(矩阵),计算为矩阵内非0的个数

代码展示:

# 灰度图
img1 = cv2.imread('tu_data.png')
img = cv2.imread('tu_data.png',0)

# 每个数字区域为20*20,每5行都是同一个数字
# hsplit 竖向切分,vsplit 沿行横向切分
# 列表生成式,先横向切分切50行,再将横向行数据竖向切分,每行切100列,共50*100=5000个图片数据,每个都是一个1000/50=20,2000/100=20
#每个图片都是20*20的数值
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# print(cells)
# 列表转矩阵
data_img = np.array(cells)
# print(data_img)
# 切分数据一半,一半作为历史数据培训模型,一半作为测试数据,检测
# 切分后的是一半是5000/2=2500个,从中间竖切一半变为50*50
train_x = data_img[:,:50]
test_x = data_img[:,50:100]
# 设置x特征数据
tr_x = train_x.reshape(-1,400).astype(np.float32)
te_x = test_x.reshape(-1,400).astype(np.float32)
# 根据图片结果构建0-9的y类别标签
# 生成0-9的np矩阵
k = np.arange(10)
# 复制标签
# 从0到9,依次复制250个,50*5=250
lab = np.repeat(k,250)
# 增加数组维度
t_lab = lab[:,np.newaxis]
#创建knn算法
knn = cv2.ml.KNearest_create()
#训练模型
knn.train(tr_x,cv2.ml.ROW_SAMPLE,t_lab)
ret,result,neighbors,dist = knn.findNearest(te_x,k=3)
# 正确率
match = result==t_lab
T = np.count_nonzero(match)
c = T*100.0/ result.size
print(c)

运行结果:
在这里插入图片描述

其它数字图片正确率预测

其他图片为单个20*20的图片,如下
代码展示:
在这里插入图片描述

import cv2
import numpy as np

# 只能是灰度图
img1 = cv2.imread('tu_data.png')
img = cv2.imread('tu_data.png',0)
# print(type(img1),type(img))
# 每个数字区域为20*20,每5行都是同一个数字
# hsplit 竖向切分,vsplit 沿行横向切分
# 列表生成式,先横向切分切50行,再将横向行数据竖向切分,每行切100列,共50*100=5000个图片数据,每个都是一个1000/50=20,2000/100=20
#每个图片都是20*20的数值
cells = [np.hsplit(row,100) for row in np.vsplit(img,50)]
# print(cells)
# 图片数据转np矩阵
data_img = np.array(cells)
# print(data_img)
# 切分数据一半,一半作为历史数据培训模型,一半作为测试数据,检测
# 切分后的是一半是5000/2=2500个,从中间竖切一半变为50*50
train_x = data_img[:,:50]
test_x = data_img[:,50:100]

# 设置x特征数据
tr_x = train_x.reshape(-1,400).astype(np.float32)
te_x = test_x.reshape(-1,400).astype(np.float32)
# 根据图片结果构建0-9的y类别标签
# 生成0-9的np矩阵
k = np.arange(10)
# 复制标签
# 从0到9,依次复制250个,50*5=250
lab = np.repeat(k,250)
# 增加数组维度
t_lab = lab[:,np.newaxis]
print(k,type(k))
print(lab,type(lab))
print(t_lab,type(t_lab))
# 创建knn算法
knn = cv2.ml.KNearest_create()
#训练模型
knn.train(tr_x,cv2.ml.ROW_SAMPLE,t_lab)
ret,result,neighbors,dist = knn.findNearest(te_x,k=3)


t1 = cv2.imread('t1.png',0)
t2 = cv2.imread('t2.png',0)
t3 = cv2.imread('t3.png',0)
t4 = cv2.imread('t4.png',0)
t5 = cv2.imread('t5.png',0)
t6 = cv2.imread('t6.png',0)
t7 = cv2.imread('t7.png',0)
t8 = cv2.imread('t8.png',0)
t9 = cv2.imread('t9.png',0)
t0 = cv2.imread('t0.png',0)
#运行都是np.array数组类型,需要添加定义为数组,再重构,可以先输出部分结果观察
tt = np.array([t0,t1,t2,t3,t4,t5,t6,t7,t8,t9])
k = np.array([0,1,2,3,4,5,6,7,8,9])
t_lab1 = k[:,np.newaxis]
tt = tt.reshape(-1,400).astype(np.float32)
# 不同数据输入可能输出结果与类型不同,判断标签可能需要调整
ret1,result1,neighbors1,dist1 = knn.findNearest(tt,k=3)
print(result1)
print(t_lab1)
match1 = result1==t_lab1
print(result1==t_lab1)
T1 = np.count_nonzero(match1)
c1 = T1*100.0/ result1.size
print(c1)

运行结果:

在这里插入图片描述

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

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

相关文章

美畅物联丨视频上云网关获取视频流地址供第三方调用的方法

在视频监控与流媒体传输领域,视频流地址的获取与调用是极为关键的环节。视频上云网关作为一款高效且稳定的视频传输设备,为获取视频流地址提供了便捷途径,从而使外部系统或平台能够方便地进行调用。今天我们就来讨论一下如何在视频上云网关上…

MySQL数据库——索引结构之B+树

本文先介绍数据结构中树的演化过程,之后介绍为什么MySQL数据库选择了B树作为索引结构。 文章目录 树的演化为什么其他树结构不行?为什么不使用二叉查找树(BST)?为什么不使用平衡二叉树(AVL树)&a…

一起学Git【第六节:查看版本差异】

git diff是 Git 版本控制系统中用于展示差异的强大工具。他可以用于查看文件在工作区、暂存区和版本库之间的差异、任意两个指定版本之间的差异和两个分支之间的差异等,接下来进行详细的介绍。 1.显示工作区与暂存区之间的差异 # 显示工作区和暂存区之间的差异,后面不加参数…

Fetch处理大模型流式数据请求与解析

为什么有的大模型可以一次返回多个 data? Server-Sent Events (SSE):允许服务器连续发送多个 data: 行,每个代表一个独立的数据块。 流式响应:大模型服务通常以流式响应方式返回数据,提高响应速度。 批量处理&#x…

期权懂|个股期权的流动性如何?

锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 个股期权的流动性如何? 个股期权作为场外交易工具,具有较高的灵活性。场外交易意味着交易双方可以直接协商交易条款,这有助于满足不同投资者的…

国产低代码框架zdppy开发笔记002 标准的接口响应

前言 通过前面的学习, 我们已经知道了zdppy_api和zdppy_req的基本用法, 接下来我们会在学习中多次用到这两个框架. 我们已经知道了该如何响应一个字符串,但是我们该如何响应json数据呢? 在zdppy_api中,我们定义了一组规范的API响应, 我们慢慢来看看. 规范的响应 首先来看…

Linux | 零基础Ubuntu解压RaR等压缩包文件

目录 介绍 案例分析 安装工具 解压实践 介绍 RAR是一种专利文件格式,用于数据压缩与归档打包,开发者为尤金罗谢尔(俄语:Евгений Лазаревич Рошал,拉丁转写:Yevgeny Lazarevich R…

Python基于卷积神经网络的车牌识别系统开发与实现

1. 简介 车牌识别是人工智能在交通领域的重要应用,广泛用于高速违章检测、停车场管理和智能交通系统等场景。本系统通过基于卷积神经网络(CNN)的深度学习算法,结合 Python 和 MySQL 实现车牌的快速识别与管理。 系统特点&#x…

stm32内部flash在线读写操作

stm32内部flash在线读写操作 📍相关开源库文章介绍《STM32 利用FlashDB库实现在线扇区数据管理不丢失》 ✨不同系列,内部flash编程有所区别。例如stm32f1是按照页擦除,半字(16bit)或全字(32bit)数据写入;st…

IDEA | SpringBoot 项目中使用 Apifox 上传接口

目录 1 安装 Apifox Helper 插件2 获取 Apifox 的 API 访问令牌3 IDEA 中设置 API 访问令牌4 IDEA 中上传接口5 常见问题5.1 如何自动设置目录名5.2 如何自动设置接口名5.3 如何更改上传位置 Apifox 官方指南: https://apifox.com/help/applications-and-p…

Leetcode 10-正则表达式匹配/ 剑指 Offer 19. 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ‘*’ 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s 的,而不是部分字符串。 题解 字符串匹配多…

学习vue3的笔记

一、vue和react的对比 1、基础介绍 vue:https://cn.vuejs.org/ vue3是2020年创建的 react:https://react.dev/ react是一个2013年开源的JavaScript库,严格意义上来说不是一个框架 2、diff算法 两个框架采用的都是同级对比策略 两节点对…

基于STM32的智能家居环境监控系统设计

目录 引言系统设计 硬件设计软件设计系统功能模块 环境监控模块控制模块显示模块系统实现 硬件实现软件实现系统调试与优化结论与展望 1. 引言 随着智能家居技术的发展,环境监控系统已经成为家居管理的重要组成部分。智能家居环境监控系统通过实时监测室内温度、湿…

【MySQL】搞懂mvcc、read view:MySQL事务原理深度剖析

前言:本节内容是事务里面最难的一部分, 就是理解mvcc快照读和read view。这两个部分需要了解隔离性里面的四种隔离级别。 博主之前讲过,但是担心友友们不了解, 所以这里开头进行了复习。 下面开始我们的学习吧! ps&…

jmeter设置tps、响应时间监测时间间隔

jmeter设置tps、响应时间监测时间间隔 思路: 1、设置tps和响应时间插件的采集时间间隔,然后运行jmeter脚本; 2、先按默认配置跑出jtl文件保存下来,再添加tps和响应时间插件,设置采集时间间隔后,导入jtl文件…

Qt 12.30 day5

day5_testppp.proQT core gui texttospeech widget.h#ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimerEvent>//定时器事件类 #include <QTimer>//时间事件类 #include <QTime>//时间类 #include <QTextToSpeech>//…

玩转OCR | 腾讯云智能结构化OCR初体验

随着数字化进程的加速&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术已逐渐成为提高企业生产力、优化工作流的重要工具。腾讯云智能结构化OCR凭借其领先的技术、广泛的应用场景和灵活的定制化能力&#xff0c;正在帮助各行业客户更高效地进行文档处理与数据提取。本…

Spring Boot教程之三十九: 使用 Maven 将 Spring Boot 应用程序 Docker 化

如何使用 Maven 将 Spring Boot 应用程序 Docker 化&#xff1f; Docker是一个开源容器化工具&#xff0c;用于在隔离环境中构建、运行和管理应用程序。它方便开发人员捆绑其软件、库和配置文件。Docker 有助于将一个容器与另一个容器隔离。在本文中&#xff0c;为了将Spring B…

模仿微信小程序wx.showModal自定义弹窗,内容可以修改

实现以下弹框样式功能 1.在components新建一个文件showModel.wpy作为组件&#xff0c;复制下面代码 <style lang"less" scoped> .bg_model {display: flex;justify-content: center;align-items: center;// 弹框背景.bg_hui {width: 100%;height: 100%;posi…

缓存管理自动化:JuiceFS 企业版 Cache Group Operator 新特性发布

近期&#xff0c;JuiceFS 企业版推出了 Cache Group Operator&#xff0c;用于自动化创建和管理缓存组集群。Operator 是一种简化 Kubernetes 应用管理的工具&#xff0c;它能够自动化应用程序的生命周期管理任务&#xff0c;使部署、扩展和运维更加高效。 在推出 Operator 之前…