如何训练专属的OCR文字识别模型

1. 背景

在10月24日程序员节,公司决定向每位技术人员发放购物实体卡以示庆祝。然而,手动输入实体卡上的一大串卡密可能是一项繁琐且不那么智能的任务;同时,线上用户在绑定购物卡的时候,同样也是需要手动输入。

基于以上背景,我们决定开发一套能够自动识别卡密的OCR文字识别模型:简单地将卡密放在相机前,便可以无需费心记忆和手动输入卡密,快速完成兑换过程,减少了可能存在的人为错误,以带来更便捷的用户体验

2. 基于通用模型的识别

2.1 OCR框架选型

随着文档数字化的发展,光学字符识别 (OCR) 变得越来越流行。OCR 在处理基于图像的文档中发挥着至关重要的作用。在文字识别方面,主要有两款主流的开源框架Tesseract和EasyOCR。

根据参考文献[1]中进行的一项实验,Tesseract 在字母识别方面做得更好,而 EasyOCR 在数字识别方面做得更好。在我们的实际使用场景下,字母的使用频率要远高于字母,因此我们选择使用Tesseract,它是一款目前由 Google 维护的开源 OCR引擎。

2.2 OCR框架安装&使用

如果你使用的是Mac系统,可以直接使用Homebrew进行安装:

brew install tesseract

框架自带的少量通用模型存储在/usr/local/share/tessdata目录下,后缀名为.traineddata,如果需要更多类型的通用模型,可以从github中下载并导入该目录下。GitHub - tesseract-ocr/tessdata_best: Best (most accurate) trained LSTM models.
模型使用可以直接在命令行中输入:

tesseract <input-pic-path> <output-path> -l <model-name> --psm 7

2.3 通用模型的识别效果

我们使用最通用的英文数字模型eng.traineddata,对一张实体卡的卡密进行识别,效果如下,可以看到,识别效果很一般,错误率较高,不仅把特殊字体的0识别成了B,还可能会把B识别成E。原因就是我们的卡密字体并不是一种常规字体,会造成通用模型的识别困难。
初步识别效果

2.4 交互层面弥补错误识别

针对通用模型识别错误率高的问题,首先想到的是交互方面的优化
将容易识别错的相似元素进行分组,譬如0、8、B、E为一组,R、A为一组等等。当识别到存在组内元素的时候,为用户提供一个用于交互的UI滚轮组件,使用户能够手动修正为组内的其他相似元素。
思考再三,还是觉得这样的解决方案太粗暴了,用户可能会疑惑为什么OCR每次都需要手动修正,这么明显的数字0为什么识别不出来?最终还是放弃了从交互层面来弥补错误的思路。

3. 训练专属的OCR模型

Tesseract除了可以使用官方提供的语言包(traineddata文件),还可以自己训练模型,特别适用于某些官方语言包识别效果不佳的场景下。本章将基于Tesseract-OCR5.0来训练自己的模型、以及如何提高准确率。
由于购物卡的卡密字体在生产过程中是不会改变的,因此我们可以根据它的字体样本,来训练一套专属的OCR模型,来改善通用模型在识别过程中的一些错误,提高OCR的准确率。

3.1 模型训练 - 样本采集准备

训练的前置准备工作就是样本采集,字体的数量千千万,我们无法通过肉眼识别实体卡的卡密到底用了哪种字体。首先我们尝试使用字体识别工具,发现最相似的字体匹配程度也只在70%左右,由于样本本身并不是百分百的匹配,经过后续的训练测试验证,识别效果也确实不理想。
字体寻找
解铃还须系铃人,只能想方设法找购物卡的制造商来解决了。经过沟通,然而制造商回应:
样本寻找
因此我们并不能拿到卡密字体的电子样本,为了不让这次沟通无功而返,我打算让制造商将0~9、A~Z打印出来并拍照。于是便有了下面这张照片,也是仅有的可用于训练的样本。
样本寻找

3.2 模型训练 - 生成用于训练的tif和box文件

首先生成训练用的tif文件,需要将多个训练图片合成到一个tif文件里。tif文件格式是一种用于存储图像数据的文件格式,具有无损压缩、支持多页等特性。我们可以直接使用jTessBoxEditor工具来完成,工具下载地址VietOCR - Browse /jTessBoxEditor at SourceForge.net。
打开jTessBoxEditor,选择Tools -> Merge TIFF,进入训练样本所在文件夹,选中要参与训练的样本图片,并将tif文件命名为"eng.myfont.exp0.tif"。

tif文件命名格式 [lang].[fontname].exp[num].tif
lang是语言名,fontname是字体名称,num为自定义版本号

tif
接着,在训练目录下打开cmd,输入下面命令,用现有的eng模型初步识别.tif文件并生成对应的.box文件,执行后在当前路径下生成 “eng.myfont.exp0.box” 文件。

tesseract eng.myfont.exp0.tif eng.myfont.exp0 -l eng --psm 7 batch.nochop makebox

box文件中将记录每个字符在图片上的位置以及识别出的内容。其中,psm参数用于设置识别模式,7代表将图像视为单个文本行,我们的场景使用的是单行统一文本,因此采用参数7。其他psm常用参数所代表的识别模式汇总如下:

0    Orientation and script detection (OSD) only.
1    Automatic page segmentation with OSD.
2    Automatic page segmentation, but no OSD, or OCR.
3    Fully automatic page segmentation, but no OSD. (Default)
4    Assume a single column of text of variable sizes.
5    Assume a single uniform block of vertically aligned text.
6    Assume a single uniform block of text.
7    Treat the image as a single text line.
8    Treat the image as a single word.
9    Treat the image as a single word in a circle.
10    Treat the image as a single character.
11    Sparse text. Find as much text as possible in no particular order.
12    Sparse text with OSD.
13    Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.

3.3 模型训练 - 矫正box文件错误

由于我们使用的是通用模型对tif进行的初步识别,因此box文件中字符的内容和位置大概率是会出错的,且需要来手动调整的。依然使用jTessBoxEditor工具,点击Box Editor -> Open,打开步骤2中生成的“zwp.test.exp0.tif”,会自动关联到“zwp.test.exp0.box”文件,这两文件要求在同一目录下。
下图是对box文件中字符内容和位置的错误纠正示例:
纠错1
纠错2
调整完样本中的错误之后,点击"save"保存修改。box文件中的字符信息也会相应地进行更改,只是jTessBoxEditor工具帮助我们可视化地完成了这件事。

3.4 模型训练 - 生成基于通用模型的lstm文件

从0到1开始训练一个新模型需要海量的样本和超强的算力,如果样本不足容易过拟合,不适合我们快速出结果,因此我们的模型将基于已有通用模型进行微调训练
从步骤2.2中的tessdata_best代码库里,下载所需语言的通用模型.traineddata文件,在本案例中选择下载eng.traineddata文件,并将该文件保存到当前工作目录下。并使用combine_tessdata命令,用当前目录下的eng.traineddata文件生成eng.lstm文件:

combine_tessdata -e eng.traineddata eng.lstm

打印输出:

Extracting tessdata components from eng.traineddata
Wrote eng.lstm
Version:4.00.00alpha:eng:synth20170629:[1,36,0,1Ct3,3,16Mp3,3Lfys64Lfx96Lrx96Lfx512O1c1]
17:lstm:size=11689099, offset=192
18:lstm-punc-dawg:size=4322, offset=11689291
19:lstm-word-dawg:size=3694794, offset=11693613
20:lstm-number-dawg:size=4738, offset=15388407
21:lstm-unicharset:size=6360, offset=15393145
22:lstm-recoder:size=1012, offset=15399505
23:version:size=80, offset=15400517

Tesseract从版本4.0开始,训练方法使用的是基于LSTM的深度学习网络,lstm文件的命名也由此而来,为模型训练的中间产物。

3.5 模型训练 - 基于样本生成lstmf文件

这一步利用tif图片文件生成lstmf文件,如下命令会生成eng.myfont.exp0.lstmf文件,这个是典型tesseract命令:

tesseract eng.myfont.exp0.tif eng.myfont.exp0 -l eng --psm 7 lstm.train

--参数介绍--
0  eng.myfont.exp0.tif   输入图像
1  eng.myfont.exp0       输出的lstmf文件名称
2  -l eng                使用的基础模型名称
3  --psm 7               分割模式,上文已介绍
4  lstm.train            指明进行lstm训练

生成lstmf之后,在同层级目录下新建一个eng.training_files.txt文本文件,将lstmf的绝对路径写入文件,在我本地电脑中的文本文件如下所示:

/Users/calvin/tesseract/training/eng.myfont.exp0.lstmf

3.6 模型训练 - 开始训练

使用lstmtraining命令开始训练,这一步将生成训练中间文件_checkpoint:

lstmtraining 
--model_output="/Users/calvin/tesseract/training/" 
--continue_from="/Users/calvin/tesseract/training/eng.lstm" 
--train_listfile="/Users/calvin/tesseract/training/eng.training_files.txt"
--traineddata="/Users/calvin/tesseract/training/eng.traineddata" 
--debug_interval -1 
--max_iterations 2000 
--target_error_rate 0.01
  • –debug_interval -1 调试打印等级
  • –max_iterations 2000 最大迭代次数
  • –target_error_rate 0.01 期望错误率
  • –continue_from 基于eng字体的lstm文件
  • –model_output 输出checkpoint文件的名称
  • –train_listfile 训练清单文件名称
  • –traineddata 训练使用的字体

输出打印:

Loaded file /Users/calvin/tesseract/training/eng.lstm, unpacking...
Continuing from /Users/calvin/tesseract/training/eng.lstm
Loaded 5/5 lines (1-5) of document /Users/calvin/tesseract/training/eng.myfont.exp0.lstmf
Iteration 0: GROUND  TRUTH : 0124567890
Iteration 0: BEST OCR TEXT : 8124567898
File eng.myfont.exp0.lstmf line 0 :
Mean rms=2.635%, delta=7.463%, train=40%(100%), skip ratio=0%
Iteration 1: GROUND  TRUTH : RSTUVWXYZ
Iteration 1: BEST OCR TEXT : RSTUUWSEYZ
File eng.myfont.exp0.lstmf line 1 :
Mean rms=2.764%, delta=8.649%, train=47.778%(100%), skip ratio=0%
..........
..........
At iteration 15/1100/1100, mean rms=0.033%, delta=0.000%, BCER train=0.000%, BWER train=0.000%, 
skip ratio=0.000%, New best BCER = 0.000 wrote best model:/Users/calvin/tesseract/training/_0.000_15_1100.checkpoint wrote checkpoint.
Finished! Selected model with minimal training error rate (BCER) = 0

3.7 模型训练 - 基于训练结果生成模型文件

使用lstmtraining命令结束训练,这一步将生成traineddata模型文件:

lstmtraining --stop_training 
--traineddata="/Users/calvin/tesseract/training/eng.traineddata" 
--continue_from="/Users/calvin/tesseract/training/_checkpoint" 
--model_output="/Users/calvin/tesseract/training/yx.traineddata"
  • –stop_training 停止训练
  • –traineddata 训练使用的字体
  • –continue_from 训练中间文件名称
  • –model_output 生成模型文件的名称

输出日志:

Loaded file /Users/calvin/tesseract/training/_checkpoint, unpacking...

3.8 模型测试

最后将生成的yx.traineddata文件拷贝到tesseract安装目录的tessdata路径下,即完成字体的安装。再次使用2.2中提及的命令,对我们的模型进行测试:

tesseract <input-pic-path> <output-path> -l yx --psm 7

result
可以看到,在我们的新模型下,图片的OCR识别效果得到了很大的改善,错误率明显降低

4. 模型准确率优化

从前面的训练步骤可以看到,开始训练时需要用到一个已存在的模型eng.traineddata,比如第3.4步抽取它的lstm文件、第3.6步的训练等。既然这个原始字体训练出来的新字体识别的准确率不高,那我们是不是可以用训练好的新字体替代eng.traineddata再训练一次呢,这样产生的第2代的新字体会不会有更好地表现?
基于参考文献[4]中的测试结果,在大量测试数据下,第二次迭代后的识别准确率是要明显高于第一次的,且不受psm识别模式的影响,同时在后续第三次、第四次、第五次迭代后准确率则提升不明显
retrain
因此,在兼顾效率和准确率的前提下,我们选择可以对模型进行二次迭代优化,回到步骤3.4步~步骤3.7,将eng.traineddata相关的内容替换为yx.traineddata,新生成的第2代模型取名为yx2.traineddata,得到更高精度的字体识别模型。

5. 模型在移动端上的落地应用

all
模型在移动端上的落地应用需要分三层工作来完成:

  • 模型的训练放到本地进行,经过反复测试、优化,将训练好的文件模型上传到服务器。
  • 服务器负责为移动端提供接口,提供简单的版本管理和资源下发。
  • 应用端基于Tesseract SDK提供模型解析环境,并将模型应用于具体的OCR场景中。

6. 总结与后续工作

基于上文的训练过程,我们完成了针对特定字体的OCR模型识别训练,和通用模型相比,我们在特定字体场景下具有更高程度的OCR识别准确度。后续的工作主要从以下两方面进行:

  • 大量测试与纠错优化
    使用更多的购物卡对模型进行测试,若出现识别错误,则基于出错样本对已有模型继续进行训练优化。
  • 移动端上的资源下载/管理的能力建设
    生成的模型的大小约15MB左右,说大不大,说小也不小。可以肯定的是,无论如何都不可能把模型内置于移动端的安装包中,原则上是按需下发加载,因此需要移动端上具有资源下载的基础能力,需要考虑资源下载失败、版本更新、完整性校验等工作。最后,模型的下发与否需要遵从用户的意愿,因此在业务层面,需要保留OCR和手动输入两种入口。

7. 参考文献

  1. OCR Engine Comparison — Tesseract vs. EasyOCR

  2. Tesseract OCR in Python with Pytesseract andOpenCV

  3. Tesseract-OCR页面分割模式 (PSM) 使用详解

  4. Tesseract-OCR5.0字体训练以及提高准确率、提升训练效率的方法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

城市易涝点监测,内涝积水监测仪的作用

近些年城市内涝问题格外突出&#xff0c;市民心中总在担心是不是哪一天自己的家园因为内涝&#xff0c;从而短时间内无法正常生活。并且内涝过后的淤泥可能堆积到路边或者居民住宅区等地&#xff0c;这会影响城市生态环境和公共卫生。 内涝积水监测仪为解决城市内涝问题提供了更…

专业远程控制如何塑造安全体系?向日葵“全流程安全闭环”解析

安全是远程控制的重中之重&#xff0c;作为国民级远程控制品牌&#xff0c;向日葵远程控制就极为注重安全远控服务的塑造。近期向日葵发布了以安全和核心的新版“向日葵15”以及同步发布《贝锐向日葵远控安全标准白皮书》&#xff08;下简称《白皮书》&#xff09;&#xff0c;…

Redis性能压测、监控工具及优化方案

Redis是一款高性能的开源缓存数据库&#xff0c;但是在实际应用中&#xff0c;我们需要对Redis进行性能压测、监控以及优化&#xff0c;以确保其稳定性和高可用性。本文将介绍Redis性能压测、监控工具及优化方案。 01 Redis性能压测 常用的Redis性能压测工具有&#xff1a; …

git的实验:cherry-pick,github对比代码的两种方式

某个commit&#xff0c;比如 c1&#xff0c;&#xff0c;最早是在a分支做的&#xff0c;当被cherry-pick到b分之后&#xff0c;还是一样的revision吗&#xff1f; 实验1&#xff1a;c1被cherry-pick到别的分支后&#xff0c;revision不变对吗&#xff1f;&#xff08;答案是变…

在矩池云使用安装AgentTuning

AgentTuning 是清华大学和智谱AI共同推出的 AI Agent方案。 AgentTuning可以令LLM具备更强大的泛化能力&#xff0c;而且同时保持其通用语言能力&#xff0c;项目中包含的AgentInstruct 数据集和 AgentLM 模型均已开源。 项目地址&#xff1a;https://github.com/THUDM/Agent…

免费图书教材配套资料:Spark大数据技术与应用(第2版)

《Spark大数据技术与应用&#xff08;第2版&#xff09;》课程内容全面介绍了Spark大数据技术的相关知识&#xff0c;内容包含包括Spark概述、Scala基础、Spark编程、Spark编程进阶、Spark SQL结构化数据文件处理、Spark Streaming实时计算框架、Spark GraphX图计算框架、Spark…

OSG文字-HUD显示汉字示例(3)

显示文字是一种非常实用的技术&#xff0c;可以用来把一些重要的文字始终显示在屏幕上。HUD的全称是HeadsUpDisplay&#xff0c;即抬头显示&#xff0c;这种技术最早应用在军事战斗机上。 创建HUD显示的基本步骤如下: <1> 创建一个osg::Camera对象&#xff0c;设置视图、…

接口自动化中cookies的处理技术

一&#xff0c;理论知识 为什么有cookie和session&#xff1f; 因为http协议是一种无状态的协议&#xff0c;即每次服务端接受到客户端的请求时都时一个全新的请求&#xff0c;服务器并不知道客户端的请求记录&#xff0c;session和cookie主要目的就是弥补http的无状态特性 …

shell脚本之循环语句(for、while、untli)

循环语句&#xff1a; 一定要有跳出循环条件 循环条件&#xff1a; 1.已知循环的次数&#xff08;新来十个人&#xff0c;就要新建十个账号 2.未知循环的次数&#xff0c;但是要有跳出循环条件&#xff08;对象生气&#xff0c;要道歉到原谅为止&#xff09; for&#xff…

AI的未来!Salesforce发布2024年全球科技的重要预测

Salesforce领导者处于影响企业的最新趋势、技术和挑战的前线&#xff0c;通过市场分析、客户对话等方面带来专业知识和洞察力。毫无疑问&#xff0c;人工智能是本年度的最热话题&#xff0c;Salesforce关于技术和人工智能的预测值得关注。 生成式AI改变商业未来的方式 01 生…

Centos7安装Cesi(Supervisor集中管理工具)

Background CeSi 是 Supervisor 官方推荐的集中化管理 Supervisor 实例的 Web UI&#xff0c;该工具是用 Python 编写&#xff0c;基于 Flask Web 框架 。Superviosr 自带的 Web UI 不支持跨机器管理Supervisor 进程&#xff0c;功能比较简单&#xff0c;通过 CeSi 可以集中管理…

Android修行手册-POI操作Excel文档

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

利用QRCode.js生成动态二维码页面

文章目录 QRCode.js简介HTML结构JavaScript生成动态二维码拓展功能1. 联系信息二维码2. Wi-Fi网络信息二维码 总结 &#x1f389;利用QRCode.js生成动态二维码页面 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文章专栏…

前端数组方法汇总集锦

前言 数组主要使用场景有&#xff1a; 存储和处理数据&#xff1a;数组是一种有序的数据结构&#xff0c;可以用来存储和处理多个相关的数据。在前端开发中&#xff0c;我们经常使用数组来存储和处理列表、表格、选项等数据。 循环和遍历&#xff1a;数组提供了循环和遍历的功能…

循环队列详解!!c 语言版本(两种方法)双向链表和数组法!!

目录 1.什么是循环队列 2.循环队列的实现&#xff08;两种方法&#xff09; 第一种方法 数组法 1.源代码 2.源代码详解&#xff01;&#xff01; 1.创造队列空间和struct变量 2.队列判空 3.队列判满&#xff08;重点&#xff09; 4.队列的元素插入 5.队列的元素删除 …

网络工程师-HCIA网课视频学习(更换策略,这个网课质量不行)

这里是速成的&#xff0c;只积累下&#xff0c;自己未曾学习到的东西。通过书本补充知识点。 视频&#xff1a;hcia17-链路聚合_哔哩哔哩_bilibili hcia16-路由高级特性&#xff1a; hcia17-链路聚合&#xff1a; 由于如果根据视频来学习的话&#xff0c;感觉视频的总结并不…

MySQL数据库常见错误及解决方案

“时记数据安全,共享优质资源”,数据库安全是指数据库数据的完整、真实、可靠和可用性。数据库也是一种软件系统,与其他软件系统一样也需要保护,需要采取一定的技术和一定的安全管理策略,保证数据库中的数据不被泄漏、不被破坏、不被修改或删除。本文列举MySQL数据库常见错…

VulnHub DC-9

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

如何做好性能压测?压测环境设计和搭建的7个步骤你知道吗?

简介&#xff1a;一般来说&#xff0c;保证执行性能压测的环境和生产环境高度一致是执行一次有效性能压测的首要原则。有时候&#xff0c;即便是压测环境和生产环境有很细微的差别&#xff0c;都有可能导致整个压测活动评测出来的结果不准确。 1. 性能环境要考虑的要素 1.1 系…

HCIA-Datacom跟官方路线学习

通过两次更换策略。最后找到最终的学习方案&#xff0c;华为ICT官网有对这个路线的学习&#xff0c;hcia基础有这个学习路线&#xff0c;hcip也有目录路线。所以&#xff0c;最后制定学习路线&#xff0c;是根据这个认证的路线进行学习了&#xff1a; 官网课程&#xff1a;课程…