opencv简易数字识别

2023-05-16

前言

使用opencv,进行简单的数字识别

注意:此案例中的数字识别仅当做学习参考,想要真正实现数字识别,实际情况复杂很多

思路

①图片预处理,将图片转灰度后再二值化,使其变成白字黑底

②查找外接矩形,找到原图中数字的最外层轮廓,根据最外层轮廓找到外接矩形

③模板匹配,以外接矩形为ROI区域,截取数字区域,与模板进行匹配

④输出结果

具体步骤

首先读入一张原图,备份(后面需要用),将其转灰度,然后二值化,再备份(后面需要用),因为查找轮廓会破坏原图,所以需要备份,然后我这素材原图就是很简单的黑底写了白字,没有其他噪声之类的,所以只需转灰度然后二值化,如果是其他图片,可能还需要滤波,腐蚀膨胀去除噪声,如果去除不不干净,还需要过滤一下,因为我们只需要得到数字的轮廓,而且最后要变成白字黑底,如下图所示

Mat img = imread("kk.png");  
Mat clone_img = img.clone(); //原图备份
cvtColor(img, img, COLOR_BGR2GRAY); //图片转灰度
threshold(img, img, 100, 255, THRESH_BINARY); //二值化
Mat clone_img1 = img.clone(); //备份二值化后的原图

然后就要开始查找轮廓了,找到轮廓后(可以不绘制轮廓和外接矩形),根据轮廓找到外接矩形,这时我们再定义一个存储原图中有效数字区域的容器,因为你找到外接矩形后,直接ROI就可以截取到该数字,注意,我们要在之前备份的二值化原图中来进行ROI截取,并且重设大小为我们模板图的大小,然后我们把该数字存起来,用于后面的识别

vector<vector<Point>> contours; //存储原图轮廓
vector<Vec4i> hierarcy;
findContours(img, contours, hierarcy, RETR_EXTERNAL, CHAIN_APPROX_NONE);//查找轮廓
drawContours(clone_img, contours, -1, Scalar(0, 255, 0), 1, 8);//绘制轮廓
vector<Rect> sort_rect(contours.size()); //外接矩形
vector<Mat> img_mat;//存储原图中的有效数字区域
for (int i = 0; i < contours.size(); i++)
{
	sort_rect[i] = boundingRect(contours[i]); //外接矩形
	Mat roi = clone_img1(sort_rect[i]);
	Mat dstroi;
	resize(roi, dstroi, Size(40, 50), 0, 0); //重设大小
	img_mat.push_back(dstroi);
    //绘制外接矩形
	rectangle(clone_img, Point(sort_rect[i].x, sort_rect[i].y),
	Point(sort_rect[i].x + sort_rect[i].width, sort_rect[i].y + sort_rect[i].height), 
     Scalar(0, 0, 255), 1, 8);
}

然后我们要对轮廓进行排序,因为opencv查找的轮廓并不是按顺序的,而是随机的,但是我们识别数字肯定是要按顺序,不然识别结果肯定是错误的,我们可以根据轮廓的外接矩形的x坐标来排序,从左往右x坐标依次增大,这里使用冒泡排序,排序过后的顺序就是原图中数字的正确顺序

//对矩形进行排序,因为轮廓的顺序不一定是数字真正的顺序
for (int i = 0; i < sort_rect.size(); i++)
{
	for (int j = i + 1; j < sort_rect.size(); j++)
	{
		int j_x = sort_rect[j].x;
		int i_x = sort_rect[i].x;
		if (j_x < i_x)
		{
			Mat temps = img_mat[i];
			img_mat[i] = img_mat[j];
			img_mat[j] = temps;
		}
	}
}

 加载模板,模板是自己准备的,可以自己画一张0123456789,然后根据查找轮廓和外接矩形截取roi存起来,存起来后,我们再建立一个容器存储模板图片,注意这个模板图片也是需要转灰度二值化处理,方便匹配识别

vector<Mat> myTemplate; //模板容器
for (int i = 0; i < 10; i++)
{
	string name = format("%d.png", i);
	Mat temp = imread(name);
	cvtColor(temp, temp, COLOR_BGR2GRAY);
	threshold(temp, temp, 100, 255, THRESH_BINARY);
	myTemplate.push_back(temp);
}

最后就是模板匹配了,匹配的方式有很多种,这里采用的是对数字和模板进行像素点的匹配,根据相同像素点的百分占比来得出结论,相同像素点越多,说明匹配相似度越高,最后以匹配程度最高的作为最终识别结果

double compare(Mat &img, Mat &temp)               
{
	Mat my_temp;
	resize(temp, my_temp, img.size());
	int rows, cols;
	uchar *img_point, *temp_point; //像素类型uchar
	rows = my_temp.rows;
	cols = my_temp.cols*img.channels();
	double result, same = 0.0, different = 0.0;
	for (int i = 0; i < rows; i++)       //遍历图像像素
	{
        //获取像素值
		img_point = img.ptr<uchar>(i); 
		temp_point = my_temp.ptr<uchar>(i);
		for (int j = 0; j < cols; j++)
		{
			if (img_point[j] == temp_point[j])
				same++;         //记录像素相同的个数
			else
				different++;    //记录像素不同的个数
		}
	}
	result = same / (same + different);
	return result;                     //返回匹配结果
}
vector<int> seq;//顺序存放识别结果
for (int i = 0; i < img_mat.size(); i++)
{
	double com = 0;
	double min = 0;
	int min_seq = 0;//记录识别结果
	for (int j = 0; j < myTemplate.size(); j++)
	{
		com = compare(img_mat[i], myTemplate[j]);
		if (com > min)
		{
			min = com;
			min_seq = j;
		}
		com = 0;
	}
	seq.push_back(min_seq);
}
//输出结果
cout << "识别结果为:";
for (int i = 0; i < seq.size(); i++)
cout << seq[i];
	

识别结果,正确识别,即使缩放大小也一样能识别成功

以上就是opencv简易的数字识别

喜欢的话就点个赞吧~

点赞收藏关注就是对我最大的支持~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv简易数字识别 的相关文章

  • 百度云离线下载含有违规内容检测方法分析

    最近国家开始一轮净网行动 xff0c 清除网上的淫秽色情信息 各大互联网厂家纷纷开始行动 xff0c 比如当年很好用的百度云离线下载就一度关闭 后来再次开启后 xff0c 就出现了这句经典词 xff0c 因含有违规内容被屏蔽无法下载 其实被
  • 基于PLC S7-200恒压变频供水系统设计

    基于PLC S7 200恒压变频供水系统设计 有Wincc仿真设计 xff0c 梯形图程序 系统主要由PLC 变频器 电动机 水阀 传感器构成 xff0c 该系统用PLC作为控制器 xff0c 将控制信号传递给变频器 xff0c 变频器控制
  • 我的首篇博客——记录学习,不忘初心

    Hello 大家好 xff01 我是阿冰 xff01 今天是2022年12月2日 xff0c 受疫情影响 xff0c 我们学校的同学都早早的回家了 xff0c 今天就是我回家的第五天 其实 xff0c 这并不算是真正意义的寒假 xff0c
  • Java标识符和关键字

    目录 前言 一 关键字 1 什么是关键字 xff1f 2 关键字的一些注意事项 二 标识符 1 什么是标识符 xff1f 2 标识符书写规范 总结 前言 在华清学习的所思所想 xff1a Java关键字及标识符 一 关键字 1 什么是关键字
  • 图为科技NVIDIA Jetson Xavier NX测评

    NVIDIA推出了世界上最小的人工智能计算机 NVIDIA Jetson Xavier NX 整个设置的大小小于普通大小的借记卡或信用卡 该模块虽然不是业务中最小的 xff0c 但它所提供的处理能力和其他质量足以弥补其尺寸 Jetson N
  • Jetson TX2 NX 模块以纳米尺寸提供 TX2 电源

    Nvidia 推出了Jetson TX2计算模块 的降速功能 xff0c 该模块位于 TX2 和低端Jetson Nano之间 Jetson TX2 NX 在与 TX2 相同的六核 CPU 和 256 核 Pascal GPU 上运行 Li
  • 无人机在行业的应用方面呈现出多元化的趋势

    随着科技的不断发展和进步 xff0c 无人机的行业应用也逐渐扩大 作为民用无人机主要细分领域之一 xff0c 测绘无人机的发展也越来越成熟 xff0c 市场规模保持高速增长 无人机在应用方面也呈现出多元化的趋势 xff0c 备受各个行业用户
  • 嵌入式能从事什么职业?

    嵌入式本身发展是很好的 xff0c 这也是大家接触它的原因 xff0c 最后大家也是想通过学习嵌入式而找到关于嵌入式开发的工作 xff0c 想必大家也应该知道嵌入式工作要求有很多 xff0c 下面就一起来看看嵌入式能从事什么职业吧 点击获取
  • 嵌入式入门学习的必要步骤

    很多新手在入门嵌入式的时候 xff0c 经常会有很多问题 xff0c 这也都是想要多多去了解嵌入式 xff0c 也害怕自己浪费了时间还没有学会嵌入式 xff0c 掌握到好方法学习嵌入式 xff0c 那么就会事半功倍 xff0c 下面一起来看
  • 逆变器原理

    逆变器是把直流电转变为交流电的一种装置 它一般包括逆变桥 控制逻辑和滤波电路组成 主要是把各种直流源转变为交流供交流负载使用 xff0c 一般直流源有蓄电池 干电池 太阳能电池等 xff0c 可以应用到不间断电源 UPS 太阳能发电转换等
  • RS-485 通讯协议简介

    与 CAN 类似 xff0c RS 485 是一种工业控制环境中常用的通讯协议 xff0c 它具有抗干扰能力强 传输距离远的特点 RS 485 通讯协议由 RS 232协议改进而来 xff0c 协议层不变 xff0c 只是改进了物理层 xf
  • 反向散射耦合RFID系统的原理及特点,带你更深入的了解

    一 反向散射耦合RFID系统 1 反向散射 雷达技术为RFID的反向散射耦合方式提供了理论和应用基础 当电磁波遇到空间目标时 xff0c 其能量的一部分被目标吸收 xff0c 另一部分以不同的强度散射到各个方向 在散射的能量中 xff0c
  • 西门子PLC,1200PLC如何接线,2分钟就能明白

    西门子PLC xff0c 1200PLC如何接线 xff0c 2分钟就能明白 西门子PLC xff0c 1200PLC如何接线 xff0c 2分钟就能明白 哔哩哔哩 bilibili
  • 2022年嵌入式开发就业前景怎么样?

    时间 xff1a 2022年5月26号 xff01 这几年嵌入式开发的发展前景可以说是非常的香 xff01 从工资和找工作的难易程度上说都是 xff01 按老师傅的说法就是 xff1a 加班不严重 xff0c 注重积累 xff0c 越往底层
  • ARM结构体系3:ARM指令的寻址和异常中断处理

    目录 ARM处理器的八种寻址方式 1 立即数寻址 2 寄存器寻址 3 寄存器间接寻址 4 寄存器移位寻址 5 基址变址寻址 6 多寄存器寻址 7 相对寻址 8 堆栈寻址 9 GNU汇编伪指令 异常中断处理 1 7种异常源 2 异常向量表 A
  • 51单片机(ESP8266模块)

    前言 xff1a 蓝牙 xff0c ESP 01s xff0c Zigbee NB Iot等通信模块都是基于AT指令的设计 一 AT指令 AT指令集是从终端设备 xff08 Terminal Equipment xff0c TE 或数据终端
  • 嵌入式工作机会会越来越少吗

    我认为嵌入式工作会越来越多 在当前产业结构升级的大背景下 xff0c 物联网会与诸多的行业领域产生更加紧密的联系 xff0c 而这个过程必然离不开嵌入式开发的参与 应用场景对于嵌入式开发领域的发展有非常直接的影响 xff0c 嵌入式开发要想
  • 大学生为何很想往嵌入式方向发展?

    这几年嵌入式工资一直在再涨 xff0c 挺好的 xff01 可以选择的公司也比较多 xff0c 起薪差不读在10k 13k的样子 招聘公司统计的数据是19K 优点1 xff1a 应届生嵌入式行业的薪资在毕业生眼里看来真的是很香 xff0c
  • 涨姿势 | 一文说透电机控制器硬件在环测试(MCU HIL)

    软件质量是嵌入式产品开发中最关注的问题之一 随着产品迭代 xff0c 软件复杂程度越来越高 xff0c 为保证软件质量 xff0c 需要对软件进行大量的测试 xff0c 这会在整个产品周期中消耗大量时间及资源 另一方面 xff0c 市场竞争
  • VMware Workstation创建Windows 11(21H2)虚拟机

    2021年6月24日 xff0c 微软发布了Windows 11 xff0c 很多人都想 尝尝鲜 可以为较高的电脑配置 xff0c 使得很多老电脑 望而却步 xff0c 或者有人想换可又嫌麻烦或不舍得 所以今天我来带大家创建Windows

随机推荐

  • 计算机知识——常见的存储类型

    一 常见存储器类型 xff1a 1 易失 非易失性存储器 xff1a 是指存储器断电后 xff0c 它存储的数据内容是否会丢失的特性 由于一般易失性存储器存取速度快 xff0c 而非易失性存储器可长期保存数据 易失性存储器最典型的代表是内存
  • 使用select函数实现TCP并发服务器

    首先介绍一下select 函数的功能 参数 返回值 int select int nfds fd set readfds fd set writefds fd set exceptfds struct timeval timeout voi
  • ROS下gazebo打不开,最新最全的可行方法

    问题具体描述 xff1a 在打开roscore的情况下 执行命令行 xff1a rosrun gazebo ros gazebo 或者命令行 xff1a roslaunch gazebo ros empty world launch 但是只
  • 西门子S7-200SMART模拟量输入、输出模块接线

    西门子S7 200SMART模拟量输入 输出模块接线 https www bilibili com video BV1J3411R7nu spm id from 61 333 337 search card all click 西门子S7
  • SyntaxError: Non-ASCII character ‘\xe9‘报错

    本人在用vscode写python代码时 xff0c 第一次运行就遇到了这种情况 解决方法 xff1a 在python文件开头加上以下一行 xff1a coding utf 8 如下图所示 xff1a 即可解决报错问题 xff08 注意 x
  • 最新:ubuntu18.04下,vscode报错:No such file or directory

    我遇到的问题是 xff1a 在vscode编译下是没有报错的 xff0c 但是运行文件时 xff0c 还是报错了 如下图所示 xff1a 实际上 xff0c vscode会经常遇到这种类似的问题 xff0c 建议可以使用ubuntu的终端运
  • 打开了ros中的rviz,显示不了机器人模型

    问题 xff1a 可以打开gazebo xff0c 但是打开rviz后 xff0c 显示不了机器人模型 报错情况如下图所示 xff1a 解决 xff1a 看看自己的launch文件是否加了以下的节点 xff1a lt node pkg 61
  • 在vscode的界面的竖线光标变成灰色方块,怎么解决?(最全方法集合)

    具体情况如下图所示 xff1a 原因 xff1a 是vscode安装了vim xff0c 所以会出现这种情况 解决方法 xff1a 1 点一下insert键 xff0c 可以单次取消灰色方块的出现 xff0c 但是不能根除灰色方块 2 卸载
  • 给keil5加芯片包(PACK)

    按照这个链接来安装即可 xff0c 非常的详细和简单 https blog csdn net qq 45931949 article details 125219598
  • Invoking “make -j1“ failed

    Invoking 34 make j1 34 failed 在进行catkin make j1 的单线程编译时 xff0c 出现了很玄学的问题 xff0c 就是一会编译成功 xff0c 之后重新编译又报这个错误 xff0c 终端报错的是这个
  • find a package configuration file provided by “GeographicLib“, but CMake did not find one.

    在编译kitty数据集时 xff0c 编译不通过 xff0c 发现是安装的系统没有安装GeographicLib库 xff0c 所以报错了 xff0c 解决方法就是自己安装就可以了 xff0c 命令行如下 xff1a git clone h
  • fatal error: glog/logging.h: 没有那个文件或目录

    compilation terminated lidar localization CMakeFiles hello kitti node dir build make 206 recipe for target 39 lidar loca
  • Docker

    概念 Go语言开发 xff0c 开发者打包他们的应用以及依赖包到一个轻量级 可移植的容器中 xff0c 然后发布到任何流行的 Linux 机器上 xff0c 也可以实现虚拟化 容器是完全使用沙箱机制 xff0c 相互之间不会有任何接口 xf
  • 【毕设项目】 基于stm32的四轴飞行器设计 - 物联网 嵌入式 单片机

    1 简介 Hi xff0c 大家好 xff0c 这里是丹成学长 xff0c 今天向大家介绍一个学长做的单片机项目 基于stm32的四轴飞行器设计 大家可用于 课程设计 或 毕业设计 单片机 嵌入式毕设选题大全及项目分享 https blog
  • keil5的安装详解(看完必会,不会你打我)

    如何安装KEIL5 本内容所涉及的软件只供教学使用 xff0c 不得用于商业用途 个人或公司因商业用途导致的法律责任 xff0c 后果自负 温馨提示 1 安装路径不能带中文 xff0c 必须是英文路径 2 安装目录不能跟51的KEIL或者K
  • 【毕设选题推荐】机器人工程专业毕设选题推荐

    文章目录 1前言2 如何选题3 机器人工程 毕设 选题推荐4 最后 1前言 x1f947 近期不少学弟学妹询问学长关于机器人工程专业工程专业相关的毕设选题 xff0c 学长特意写下这篇文章以作回应 xff01 以下是学长亲手整理相关的毕业设
  • 【开源】千元级桌面六轴机械臂,适合教育科研二次开发

    目前市场上面的机械臂大多数在10万元左右 xff0c 由于成本太高 xff0c 不能广泛应用 xff0c 只能应用于一些特殊要求的工业场合 那么有没有一款机械臂小巧灵活 xff0c 价格接地气 xff1f myCobot 280 amp n
  • 基于主成分分析的LSTM和GPR模型融合负荷预测(可实现概率预测)

    基于主成分分析的LSTM和GPR融合负荷预测 一 背景介绍 二 部分代码展示 三 结果分析 一 背景介绍 本文数据来源于某地区2020年1月1日至12月31日的综合能源系统冷热电负荷和其他各种影响因子 xff0c 每间隔一小时采一次样 本文
  • Qt制作图表生成器

    基于Qt中的QCharts模块制作图表生成器软件 添加模块 QT 43 61 charts 添加命名空间 using namespace QtCharts 该软件可制作多种图表 多样化主题设置 保存移植便捷快速 输入相关数据 自动生成对应图
  • opencv简易数字识别

    前言 使用opencv xff0c 进行简单的数字识别 注意 xff1a 此案例中的数字识别仅当做学习参考 xff0c 想要真正实现数字识别 xff0c 实际情况复杂很多 思路 图片预处理 xff0c 将图片转灰度后再二值化 xff0c 使