EasyOCR——超强超便捷的OCR开源算法介绍与文本检测模型CRAFT微调方法

背景

最近在实际操作阿拉伯文小语种OCR功能的时候,尝试了诸多开源算法,但效果均不尽如人意。

说实在的,针对阿拉伯文的OCR开源算法,若仅仅是效果没那么优秀,比如识别率能有个70%80%,我还能微调微调,但是现在很多开源算法连最基础的识别率都不能保证,丝毫没有微调的可能性,这和从头训练没有区别!

但是前几天以一种不抱希望的态度尝试EasyOCR里面阿拉伯文模型的时候,带给了我惊喜,在我实际操作使用的过程中,easyOCR算法无论在实际效果、运行效率、易操作性都大大领先与一众其他的OCR开源算法。

本文则重点介绍EasyOCR算法中CRAFT文本检测模型的微调方法

EasyOCR简介

一般的OCR算法主要分三步走:

  • 文本检测模型框出待检测图像内的文本,并输出文本框的坐标描述。
  • 文本分割模型分割文本框内的文本,最终输出字符的文本框坐标描述
  • 文本识别模型针对每个字符进行识别,并最终输出

显然这种方式丢失了各个字符之间的相互关系信息,使得前后字符无法互相纠错,识别率自然大大降低。

故EasyOCR将后续两步进行了大修,先用基础的ResNet进行特征提取,后采用了时间序列的循环神经网络LSTM和CTC解码的方式进行整体单词的识别和输出,这使得EasyOCR在对于一些基于字母排列顺序的文本识别效果极佳(例如:英文、阿拉伯文、德语……)

EasyOCR详细的架构图如下

CRAFT微调方法

其实官网有详细的说明文档,本文也是基于官网的操作步骤进行补充说明,以期使得更加易懂和富有操作性。

官网连接如下:

EasyOCR/trainer/craft/README.md at master · JaidedAI/EasyOCR · GitHub

step1:安装相关项目和库

1. 下载项目

git clone https://github.com/JaidedAI/EasyOCR.git

2. 安装相关库

进入项目根目录下的trainer\craft文件夹,并执行:
pip install -r requirements.txt

注:实测并非一定要求版本号一模一样,具体的可以按照自己的环境配置具体试试

conda==4.10.3
opencv-python==4.5.3.56
Pillow==9.3.0
Polygon3==3.0.9.1
PyYAML==5.4.1
scikit-image==0.17.2
Shapely==1.8.0
torch==1.13.1
torchvision==0.10.0
wandb==0.12.9

step2:准备本地数据集

1. craft文件夹下文件树结构介绍

trainer\craft文件目录下的文件树如下所示,重点为下列加粗红色标记的文件

├── config(放置训练时候的配置文件)
│   ├── syn_train.yaml
│   └── custom_data_train.yaml(本地训练使用的yaml)
├── data
│   ├── pseudo_label
│   │   ├── make_charbox.py
│   │   └── watershed.py
│   ├── boxEnlarge.py
│   ├── dataset.py
│   ├── gaussian.py
│   ├── imgaug.py
│   └── imgproc.py
├── loss
│   └── mseloss.py
├── metrics
│   └── eval_det_iou.py
├── model
│   ├── craft.py
│   └── vgg16_bn.py
├── utils
│   ├── craft_utils.py
│   ├── inference_boxes.py
│   └── utils.py
├── trainSynth.py
├── train.py(训练程序入口)
├── train_distributed.py
├── eval.py
├── data_root_dir   (数据集存放位置)
└── exp  (模型输出位置) 

 2. 数据集结构说明

└── data_root_dir (you can change root dir in yaml file)
    ├── ch4_training_images(存放训练图片)
    │   ├── img_1.jpg
    │   └── img_2.jpg
    ├── ch4_training_localization_transcription_gt((存放所有图片的标签文件))
    │   ├── gt_img_1.txt
    │   └── gt_img_2.txt
    └── ch4_test_images(存放测试图片)
        ├── img_1.jpg
        └── img_2.jpg

注:ch4_training_localization_transcription_gt文件夹内的label文本命名方式是图片名称前面增加gt_!

 label文本文件的结构如下:

x1,71x2,y2,x3,y3,x4,y4,txt(文本内容)

 对应的图形化说明如下:

label文本文件的一个示例如下: 

 377,117,463,117,465,130,378,130,Genaxis Theatre
 493,115,519,115,519,131,493,131,[06]
 374,155,409,155,409,170,374,170,###  

3. 使用labelimg来帮助标注

easyocr的标注格式奇奇怪怪的,没找到合适的标注软件,之前常用labelimg来进行模型标注,相似的标注格式为YOLO的图像标注,故采用labelimg来进行标注。若读者有更好的标注方式,请评论告知,满城百姓,感谢不尽!

我猜测easyocr还支持相似变换的OCR功能,所以标注文件需要把四个点的坐标都输出,以支持类似平行四边形、梯形的文本框。(待验证)

注意:YOLO 的标注文件的格式为:

类别id 检测框中心坐标x 检测框中心坐标y 检测框长度 检测框宽度

我们需要自己手动进行一个格式的转换,可尝试使用python代码如下:

yolo标签格式转easyocr标签格式: 

def yolo_to_corners(txt_file_path, img_path):  # 读取图像尺寸  img = cv2.imread(img_path)  img_height, img_width, _ = img.shape  # 读取YOLO格式的标签文件  with open(txt_file_path, 'r') as f:  lines = f.readlines()  results = []for line in lines:  parts = line.strip().split(' ')  cls = int(parts[0])  x_center = float(parts[1])  y_center = float(parts[2])  width = float(parts[3])  height = float(parts[4])  # 将相对坐标转换为绝对像素坐标  x_center_px = int(x_center * img_width)  y_center_px = int(y_center * img_height)  half_width = int(width * img_width / 2)  half_height = int(height * img_height / 2)  # 计算四个角的坐标  x1, y1 = x_center_px - half_width, y_center_px - half_height  x2, y2 = x_center_px + half_width, y_center_px - half_heightx3, y3 = x_center_px + half_width, y_center_px + half_height  x4, y4 = x_center_px - half_width, y_center_px + half_height results.append(f"{x1},{y1},{x2},{y2},{x3},{y3},{x4},{y4},txt")return results

step3:下载预训练模型,并更新config配置 

1. 下载预训练模型

官方链接如下:

https://drive.google.com/file/d/1enVIsgNvBf3YiRsVkxodspOn55PIK-LJ/view?usp=sharing

下载完毕后,放于EasyOCR\trainer\craft\pretrained_model目录下,若没有pretrained_model目录,自己新建一个即可。

2. 更新config配置

进入config文件夹,里面有一个custom_data_train.yaml文件。

若你是根据上诉步骤一步步来的,实际上无需修改任何配置,但是也许你可以修改一下end_iter字段,这个是训练轮次的意思,原来数据为25000,一开始你可以设置的小一点。

总之我的custom_data_train.yaml文件内容如下:

wandb_opt: False

results_dir: "./exp/"
vis_test_dir: "./vis_result/"

data_root_dir: "./data_root_dir/"
score_gt_dir: None # "/data/ICDAR2015_official_supervision"
mode: "weak_supervision"


train:
  backbone : vgg
  use_synthtext: False # If you want to combine SynthText in train time as CRAFT did, you can turn on this option
  synth_data_dir: "/data/SynthText/"
  synth_ratio: 5
  real_dataset: custom
  ckpt_path: "./pretrained_model/CRAFT_clr_amp_29500.pth"
  eval_interval: 1000
  batch_size: 5
  st_iter: 0
  end_iter: 25
  lr: 0.0001
  lr_decay: 7500
  gamma: 0.2
  weight_decay: 0.00001
  num_workers: 0 # On single gpu, train.py execution only works when num worker = 0 / On multi-gpu, you can set num_worker > 0 to speed up
  amp: True
  loss: 2
  neg_rto: 0.3
  n_min_neg: 5000
  data:
    vis_opt: False
    pseudo_vis_opt: False
    output_size: 768
    do_not_care_label: ['###', '']
    mean: [0.485, 0.456, 0.406]
    variance: [0.229, 0.224, 0.225]
    enlarge_region : [0.5, 0.5] # x axis, y axis
    enlarge_affinity: [0.5, 0.5]
    gauss_init_size: 200
    gauss_sigma: 40
    watershed:
      version: "skimage"
      sure_fg_th: 0.75
      sure_bg_th: 0.05
    syn_sample: -1
    custom_sample: -1
    syn_aug:
      random_scale:
        range: [1.0, 1.5, 2.0]
        option: False
      random_rotate:
        max_angle: 20
        option: False
      random_crop:
        version: "random_resize_crop_synth"
        option: True
      random_horizontal_flip:
        option: False
      random_colorjitter:
        brightness: 0.2
        contrast: 0.2
        saturation: 0.2
        hue: 0.2
        option: True
    custom_aug:
      random_scale:
        range: [ 1.0, 1.5, 2.0 ]
        option: False
      random_rotate:
        max_angle: 20
        option: True
      random_crop:
        version: "random_resize_crop"
        scale: [0.03, 0.4]
        ratio: [0.75, 1.33]
        rnd_threshold: 1.0
        option: True
      random_horizontal_flip:
        option: True
      random_colorjitter:
        brightness: 0.2
        contrast: 0.2
        saturation: 0.2
        hue: 0.2
        option: True

test:
  trained_model : null
  custom_data:
    test_set_size: 500
    test_data_dir: "./data_root_dir/"
    text_threshold: 0.75
    low_text: 0.5
    link_threshold: 0.2
    canvas_size: 2240
    mag_ratio: 1.75
    poly: False
    cuda: True
    vis_opt: False

step3:微调训练开始!

进入EasyOCR\trainer\craft目录运行如下代码:

python train.py --yaml=custom_data_train 

然后静待结束即可 。训练完成的模型输出目录为:EasyOCR\trainer\craft\exp\custom_data_train

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

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

相关文章

【React系列三】—React学习历程的分享

一、组件实例核心—Refs 通过定义 ref 属性可以给标签添加标识 字符串形式的Refs 这种形式已经不再推荐使用&#xff0c;官方不建议使用 https://zh-hans.legacy.reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs 回调形式的Refs <script type"te…

PostgreSQL中触发器递归的处理 | 翻译

许多初学者在某个时候都会陷入触发器递归的陷阱。通常&#xff0c;解决方案是完全避免递归。但对于某些用例&#xff0c;您可能必须处理触发器递归。本文将告诉您有关该主题需要了解的内容。如果您曾经被错误消息“超出堆栈深度限制”所困扰&#xff0c;那么这里就是解决方案。…

Pytest参数详解 — 基于命令行模式!

1、--collect-only 查看在给定的配置下哪些测试用例会被执行 2、-k 使用表达式来指定希望运行的测试用例。如果测试名是唯一的或者多个测试名的前缀或者后缀相同&#xff0c;可以使用表达式来快速定位&#xff0c;例如&#xff1a; 命令行-k参数.png 3、-m 标记&#xff08;…

msql事务隔离级别 线上问题

1. 对应代码 解决方式&#xff1a; 在事务隔离级别为可重复读&#xff08;RR&#xff09;时&#xff0c;数据库确实通常会记录当前数据的快照。 在可重复读隔离级别下&#xff0c;事务在执行期间看到的数据是事务开始时的数据快照&#xff0c;即使其他事务对数据进行了修改&am…

Lucas带你手撕机器学习——线性回归

什么是线性回归 线性回归是机器学习中的基础算法之一&#xff0c;用于预测一个连续的输出值。它假设输入特征与输出值之间的关系是线性关系&#xff0c;即目标变量是输入变量的线性组合。我们可以从代码实现的角度来学习线性回归&#xff0c;包括如何使用 Python 进行简单的线…

2024 最新版1200道互联网大厂Java面试题附答案详解

很多 Java 工程师的技术不错&#xff0c;但是一面试就头疼&#xff0c;10 次面试 9 次都是被刷&#xff0c;过的那次还是去了家不知名的小公司。 问题就在于&#xff1a;面试有技巧&#xff0c;而你不会把自己的能力表达给面试官。 应届生&#xff1a;你该如何准备简历&#…

4、CSS3笔记

文章目录 四、CSS3CSS3简介css3概述CSS3私有前缀什么是私有前缀为什么要有私有前缀常见浏览器私有前缀 CSS3基本语法CSS3新增长度单位CSS3新增颜色设置方式CSS3新增选择器CSS3新增盒模型相关属性box-sizing 怪异盒模型resize 调整盒子大小box-shadow 盒子阴影opacity 不透明度 …

【ChatGPT插件漏洞三连发之一】未授权恶意插件安装

漏洞 要了解第一个漏洞&#xff0c;我们必须首先向您展示 OAuth 身份验证的工作原理&#xff1a; 假设您是 Dan&#xff0c;并且您想使用您的 Facebook 帐户连接到 Example.com。当您点击“使用Facebook登录”时会发生什么&#xff1f; 在步骤 2-3 中&#xff1a; 在 Dan 单…

QT枚举类型转字符串和使用QDebug<<重载输出私有枚举类型

一 将QT自带的枚举类型转换为QString 需要的头文件&#xff1a; #include <QMetaObject> #include <QMetaEnum> 测试代码 const QMetaObject *metaObject &QImage::staticMetaObject;QMetaEnum metaEnum metaObject->enumerator(metaObject->indexOf…

【ubuntu18.04】ubuntu18.04升级cmake-3.29.8及还原系统自带cmake操作说明

参考链接 cmake升级、更新&#xff08;ubuntu18.04&#xff09;-CSDN博客 升级cmake操作说明 下载链接 Download CMake 下载版本 下载软件包 cmake-3.30.3-linux-x86_64.tar.gz 拷贝软件包到虚拟机 cp /var/run/vmblock-fuse/blockdir/jrY8KS/cmake-3.29.8-linux-x86_64…

详解mac系统通过brew安装mongodb与使用

本文目录 一、通过brew安装MongoDB二、mongodb使用示例1、启动数据库2、创建/删除数据库3、创建/删除集合 三、MongoDB基本概念1&#xff09;数据库 (database)2&#xff09;集合 &#xff08;collection&#xff09;3) 文档&#xff08;document&#xff09;4&#xff09;mong…

什么是感知与计算融合?

感知与计算融合&#xff08;Perception-Computing Fusion&#xff09;是指将感知技术&#xff08;如传感器、摄像头等&#xff09;与计算技术&#xff08;如数据处理、人工智能等&#xff09;有机结合&#xff0c;以实现对环境的更深层次理解和智能反应的过程。该技术广泛应用于…

基于ISO13400实现的并行刷写策略

一 背景及挑战 随着车辆智能化的逐渐普及&#xff0c;整车控制器数量的急剧增加&#xff0c;加之软件版本的迭代愈发频繁&#xff0c;使整车控制器刷写的数据量变得越来越大。面对如此多的控制器刷写&#xff0c;通过传统的控制器顺序刷写则易出现刷写时间过长的情况&#xff…

将本地文件上传到GIT上

上传文件时&#xff0c;先新建一个空文件&#xff0c;进行本地库初始化&#xff0c;再进行远程库克隆&#xff0c;将要上传的文件放到克隆下来的文件夹里边&#xff0c;再进行后续操作 1.在本地创建文件夹&#xff0c;将要上传的文件放在该文件下 2.在该文件页面中打开Git Bas…

免登录H5快手商城系统/抖音小店商城全开源运营版本

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 最近因为直播需要然后在互站花500买了一套仿抖音的商城系统&#xff0c;感觉确实还可以&#xff0c;反正都买了所以就分享给有需要的人 以下是互站那边的网站介绍可以了看一下&#…

【路径规划】基于蚁群算法的飞行冲突解脱

摘要 飞行冲突解脱是空中交通管理中的重要问题&#xff0c;确保飞机之间安全的距离避免冲突尤为重要。本文提出了一种基于蚁群算法的飞行冲突解脱方法&#xff0c;通过优化飞行器的路径&#xff0c;实现冲突的有效解脱。蚁群算法是一种模拟蚂蚁觅食行为的启发式算法&#xff0…

大厂为什么要禁止使用数据库自增主键

大表为何不能用自增主键&#xff1f; 数据库自增主键&#xff0c;以mysql为例&#xff0c;设置表的ID列为自动递增&#xff0c;便可以在插入数据时&#xff0c;ID字段值自动从1开始自动增长&#xff0c;不需要人为干预。 在小公司&#xff0c;或者自己做项目时&#xff0c;设置…

爬虫基础--requests模块

1、requests模块的认识 requests模块的认识请跳转到 requests请求库使用_使用requests库-CSDN博客 2、爬取数据 这里我们以b站动漫追番人数为例。 首先进去b站官网 鼠标右键点击检查或者键盘的F12&#xff0c;进入开发者模式。&#xff08;这里我使用的是谷歌浏览器为例&#…

二分查找_ x 的平方根搜索插入位置山脉数组的峰顶索引

x 的平方根 在0~X中肯定有数的平方大于X&#xff0c;这是肯定的。我们需要从中找出一个数的平方最接近X且不大于X。0~X递增&#xff0c;它们的平方也是递增的&#xff0c;这样我们就可以用二分查找。 我们找出的数的平方是<或者恰好X&#xff0c;所以把0~X的平方分为<X …

Elasticsearch是做什么的?

初识elasticsearch 官方网站&#xff1a;Elasticsearch&#xff1a;官方分布式搜索和分析引擎 | Elastic Elasticsearch是做什么的&#xff1f; Elasticsearch 是一个分布式搜索和分析引擎&#xff0c;专门用于处理大规模数据的实时搜索、分析和存储。它基于 Apache Lucene …