PP-OCR

article/2025/9/24 12:41:09

论文: PP-OCR: A Practical Ultra Lightweight OCR System

Github:https://github.com/PaddlePaddle/PaddleOCR

 

 

百度开源的ocr检测+识别系统,称为PP-OCR。PP-OCR的中文字符识别模型仅3.5M,支持识别6622个中文字符。英文字符识别模型2.8M,支持识别63个英文字符。并且PP-OCR还支持识别法语,韩语,日语,德语等多国语言。

 

整体流程

首先输入待检测图片,然后进行文本行的检测。对检测出来的每一个文本行进行方向检测。对进行方向矫正后的文本行进行文本识别,得到最终的结果。

 

文本检测

文本检测使用了 Differentiable Binarization (DB)算法,模型大小仅仅1.4M。

整个网络结构的基本思想还是基于特征融合FPN的思想。红色的框,表示模型的主干网络结构,使用了 MobileNetV3 large x0.5灰色的框表示头部预测分支。使用该方法可以实现横,纵,曲形,文本的检测。

主要使用的核心技术,

Light Backbone

基于MobileNetV3拥有比MobileNetV1,MobileNetV2, ShuffleNetV2 在同等参数量下更好的精度,同时基于速度的考虑,使用了MobileNetV3 large x0.5网络结构。

Light Head

这里基于FPN思想,使用了轻量化的头部预测分支。在FPN特征融合这一步,一般使用1*1的卷积实现将通道数对齐。实验证明,当内部通道数从256变为96,模型大小将会从7M变为4.1M,但是准确性下降很少。

Remove SE

squeeze-and-excitation模块在SENet中提出,本质是一种通道attention的机制,取得了不错的效果。

但是,当输入图片分辨率较大的时候,比如640*640,这时SE模块的效果带来的精度提升就比较有限,反而造成了较大的推理时间开销。

因此,这里去掉了SE模块。

Cosine Learning Rate Decay

cos形式的学习策略,可以使得训练得到更佳的训练模型。

Learning Rate Warm-up

训练过程使用学习率热启动策略,可以使得训练结果更好。

FPGM Pruner

使用FPGM方法进行减枝。

 

方向分类

对于每一行的文本,使用了文本方向分类模型进行分类。

主要使用的核心技术,

Light Backbone

使用轻量化的网络结构MobileNetV3 small x0.35。

Data Augmentation

使用的数据增强包括,旋转变换,反射变换,运动模糊,高斯噪声,随机数据增强 RandAugmen。其中,RandAugmen取得了最好的效果。

Input Resolution

在 PP-OCR中,输入图片的高度为48,宽度为192。

PACT Quantization

量化包含离线量化(offline quantization ),在线量化(online quantization)两种方法。在线量化可以获得比离线量化更好的精度。这里使用了PACT在线量化方法,该方法基于 PaddleSlim实现。

原始的PACT量化方法,

改进后的PACT量化,

 

文本识别

文本识别采用了CRNN这种基于ctc解码的方法。

主要使用的核心技术,

Light Backbone

这里使用了轻量化网络结构 MobileNetV3 small x0.5。

Data Augmentation

基于TIA方法的数据增强。

Cosine Learning Rate Decay

cos形式的学习策略,可以使得训练得到更佳的训练模型。

Feature Map Resolution

CRNN输入图片的高度为32,宽度为320。

Regularization Parameters

这里使用了权值衰减 weight decay来防止过拟合。使用了L2正则化 L2 regularization使得模型学习的参数都更加接近于0。

Learning Rate Warm-up

训练过程使用学习率热启动策略,可以使得训练结果更好。

Light Head

轻量化的头部结构,这里将CRNN的全连接层的特征大小设置为48。

Pre-trained Model

使用 ImageNet预训练模型,可以使得模型的精度更高。

PACT Quantization

除去CRNN模型中的LSTM模块,其他部门都进行PACT量化。

 

实验结果

 

模型对比:

模型介绍模型名字推荐场景检测模型方向模型识别模型gpu允许速度(2080ti)gpu允许显存
Chinese and English ultra-lightweight OCR model (9.4M)ch_ppocr_mobile_v2.0_xxMobile & server3.1M1.4M5.0M70ms10G
Chinese and English general OCR model (143.4M)ch_ppocr_server_v2.0_xxServer48M1.4M108M130ms8.4G

 

 

 

 

检测模型,修改ppocr/data/imaug/operators.py,保证对输入图片进行resize 操作,保证输入网络图片的最长边不超过960像素,从而保证显存够用。否则遇到大图片可能32G显存都不够。

class DetResizeForTest(object):def __init__(self, **kwargs):super(DetResizeForTest, self).__init__()self.resize_type = 0if 'image_shape' in kwargs:self.image_shape = kwargs['image_shape']self.resize_type = 1elif 'limit_side_len' in kwargs:self.limit_side_len = kwargs['limit_side_len']self.limit_type = kwargs.get('limit_type', 'min')elif 'resize_long' in kwargs:self.resize_type = 2self.resize_long = kwargs.get('resize_long', 960)else:#self.limit_side_len = 736#self.limit_type = 'min'self.limit_side_len = 960self.limit_type = 'max'

方向分类模型,即使按照默认设置"cls_batch_num",30个batch,所占用的显存也非常少,也就增加100M显存的样子。

识别模型,1个batch 和30batch的显存占用是有很大区别的,大概4个G的差别。所以可以根据显卡显存大小,合理设置"rec_batch_num".

经过测试,最小的情况下,大概需要2个G(3个G以内稳妥),才可以跑起来整个流程。

 

安装:

python3 -m pip install paddlepaddle-gpu==2.0.0 -i https://mirror.baidu.com/pypi/simple
pip3 install -r requirements.txt

 

实际测试:

import os
import cv2
import numpy as np
from paddleocr import PaddleOCR
# Paddleocr目前支持中英文、英文、法语、德语、韩语、日语,可以通过修改lang参数进行切换
# 参数依次为`ch`, `en`, `french`, `german`, `korean`, `japan`。def draw_ocr(img, boxes, txts, scores):import randomfrom PIL import Imagefrom PIL import ImageFont,ImageDrawbg = np.ones_like(img)*255fg = np.zeros_like(img)img_PIL_bg = Image.fromarray(cv2.cvtColor(bg,cv2.COLOR_BGR2RGB))img_PIL_fg = Image.fromarray(cv2.cvtColor(fg,cv2.COLOR_BGR2RGB))font = ImageFont.truetype('StyleText/fonts/ch_standard.ttf',10)fillColor = (0,0,0)#if not isinstance(chinese,unicode):#chinese = chinese.decode('utf-8')draw_bg = ImageDraw.Draw(img_PIL_bg)draw_fg = ImageDraw.Draw(img_PIL_fg)for box, txt , score in zip(boxes, txts, scores):tuple_polygon = (box[0][0], box[0][1], box[1][0],box[1][1], box[2][0],box[2][1], box[3][0],box[3][1])color = (random.randint(0,255),random.randint(0,255),random.randint(0,255))draw_bg.polygon(tuple_polygon, fill = color)draw_fg.polygon(tuple_polygon, fill = color)draw_bg.text(box[0] , " ".join([txt,str(float(score))]),font=font,fill=fillColor)img_bg = cv2.cvtColor(np.asarray(img_PIL_bg),cv2.COLOR_RGB2BGR)img_fg = cv2.cvtColor(np.asarray(img_PIL_fg),cv2.COLOR_RGB2BGR)return np.hstack([cv2.addWeighted(img, 0.5, img_fg, 0.5, gamma=0), img_bg])def test_one_image():# smallocr = PaddleOCR(det_model_dir="models/ultra-lightweight_2.0/det/",rec_model_dir="models/ultra-lightweight_2.0/rec/ch/",rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",cls_model_dir="models/ultra-lightweight_2.0/cls/",use_angle_cls=True,lang="ch") # need to run only once to download and load model into memory# bigocr = PaddleOCR(det_model_dir="models/general_2.0/det/",rec_model_dir="models/general_2.0/rec/ch/",rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",cls_model_dir="models/general_2.0/cls/",use_angle_cls=True,lang="ch") # need to run only once to download and load model into memoryimg_path = 'doc/imgs/11.jpg'img = cv2.imread(img_path)result = ocr.ocr(img, cls=True)boxes = [line[0] for line in result]txts = [line[1][0] for line in result]scores = [line[1][1] for line in result]for box, txt , score in zip(boxes, txts, scores):print(box, txt, score)draw_out = draw_ocr(img, boxes, txts, scores)cv2.imwrite(img_path.split("/")[-1],draw_out)def test_images():# small"""ocr = PaddleOCR(det_model_dir="models/ultra-lightweight_2.0/det/",rec_model_dir="models/ultra-lightweight_2.0/rec/ch/",rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",cls_model_dir="models/ultra-lightweight_2.0/cls/",use_angle_cls=True,lang="ch") # need to run only once to download and load model into memory"""# bigocr = PaddleOCR(det_model_dir="models/general_2.0/det/",rec_model_dir="models/general_2.0/rec/ch/",rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",cls_model_dir="models/general_2.0/cls/",use_angle_cls=True,lang="ch") # need to run only once to download and load model into memorydata_dir= "test_images/"out_dir = "out_images/"for name in os.listdir(data_dir):print(name)img_path = os.path.join(data_dir, name)img = cv2.imread(img_path)result = ocr.ocr(img, cls=True)boxes = [line[0] for line in result]txts = [line[1][0] for line in result]scores = [line[1][1] for line in result]for box, txt , score in zip(boxes, txts, scores):print(box, txt, score)draw_out = draw_ocr(img, boxes, txts, scores)cv2.imwrite(os.path.join(out_dir, name),draw_out)if __name__=="__main__":#test_one_image()test_images()

 

总结:

(1)开源的非常不错的ocr代码,精度挺高。

 


http://chatgpt.dhexx.cn/article/9CaKxYMR.shtml

相关文章

pp助手可以刷机吗android,如何使用PP助手进行刷机?

PP助手官方版是当前最适合的苹果助手,iPhone/iTouch/iPad通通完美支持,个性铃声自制,一键越狱插件安装、资料备份、SHSH管理等通通都具备,PP助手官方版汇集了很多大型热门游戏软件,统统一键即可简单下载!今天在这里小编…

pp助手可以刷机吗android,pp助手刷机 pp助手怎么刷机

小编今天带来pp助手刷机,pp助手怎么刷机的教程。想用pp助手刷机?要知道刷机有风险,刷机需谨慎。想清楚了,那么就进来看教程刷机吧。包教包会! 注意:刷机前一定要备份好自己的东西。 1.首先下载更新新版本pp…

pp-vehicle简介

简介 飞桨目标检测端到端开发套件PaddleDetection正式开源车辆分析工具PP-Vehicle!该工具主要包含:提供车牌识别、车辆属性分析(颜色、车型)、车流量统计以及违章检测四大功能,兼容图片、在线视频流、视频输入&#x…

PP-YOLO

PP-YOLOv2 目录 PP-YOLOv2的改进点 数据增强 : MixUp Backbone :换R50 Better Pre-Train dcn Neck : SPP CoordConv DropBlock PAN MISH Loss : IoU Loss IoU Aware Loss 其他 : Large Batch Size Grid…

PP-LiteSeg

简介 整体还是采用跳层连接结构,引入了统一注意力融合模块(空间和通道注意力机制)、金字塔模块来聚合上下文。 使用统一注意力模块来提高分割精度,通过融合解码器中的低级和高级特征来实现的,与之前的BiSeNetV2中的通道…

SPSS PP图和QQ图

P-P图和Q-Q图都是用来观察变量是否服从正太分布的。 选择菜单中的分析-描述统计-P-P图,则如下图 1变量选项栏:选择绘制pp图的变量,可多选 2检验分布选项栏:用于检测待检验分布的类型,如beta,卡方&#xff0…

PP图和QQ图以及它们意义

先说结论1: P-P图和Q-Q图的用途完全相同,只是检验方法存在差异。 如果两个分布相似,则该Q-Q图趋近于落在y=x线上。如果两分布线性相关,则点在Q-Q图上趋近于落在一条直线上,但不一定在y=x线上。 再说结论2:Q-Q图可以用来在分布的位置-尺度范畴上可视化的评估参数。 从定义…

正态性检验之QQ图与PP图

正态性检验方法有很多种,主要可以分为以下几类: 图示法统计方法正态概率图、频率直方图、PP图、QQ图偏度峰度检验、皮尔逊卡方检验、K-S检验、W检验、EP检验、秩和检验、游程检验等非参检验 按理说图示法应该是最简单的方法,但大多本科统计…

PP图,QQ 图,及 python 画图

统计学中有时会用到 PP 图 或 QQ 图,用来看样本数据是否服从某一特定分布。 若 PP 或 QQ 图中的点基本落在一条 45度 的线上,则说明服从特定分布。 一般的步骤为: 将样本数据从小到大排序,假设排序后的样本数据为 x 1 x_1 x1​…

pptp服务搭建

1 检查系统是否支持pptp cat /dev/ppp 如果输出 cat: /dev/ppp: No such device or address 则说明可以正常架设pptp服务 2 设置内核转发,开启路由转发 vi /etc/sysctl.conf 添加 net.ipv4.ip_forward1 通过下面命令查看 sysctl -p 3更新yum相关源 wget http…

VPN服务搭建流程记录

之前,一直有想法搭建一套属于自己的VPN服务,但是,一直苦于"拖延症"的困扰,没有真正实际去实践。最近,终于打破了这个困扰,所以,也希望记录一下整体的搭建流程,操作系统Cen…

Guava常用方法

目录 简介 Maven依赖 字符串检查工具 NULL值检查 先决条件检查 判断对象是否为null 操作集合 简介 Guava,中文是石榴的意思,Guava项目,是基于java的Google的开源的工具类库,包含了许多被Google的java项目广泛依赖的核心库&…

【guava】基础用法

依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>29.0-jre</version></dependency> 不可变集合与对象 优点&#xff1a;1、线程安全 2、可用作常熟 ImmutableXXX 创建方式&…

guacamole 源码_Guacamole学习笔记

1: 介绍: Guacamole可以同HTML5来代理远程桌面协议(如: VNC, RDP, Telnet, SSH) 官网: http://guac-dev.org/ 2: 架构: 架构图: image.png 架构解释: 用户通过浏览器连接到Guacamole的服务端, Guacamole通过JS写的客户端是为用户提供服务, 服务端和客户端的通信是基于HTTP的私有…

Guacamole 介绍以及架构

目前在从事一些虚拟化解决方案方面的工作&#xff0c;最近项目有需求&#xff0c;希望能在浏览器上远程操作虚拟机。 此时发现了Guacamole&#xff0c;一个提供远程桌面的解决方案的开源项目&#xff0c;通过浏览器就能操作虚拟机&#xff0c;适用于Chrome&#xff0c;Firefox&…

使用Google Guava来编写优雅的代码一Guava简介

以往我们在使用工具包的时候首先想到是著名的Apache的Commons系列,今天我要介绍的是同样出色&#xff0c;并且目前发展比Apache Commons系列更为迅速的Google Guava库。 Google Guava库是一个非常优秀的包含很多Java工具类集的库&#xff0c;广泛使用在Google公司内部&#xf…

guacamole学习小结(一)

一、快速安装 https://blog.csdn.net/qq_38781075/article/details/106459458 二、整体理解 先放一张经典的图。 guacamole最重要的作用还是连接远程服务器的&#xff0c;可以连接多台服务器&#xff0c;连接不同的远程协议的服务器。使得用户能远程快捷的访问远程桌面。它跨…

guacamole 认识

简介&#xff1a;guacamole是apache开源的一款连接远程机器(类似window机器的mstsc工具以及linux的 xfreerdp远程工具)的web应用。 官网&#xff1a;http://guacamole.apache.org/ 一、介绍 1、先看看官网提供的架构图 其中guacamole将架构图中 HTML5(JavaScript编写)以及g…

Guacamole搭建教程

目录 安装系统环境安装依赖环境安装依赖包 下载安装包服务端安装解压并安装&#xff1a;在当前目录下继续执行&#xff1a;安装完成之后&#xff0c;可以使用以下来看guacd是否安装成功&#xff1a; 客户端安装安装安装git安装maven 下载客户端并解压创建/etc/guacamole/文件目…

使用EasyDarwin+FFmpeg实现rtsp推流

一、背景 ​ 最近在学习ffmpeg的基本操作,ffmpeg功能非常强大&#xff0c;可以运行音频和视频多种格式的录影、转换、流功能&#xff0c;包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库&#xff0c;以及libavformat——一个音频与视频格式转换库 可以利用ff…