基于opencv的数字识别系统

news2024/9/21 12:40:22

一、目的

想要实现的功能:帮助我们在泵中扫描燃油,并在应用程序中输入燃油信息。

所需技术:①python程序对于拍摄的汽油泵的图像,尝试从中读取数字。——opencv实现。②先使用python对其进行原型设计,然后将代码转换成C++以在ios应用程序上运行。

        但是我不会部署在移动端,对第二个不做研究。

目标:需要考虑两个问题:

  1. 可以从图像中分离出数字吗?——用opencv图像阈值法来查找数字,进行裁剪轮廓
  2. 可以确定图像代表哪个数字吗?——KNN进行分类训练。

二、图像中分离出数字

思路:利用简单的图像阈值法来查找数字。

图像阈值法:将图像转换为灰度,然后说灰度值小于某个常数的任何像素,则该像素为一个值,否则为另一个。最后,得到的二进制图像只有两种颜色,在大多数情况下只是黑白图像。一幅图通常包含目标物体还有各种背景和噪声,想要得到目标物体,就要设置一个阈值,用阈值将图像的像素分割成两部分。

        但是阈值的值如何确定呢?——五、自动化可以解决阈值的选择

        这个概念在OCR应用中非常有效,但是主要问题是决定对该阈值使用什么。我们可以选择一些常量,也可以使用OpenCV选择其他一些选项。我们可以使用自适应阈值而不是使用常数,这将使用图像的较小部分并确定要使用的不同阈值。这在具有不同照明情况的应用中特别有用,特别是在扫描气泵中。

设置好阈值后,使用opencv中的findcontours方法查找图像中连接了白色像素部分的区域。绘制轮廓后,便可以裁剪出这些区域并确定它们是否可能是数字以及是什么数字。

2.1 图像处理流程

这是我在测试图像处理中使用的原始图像。它有一些眩光点,但是图像相当干净。让我们逐步完成获取此源图像的过程,并尝试将其分解为单个数字。

在代码中主要对应于playground.py函数,这个相当于完整的代码,会输出最后的预测结果,其中图像分割部分主要调用的是frameProcessor.py文件中的函数。

原始图片

 2.1.1 图像准备

在开始图像处理流程之前,我们决定先调整一些图像属性,然后再继续。这有点试验和错误,但注意到,当我们调整图像的曝光度时,可以获得更好的结果。下面是使用Python调整后的图像,相当于曝光(阿尔法)的图像cv::Mat::convertTo这是刚刚在图像点乘法操作cv2.multiply(some_img, np.array([some_alpha]),

调整曝光

2.1.2 灰阶

将图像转换为灰度。

转换为灰度

2.1.3 模糊

模糊图像以减少噪点。我们尝试了许多不同的模糊选项,但仅用轻微的模糊就找到了最佳结果。

稍微模糊

2.1.4 阈值化

图像转换为黑白图像

在下图中,使用cv2.adaptiveThreshold带有cv2.ADAPTIVE_THRES_GAUSSIAN_C选项的方法。此方法采用两个参数,块大小和要调整的常数。确定这两者需要一些试验和错误,更多有关优化部分的内容。

阈值为黑/白

2.1.5 填补空白

由于大多数燃油泵都使用某种7段LCD显示屏,因此数字中存在一些细微的间隙,无法使用轮廓绘制方法,因此我们需要使这些段看起来相连。在这种情况下,我们将转到erode(黑多白少)图像来弥补这些差距。由于大家可能希望使用,所以这似乎向后看,dilate但是这些方法通常适用于图像的白色部分。在我们的案例中,我们正在“侵蚀erode”白色背景以使数字看起来更大。

侵蚀出来的数字

2.1.6 反转图像

在尝试在图像中查找轮廓之前,我们需要反转颜色,因为该findContours方法将找到白色的连接部分,而当前的数字是黑色。

颜色反转

2.1.7 在图像上找到轮廓

下图显示了我们的原始图像,该图像在上图的每个轮廓上都有包围框。大家可以看到它找到了数字,但也找到了一堆不是数字的东西,因此我们需要将它们过滤掉。

红色框显示所有找到的轮廓

轮廓过滤

  1. 现在我们有了许多轮廓,我们需要找出我们关心的轮廓。浏览了一堆气泵的显示和场景后,使用一套适用于轮廓的快速规则。
  2. 收集所有我们将分类为潜在小数的正方形轮廓。
  3. 扔掉任何不是正方形或高矩形的东西。
  4. 使轮廓与某些长宽比匹配。LCD显示屏中的十个数字中有九个数字的长宽比类似于下面的蓝色框高光之一。该规则的例外是数字“ 1”,其长宽比略有不同。通过使用一些样本轮廓,我将0–9!1方面确定为0.6,将1方面确定为0.3。它将使用这些比率和+/-缓冲区来确定轮廓是否是我们想要的东西,并收集这些轮廓。
  5. 对潜在数字应用一组附加规则,在这里我们将确定轮廓边界是否偏离所有其他潜在数字的平均高度或垂直位置。由于数字的大小应相同,并且在相同的Y上对齐,因此我们可以丢弃它认为是数字的任何轮廓,但不能像其他轮廓那样将其对齐和调整大小。

蓝色矩形显示我们的数字/十进制,红色被忽略

 2.1.8 查找小数点

在图像中查找小数点是要解决的另一个问题。由于它很小,有时会连接到它旁边的手指,因此使用我们在手指上使用的方法来确定它似乎有问题。当我们过滤轮廓时,我们收集了可能是十进制的正方形轮廓。从上一步获得经过验证的数字轮廓之后,我们将找到数字的最左x位置和最右x位置,以确定我们期望的小数位数。然后,我们将遍历那些潜在的小数,确定它是否在该空间以及该空间的下半部分,并将其分类为小数。找到小数点后,我们可以将其插入到我们上面预测的数字字符串中。

只在黄色部分中查找小数

 2.1.9 将识别的数字裁剪

cropped = eroded[y:y + h, x: x + w]

直接选用img[h, w, c]进行切割。

三、 对切割的数字进行预测

3.1 数字训练

在机器学习的世界中,解决OCR问题是一个分类问题。我们建立了一组训练有素的数据,例如图像处理中的数字,将它们分类为某种东西,然后使用该数据来匹配任何新图像。一旦基本的图像隔离功能开始工作,我就创建了一个脚本,generate_distorted_images.py,该脚本可以遍历图像文件夹,运行数字隔离代码,然后将裁剪的数字保存到新文件夹中供我查看。运行完之后,我会有一个未经训练的数字文件夹,然后可以用来训练系统。(其实感觉是对裁剪好的数字图像进行腐蚀或者膨胀操作,然后增加数字图像的,类似于数据增强的操作一样

由于OpenCV已经包含了k近邻(k-NN)实现,因此无需引入任何其他库。为了进行训练,我们浏览了数字图像的文件夹,然后将其放入标有0–9的新文件夹中,因此每个文件夹中都有一个数字的不同版本的集合。我们没有大量的这些图像,但是有足够的证据来证明这是可行的。由于这些数字是相当标准的,我认为我不需要大量训练有素的图像就可以相当准确。

k-NN工作原理的基础是,我们将以黑白方式加载每个图像,将该图像存储在每个像素处于打开或关闭状态的数组中,然后将这些打开/关闭像素与特定的数字相关联。然后,当我们要预测一个新图像时,它将找出哪个训练图像与这些像素最匹配,然后向我们返回最接近的值。frameProcessor.py

# 调用cv2.ml.KNearest_create()创建一个KNN分类器,
# 然后调用train方法进行训练,
# 调用findNearest方法进行测试,
# findNearest的返回值result表示根据knn算法得到的测试图像对应的标签,neighbours表示测试图像的k个最近邻,dist表示相应最近邻的距离

整理好数字后,将创建一个新的脚本,该脚本将遍历这些文件夹,获取每个图像并将该图像与数字关联。到目前为止,在大多数代码中,一般的图像处理概念在Python和C ++中都应用相同,但是在这里会有细微的差别。train_model.py文件写分类结果

 在大多数此类应用程序的Python示例中,分类被写入两个文件,一个包含分类,另一个包含该分类的图像内容。通常使用NumPy和标准文本文件完成此操作。但是,由于我想在iOS应用程序上重用该系统,因此我需要想出一种可以拥有跨平台分类文件的方式。当时,我什么都找不到,因此最终编写了一个快速实用程序,该实用程序将从Python中获取分类数据并将其序列化为JSON文件,我可以在OpenCV的FileStorage系统的C ++端使用它。这不漂亮,但是我写了一个简单的MatPython中的序列化方法,它将为OpenCV创建合适的结构以在iOS端读取。现在,当我训练数字时,我将获得NumPy文件供我的Python测试使用,然后获取一个JSON文档,我可以将其拖到我的iOS应用程序中。您可以在此处看到该代码。

3.2 预测

有两个等高线轮廓,一个带潜在位数,一个带潜在小数位,我们可以使用这些轮廓边界裁剪图像,并将其输入经过训练的系统中以预测其值。有关此过程的更多信息,请参见“3.1 数字训练”部分。

 四、优化

playground.py

一旦确定了数字隔离和预测的两个目标,就需要对算法进行优化,以预测泵的新图像上的数字。

在优化的初始阶段,创建了一个简单的Playground应用程序,其中使用了OpenCV提供的一些简单的UI组件。使用这些组件,可以创建一些简单的轨迹栏,以左右滑动并更改不同的值并重新处理图像。围绕该cv2.imshow方法创建了一个小包装程序,该方法可以平铺显示的窗口,因为我讨厌总是重新放置它们,

尝试不同的变量

我们可以加载不同的图像,并在图像处理中尝试变量的不同变化,并确定最佳的组合。

 五、自动化

test_processing.py中的bulk_run方法

在每个图像上测试不同的变量是上手的好方法,但是我们想要一种更好的方法来验证是否更改了一个图像的变量是否会对其他任何图像产生影响。为此,我们想出了针对这些图像进行一些自动化测试的系统。

我拍摄了每个测试图像,并将它们放在文件夹中。然后,我用图像中期望的数字来命名每个文件,并用小数点“ A”表示。应用程序可以加载该目录中的每个图像并预测数字,然后将其与文件名中的数字进行比较以确定是否匹配。这使我们可以针对所有不同的图像快速尝试更改。

自动测试输出

更进一步,我创建了此脚本的不同版本,该脚本将尝试对这组图像进行模糊,阈值等变量的几乎每种组合,并找出最优化的变量集将具有最佳的性能。准确性。该脚本在计算机上花费了相当长的时间才能运行,大约需要7个小时,但是最后提出了一组不同的变量,这些变量在我们手动测试时找不到。

 六、结论

这是否是任何人实际上都会使用的功能尚待确定,但这在实现某些机器学习概念和使用OpenCV方面是一个有趣的练习。到目前为止,在我们的测试中,应用程序最大的问题是泵显示屏上的眩光。根据泵上的照明和手机的角度,可能会导致某些扫描失效。

代码链接: https://download.csdn.net/download/weixin_45823221/87364739

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

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

相关文章

TiDB分布式数据库部署与安装详解

TiUP 是 TiDB 4.0 版本引入的集群运维工具,TiUP cluster 是 TiUP 提供的使用 Golang 编写的集群管理组件,通过 TiUP cluster 组件就可以进行日常的运维工作,包括部署、启动、关闭、销毁、弹性扩缩容、升级 TiDB 集群,以及管理 TiD…

EMQX Enterprise 4.4.124.4.13 发布:集群负载重平衡、TDengine 3.0 适配以及子表批量插入

我们很高兴地告诉大家,EMQX Enterprise 4.4.12 以及 4.4.13 版本正式发布! 在本次发布中,我们带来了集群负载重平衡与节点疏散功能为运维人员提供更灵活的集群管理方式,适配了 TDengine 3.0 版本并新增分表批量插入功能&#xff…

ECMAScript 2022 中的新特性!

新钛云服已累计为您分享718篇技术干货本文盘点ECMAScript 2022 中的新特性,包括顶级等待、RegExp 匹配索引、新的公共和私有类字段等。一、公共和私有实例字段最新的 ES13 规范允许我们将成员字段内联定义为类主体的一部分,我们可以使用#来表示私有字段。…

Python打包(问题记录,带解决)

引言 文章用于测试在Python3.8的版本,打包Obspy地震包,最后集成到PyQt5上。 部署或冻结应用程序是 Python 项目的重要组成部分, 这意味着捆绑所有必需的资源,以便应用程序找到它需要的一切 能够在客户端计算机上运行。 但是&…

Ethereum 基础(一)

以太坊(Ethereum)是社区运行的技术,为加密货币以太币(ETH)和数千个去中心化应用程序提供动力。 ethereum.org是您进入以太坊世界的门户。这项技术是新的、不断发展的——有个向导会有帮助。如果你想深入研究,我们建议你这样做。 …

Linux内核定时器

1.概念 在linux内核内部开发者设计了内核定时器,它的工作原理和硬件定时器一样,使用它不需要关注底层的实现,只需要分配定时器对象,初始化对象,启用定时器即可,当定时时间到达之后执行定时器的处理函数。 …

2022年第十二届APMCM亚太地区数学建模竞赛1月加赛E题翻译以及思路

中文2022年亚洲及太平洋地区建模数学竞赛问题E有多少颗核弹可以摧毁地球?1945年8月6日,第二次世界大战已接近尾声。为了尽快结束战争,美国在日本广岛投下了名为 "小男孩" 的第二颗原子弹。这样一颗原子弹炸死了广岛的200000人&…

硬盘容量计算

硬盘容量(Hard drive capacity)以兆字节(MB)或千兆字节(GB)为单位,主流硬盘容量为500G~2TB,影响硬盘容量的因素有单碟容量和碟片数量。许多人发现,计算机中显…

Java--面向对象经典练习题

文章内容 一、文字版格斗游戏 二、对象数组1 三、对象数组2 四、对象数组3 五、对象数组4 题目代码如下: 文字版格斗游戏 格斗游戏,每个游戏角色的姓名,血量,都不相同,再选定人物的时候(new对象的时候)&#xf…

(Java高级教程)第三章Java网络编程-第一节1:网络编程必备网络知识1之网络初识和网络协议

文章目录一:计算机网络基本概念二:计算机网络发展三:网络协议(1)生活中的协议(2)网络协议(3)协议是谁制定的注意:本节会总结一些必要的网络知识,便…

第03讲:HTTP操作之ElasticSearch映射操作

3.1.3、映射操作 有了索引库,等于有了数据库中的 database。 接下来就需要建索引库(index)中的映射了,类似于数据库(database)中的表结构(table)。 创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一…

P11 PyTorch Momentum

参考: 关于梯度下降与Momentum通俗易懂的解释_ssswill的博客-CSDN博客_梯度 momentum 前言: P9讲梯度的时候,讲到过这种算法的梯度更新方法 这边重点讲解一下原理 Momentum算法又叫做冲量算法,其迭代更新公式如下: 实…

【Vue中使用Echarts】响应式布局flexible.js+rem适配方案

文章目录一、vue集成flexible方案第一种:在编译的时候自动转换(px2rem-loader)第二种:直接在写css样式的时候转换(cssrem)二、安装&配置lib-flexible.js三、安装插件cssrem一、vue集成flexible方案 先介绍几个基本的概念 px像素(Pixel&…

LeetCode分类刷题---数组篇

刷题班数组1.二分查找704.二分查找35.搜索插入位置34.在排序数组中查找元素的第一个和最后一个位置。69.X的平方和367.有效的完全平方数2.移除元素27.移除元素283.移动零844.比较含退格的字符串977.有序数组的平方3.长度最小的子数组209.长度最小的子数组904.水果成蓝76.最小覆…

2023-01-05 长亭科技 Go 后端开发实习生二面

由于面试官前几天 🐏 了,在 HR 面后补了技术二面,不过问得倒也不难,但还是记录下。 1、请做 3 ~ 5 分钟的自我介绍。 2、你说研究生的方向是漏洞挖掘和模糊测试,可以介绍一下吗? 3、简单介绍下缓冲区溢出漏…

2022年中国特色智能工厂领航制造业升级分析报告

易观:当前,新一轮的科技革命和产业变革正在重塑世界格局,科技创新也成为影响国家竞争力的决定性因素。在全球制造业格局重塑的过程中,智能工厂作为全球智能制造产业实践的示范标杆与标准载体,是引领全球制造业企业与工…

机器学习中的数学原理——逻辑回归

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟,也希望对你的学习有帮助哦!感兴趣的小伙伴欢迎私信或者评论区留言!这一篇就更新一下《白话机器学习中的数学——逻辑回归》!什么是逻辑回归算法逻辑回归 (Logistic…

【信管6.3】成本挣值计算

成本挣值计算铺垫了那么久,不知道大家期待不期待。总算到了挣值计算这一课,这个名字很奇怪呀,什么叫做挣值?成本不就是我们的投资吗?这个挣值到底是要干嘛?带着这些疑问,我们就来看看挣值计算到…

2022全年度奶粉十大热门品牌销量榜单

随着居民收入水平的提升、消费观念的转变及健康饮食意识的逐渐增强,消费者对食品品质的要求也越来越高,奶粉市场也同样如此。当前,国内婴幼儿奶粉市场规模呈稳步增长态势,同时,“三孩政策”的发布实施,也利…

C++模板 - 提高编程

引言 本阶段主要针对C泛型编程和STL技术做详细的讲解,探讨C更深层的使用 1 模板 1.1 模板的概念 模板就是建立通用的模具,大大提高复用性 例如生活中的模板: 一寸照片模板: 模板的特点: 模板不可以直接使用&#…