当前位置:   article > 正文

PP-OCR_pporc

pporc

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

Githubhttps://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显存都不够。

  1. class DetResizeForTest(object):
  2. def __init__(self, **kwargs):
  3. super(DetResizeForTest, self).__init__()
  4. self.resize_type = 0
  5. if 'image_shape' in kwargs:
  6. self.image_shape = kwargs['image_shape']
  7. self.resize_type = 1
  8. elif 'limit_side_len' in kwargs:
  9. self.limit_side_len = kwargs['limit_side_len']
  10. self.limit_type = kwargs.get('limit_type', 'min')
  11. elif 'resize_long' in kwargs:
  12. self.resize_type = 2
  13. self.resize_long = kwargs.get('resize_long', 960)
  14. else:
  15. #self.limit_side_len = 736
  16. #self.limit_type = 'min'
  17. self.limit_side_len = 960
  18. self.limit_type = 'max'

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

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

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

 

安装:

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

 

实际测试:

  1. import os
  2. import cv2
  3. import numpy as np
  4. from paddleocr import PaddleOCR
  5. # Paddleocr目前支持中英文、英文、法语、德语、韩语、日语,可以通过修改lang参数进行切换
  6. # 参数依次为`ch`, `en`, `french`, `german`, `korean`, `japan`。
  7. def draw_ocr(img, boxes, txts, scores):
  8. import random
  9. from PIL import Image
  10. from PIL import ImageFont,ImageDraw
  11. bg = np.ones_like(img)*255
  12. fg = np.zeros_like(img)
  13. img_PIL_bg = Image.fromarray(cv2.cvtColor(bg,cv2.COLOR_BGR2RGB))
  14. img_PIL_fg = Image.fromarray(cv2.cvtColor(fg,cv2.COLOR_BGR2RGB))
  15. font = ImageFont.truetype('StyleText/fonts/ch_standard.ttf',10)
  16. fillColor = (0,0,0)
  17. #if not isinstance(chinese,unicode):
  18. #chinese = chinese.decode('utf-8')
  19. draw_bg = ImageDraw.Draw(img_PIL_bg)
  20. draw_fg = ImageDraw.Draw(img_PIL_fg)
  21. for box, txt , score in zip(boxes, txts, scores):
  22. 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])
  23. color = (random.randint(0,255),random.randint(0,255),random.randint(0,255))
  24. draw_bg.polygon(tuple_polygon, fill = color)
  25. draw_fg.polygon(tuple_polygon, fill = color)
  26. draw_bg.text(box[0] , " ".join([txt,str(float(score))]),font=font,fill=fillColor)
  27. img_bg = cv2.cvtColor(np.asarray(img_PIL_bg),cv2.COLOR_RGB2BGR)
  28. img_fg = cv2.cvtColor(np.asarray(img_PIL_fg),cv2.COLOR_RGB2BGR)
  29. return np.hstack([cv2.addWeighted(img, 0.5, img_fg, 0.5, gamma=0), img_bg])
  30. def test_one_image():
  31. # small
  32. ocr = PaddleOCR(det_model_dir="models/ultra-lightweight_2.0/det/",
  33. rec_model_dir="models/ultra-lightweight_2.0/rec/ch/",
  34. rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",
  35. cls_model_dir="models/ultra-lightweight_2.0/cls/",
  36. use_angle_cls=True,
  37. lang="ch") # need to run only once to download and load model into memory
  38. # big
  39. ocr = PaddleOCR(det_model_dir="models/general_2.0/det/",
  40. rec_model_dir="models/general_2.0/rec/ch/",
  41. rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",
  42. cls_model_dir="models/general_2.0/cls/",
  43. use_angle_cls=True,
  44. lang="ch") # need to run only once to download and load model into memory
  45. img_path = 'doc/imgs/11.jpg'
  46. img = cv2.imread(img_path)
  47. result = ocr.ocr(img, cls=True)
  48. boxes = [line[0] for line in result]
  49. txts = [line[1][0] for line in result]
  50. scores = [line[1][1] for line in result]
  51. for box, txt , score in zip(boxes, txts, scores):
  52. print(box, txt, score)
  53. draw_out = draw_ocr(img, boxes, txts, scores)
  54. cv2.imwrite(img_path.split("/")[-1],draw_out)
  55. def test_images():
  56. # small
  57. """
  58. ocr = PaddleOCR(det_model_dir="models/ultra-lightweight_2.0/det/",
  59. rec_model_dir="models/ultra-lightweight_2.0/rec/ch/",
  60. rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",
  61. cls_model_dir="models/ultra-lightweight_2.0/cls/",
  62. use_angle_cls=True,
  63. lang="ch") # need to run only once to download and load model into memory
  64. """
  65. # big
  66. ocr = PaddleOCR(det_model_dir="models/general_2.0/det/",
  67. rec_model_dir="models/general_2.0/rec/ch/",
  68. rec_char_dict_path="ppocr/utils/ppocr_keys_v1.txt",
  69. cls_model_dir="models/general_2.0/cls/",
  70. use_angle_cls=True,
  71. lang="ch") # need to run only once to download and load model into memory
  72. data_dir= "test_images/"
  73. out_dir = "out_images/"
  74. for name in os.listdir(data_dir):
  75. print(name)
  76. img_path = os.path.join(data_dir, name)
  77. img = cv2.imread(img_path)
  78. result = ocr.ocr(img, cls=True)
  79. boxes = [line[0] for line in result]
  80. txts = [line[1][0] for line in result]
  81. scores = [line[1][1] for line in result]
  82. for box, txt , score in zip(boxes, txts, scores):
  83. print(box, txt, score)
  84. draw_out = draw_ocr(img, boxes, txts, scores)
  85. cv2.imwrite(os.path.join(out_dir, name),draw_out)
  86. if __name__=="__main__":
  87. #test_one_image()
  88. test_images()

 

总结:

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/1006390
推荐阅读
相关标签
  

闽ICP备14008679号