https://github.com/PaddlePaddle/PaddleOCR
https://aistudio.baidu.com/aistudio/projectdetail/1188761
项目演示视频:
中软杯国二开源——基于OCR+NLP的企业实体识别项目
https://www.bilibili.com/video/BV1aA411K7zg
OCR+NLP应用案例:Android端文字检测和企业实体识别
https://www.bilibili.com/video/BV1kK4y1h75C
PaddleOCR旨在打造一套丰富、领先、且实用的OCR工具库,助力使用者训练出更好的模型,并应用落地。基于飞桨的OCR工具库,包含总模型仅8.6M的超轻量级中文OCR,单模型支持中英文数字组合识别、竖排文本识别、长文本识别。同时支持多种文本检测、文本识别的训练算法。
https://www.paddlepaddle.org.cn/hub/scene/ocr
PaddleOCR开源的文本检测算法包括:
在 DB 算法之前,对于曲形文本的检测任务,基于分割的算法比基于回归的算法表现更好,但之前基于分割的算法,都需要进行手动设计二值化的后处理算法,将分割生成的概率图转换为文本的包围框。
该篇文章的作者提出了 Differentiable Binarization (DB),它可以在分割网络中执行二值化过程,可以自适应地设置二值化阈值,不仅简化了后处理,而且提高了文本检测的性能,并且在 5 个文本检测数据集上都取得了SOTA的效果。
主要包含三个部分:
标准二值化(Standard Binarization,SB)对于分割特征图 P ∈ R H ∗ W P\in R^{H*W} P∈RH∗W,使用下面的方式进行二值化处理:
由于上述公式中的二值方法不是可微的,因而就不能在分割网络中随着训练的过程进行优化,为了解决这个问题文章提出了一个函数来近似这个二值化过程:
其中 B ^ \hat B B^ 就是近似二值图,T是自适应的阈值图,k是膨胀因子(经验性设置k=50)。
则正样本标签和负样本标签的loss分别为:
在下图中展示了阈值图对于检测的影响,就算没有阈值图的监督,阈值图也可以很好区分文本的边界:
作者使用可变形卷积的原因是,可变形卷积可以提供更加丰富的感受野,这对于极端比例的文本检测效果有益:
此外,为了增加网络的感受野,文章在backbone的stage3、stage4、stage5使用了deformable卷积。
在训练标签的生成过程中借鉴了PSENet的方法,使用标签收缩的方式进行,这里对于搜索的offset D DD使用下面的计算方式得到:
即如图所示:
上面三个损失分量分别是分割概率损失、二值图损失、阈值图损失, α = 1.0 , β = 10.0 \alpha=1.0,\beta=10.0 α=1.0,β=10.0。
并且为了样本均衡这里使用了困难样本挖掘,保持正负样本的比例为1:3。
在推理过程中,可以使用概率图(probability map)或者近似概率图(approximate binary map)产生文本边缘框。为了提升效率,作者使用了概率图。产生预测结果分为三个步骤:
PaddleOCR基于动态图开源的文本识别算法列表:
CRNN 全称为 Convolutional Recurrent Neural Network,主要用于端到端地对不定长的文本序列进行识别,不用先对单个文字进行切割,而是将文本识别转化为时序依赖的序列学习问题,就是基于图像的序列识别。
整个CRNN网络结构包含三部分,从下到上依次为:
输入图像为灰度图像(单通道);高度为32,这是固定的,图片通过 CNN 后,高度就变为1,这点很重要;宽度为160,宽度也可以为其他的值,但需要统一,所以输入CNN的数据尺寸为 (channel, height, width)=(1, 32, 160)。
CNN的输出尺寸为 (512, 1, 40)。即 CNN 最后得到512个特征图,每个特征图的高度为1,宽度为40。
即:
因为 RNN 有梯度消失的问题,不能获取更多上下文信息,所以 CRNN 中使用的是 LSTM,LSTM 的特殊设计允许它捕获长距离依赖,不了解的话可以看一下这篇文章 对RNN和LSTM的理解。
LSTM 是单向的,它只使用过去的信息。然而,在基于图像的序列中,两个方向的上下文是相互有用且互补的。将两个LSTM,一个向前和一个向后组合到一个双向LSTM中。此外,可以堆叠多层双向LSTM,深层结构允许比浅层抽象更高层次的抽象。
这里采用的是两层各256单元的双向 LSTM 网络:
通过上面一步,我们得到了40个特征向量,每个特征向量长度为512,在 LSTM 中一个时间步就传入一个特征向量进行分类,这里一共有40个时间步。
我们知道一个特征向量就相当于原图中的一个小矩形区域,RNN 的目标就是预测这个矩形区域为哪个字符,即根据输入的特征向量,进行预测,得到所有字符的softmax概率分布,这是一个长度为字符类别数的向量,作为CTC层的输入。即输出为 40 个长度为字符类别数的向量构成的后验概率矩阵。
转录是将 RNN 对每个特征向量所做的预测转换成标签序列的过程。数学上,转录是根据每帧预测找到具有最高概率组合的标签序列。即CTC是一种对不需要对齐的Loss计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。
序列合并机制:
CTC以“-”符号代表blank,RNN 输出序列时,在文本标签中的重复的字符之间插入一个“-”,比如输出序列为“bbooo-ookk”,则最后将被映射为“book”,即有blank字符隔开的话,连续相同字符就不进行合并。即对字符序列先删除连续重复字符,然后从路径中删除所有“-”字符,这个称为解码过程,而编码则是由神经网络来实现。引入blank机制,我们就可以很好地解决重复字符的问题。
CTC 称上述变换为 β \beta β 变换,例如: β ( − − b b o o − o o o k k ) = b o o k \beta(--bboo-oookk)=book β(−−bboo−oookk)=book。然 β \beta β 变换不是单对单映射。
一些符号表示:
对于LSTM给定输入 x x x (特征向量)的情况下,输出为 l l l (对应的字符)的概率为:
p ( l ∣ x ) = ∑ π ∈ β − 1 ( l ) p ( π ∣ x ) p(l|x)=\sum_{\pi \in \beta^{-1}(l)}p(\pi|x) p(l∣x)=∑π∈β−1(l)p(π∣x)
其中 π ∈ β − 1 ( l ) \pi \in \beta^{-1}(l) π∈β−1(l) 表示经过 β \beta β 变换后为 l l l 的路径。对于任意一条路径 π \pi π 有:
p ( π ∣ x ) = ∏ t = 1 T y π t t p(\pi|x)=\prod^T_{t=1}y^t_{\pi_t} p(π∣x)=∏t=1Tyπtt
例如对于 T = 12 T=12 T=12 的路径 π 1 \pi_1 π1:
π 1 = ( − − s t t a − t − − − e ) \pi_1=(--stta-t---e) π1=(−−stta−t−−−e)
p ( π 1 ∣ x ) = y − 1 ⋅ y − 2 ⋅ y s 3 ⋅ y t 4 ⋅ y t 5 ⋅ y a 6 ⋅ y − 7 ⋅ y t 8 ⋅ y − 9 ⋅ y − 10 ⋅ y − 11 ⋅ y e 12 ⋅ p(\pi_1|x)=y^1_-\cdot y^2_-\cdot y^3_s\cdot y^4_t\cdot y^5_t\cdot y^6_a\cdot y^7_-\cdot y^8_t\cdot y^9_-\cdot y^{10}_-\cdot y^{11}_-\cdot y^{12}_e\cdot p(π1∣x)=y−1⋅y−2⋅ys3⋅yt4⋅yt5⋅ya6⋅y−7⋅yt8⋅y−9⋅y−10⋅y−11⋅ye12⋅
CTC的训练:
CTC 的训练过程本质上是通过梯度 ∂ p ( l ∣ x ) ∂ w \frac{\partial p(l|x)}{\partial w} ∂w∂p(l∣x) 调整 LSTM 的参数 w w w,使得输入样本为 π \pi π 时使得 p ( l ∣ x ) p(l|x) p(l∣x) 尽可能大。
因此 CTC 借用了 HMM 的“向前—向后”(forward-backward)算法来计算 p ( l ∣ x ) p(l|x) p(l∣x) ,这段比较长,大家可以参考:https://zhuanlan.zhihu.com/p/43534801
!pip install shapely
!pip install pyclipper
Looking in indexes: https://mirror.baidu.com/pypi/simple/
Collecting shapely
[?25l Downloading https://mirror.baidu.com/pypi/packages/98/f8/db4d3426a1aba9d5dfcc83ed5a3e2935d2b1deb73d350642931791a61c37/Shapely-1.7.1-cp37-cp37m-manylinux1_x86_64.whl (1.0MB)
[K |████████████████████████████████| 1.0MB 13.1MB/s eta 0:00:01
[?25hInstalling collected packages: shapely
Successfully installed shapely-1.7.1
Looking in indexes: https://mirror.baidu.com/pypi/simple/
Collecting pyclipper
[?25l Downloading https://mirror.baidu.com/pypi/packages/1a/2f/ba30c6fe34ac082232a89f00801ea087c231d714eb200e8a1faa439c90b5/pyclipper-1.2.0-cp37-cp37m-manylinux1_x86_64.whl (126kB)
[K |████████████████████████████████| 133kB 12.5MB/s eta 0:00:01
[?25hInstalling collected packages: pyclipper
Successfully installed pyclipper-1.2.0
from PIL import Image, ImageDraw, ImageFont
from numpy import random
import paddlehub as hub
import numpy as np
import paddle.fluid as fluid
class Detector(object):
def __init__(self):
# 加载移动端预训练模型
# self.ocr = hub.Module(name='chinese_ocr_db_crnn_mobile')
# 服务端可以加载大模型,效果更好
self.ocr = hub.Module(name='chinese_ocr_db_crnn_server')
def feedCap(self, np_images, vis=True):
results = self.ocr.recognize_text(
# 图片数据,ndarray.shape 为 [H, W, C],BGR格式;
images=[np_images],
use_gpu=True, # 是否使用 GPU;若使用GPU,请先设置CUDA_VISIBLE_DEVICES环境变量
visualization=False, # 是否将识别结果保存为图片文件;
box_thresh=0.5, # 检测文本框置信度的阈值;
text_thresh=0.5)
img = Image.fromarray(np_images[:, :, [2, 1, 0]])
draw = ImageDraw.Draw(img) # 图片上打印
txt = []
for result in results:
data = result['data']
for infomation in data:
if vis:
for i in range(5):
pos = [(v[0]+i, v[1]+i)
for v in infomation['text_box_position']]
draw.polygon(pos, outline=(0, 255, 0))
txt.append(infomation['text'])
# img = np.array(img)[:, :, [2, 1, 0]]
return img, txt
import os
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
os.environ["CUDA_VISIBLE_DEVICES"] = '0'
img = cv2.imread('21.jpg')
plt.imshow(img[:, :, [2, 1, 0]])
ocr_model = Detector()
result, txt = ocr_model.feedCap(img)
plt.imshow(result)
plt.show()
print(txt)
[32m[2020-11-04 10:05:29,624] [ INFO] - Installing chinese_ocr_db_crnn_server module[0m
[32m[2020-11-04 10:05:29,627] [ INFO] - Module chinese_ocr_db_crnn_server already installed in /home/aistudio/.paddlehub/modules/chinese_ocr_db_crnn_server[0m
[32m[2020-11-04 10:05:30,104] [ INFO] - Installing chinese_text_detection_db_server module-1.0.2[0m
[32m[2020-11-04 10:05:30,107] [ INFO] - Module chinese_text_detection_db_server-1.0.2 already installed in /home/aistudio/.paddlehub/modules/chinese_text_detection_db_server[0m
['正新鸡排', '遇见', '见', '天派', '天派', '元', 'Bh!', '31G元', '有爱就是', '超大派', '正新', '12元', '正新鸡排', '正新鸡排', '门市价18元', '再饮科1']