印章文本识别产线使用教程¶
1. 印章文本识别产线介绍¶
印章文本识别是一种自动从文档或图像中提取和识别印章内容的技术,印章文本的识别是文档处理的一部分,在很多场景都有用途,例如合同比对,出入库审核以及发票报销审核等场景。
印章文本识别产线用于识别印章的文本内容,提取印章图像中的文字信息以文本形式输出,本产线集成了业界知名的 PP-OCRv4 的端到端 OCR 串联系统,支持弯曲印章文本的检测和识别。同时,本产线集成了可选的版面区域定位模块,可以在整个文档中准确定位印章所在的版面位置。此外也增加可选的文档图像的方向矫正和扭曲矫正功能。基于本产线,可实现 CPU 上毫秒级的文本内容精准预测。本产线同时提供了灵活的服务化部署方式,支持在多种硬件上使用多种编程语言调用。不仅如此,本产线也提供了二次开发的能力,您可以基于本产线在您自己的数据集上训练调优,训练后的模型也可以无缝集成。

印章文本识别产线中包含以下5个模块。每个模块均可独立进行训练和推理,并包含多个模型。有关详细信息,请点击相应模块以查看文档。
- 印章文本检测模块
 - 文本识别模块
 - 版面区域检测模块(可选)
 - 文档图像方向分类模块 (可选)
 - 文本图像矫正模块 (可选)
 
在本产线中,您可以根据下方的基准测试数据选择使用的模型。
推理耗时仅包含模型推理耗时,不包含前后处理耗时。
版面区域检测模块(可选):
* 版面检测模型,包含20个常见的类别:文档标题、段落标题、文本、页码、摘要、目录、参考文献、脚注、页眉、页脚、算法、公式、公式编号、图像、表格、图和表标题(图标题、表格标题和图表标题)、印章、图表、侧栏文本和参考文献内容| 模型 | 模型下载链接 | mAP(0.5)(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-DocLayout_plus-L | 推理模型/训练模型 | 83.2 | 53.03 / 17.23 | 634.62 / 378.32 | 126.01 | 基于RT-DETR-L在包含中英文论文、多栏杂志、报纸、PPT、合同、书本、试卷、研报、古籍、日文文档、竖版文字文档等场景的自建数据集训练的更高精度版面区域定位模型 | 
| 模型 | 模型下载链接 | mAP(0.5)(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-DocLayout-L | 推理模型/训练模型 | 90.4 | 33.59 / 33.59 | 503.01 / 251.08 | 123.76 | 基于RT-DETR-L在包含中英文论文、杂志、合同、书本、试卷和研报等场景的自建数据集训练的高精度版面区域定位模型 | 
| PP-DocLayout-M | 推理模型/训练模型 | 75.2 | 13.03 / 4.72 | 43.39 / 24.44 | 22.578 | 基于PicoDet-L在包含中英文论文、杂志、合同、书本、试卷和研报等场景的自建数据集训练的精度效率平衡的版面区域定位模型 | 
| PP-DocLayout-S | 推理模型/训练模型 | 70.9 | 11.54 / 3.86 | 18.53 / 6.29 | 4.834 | 基于PicoDet-S在中英文论文、杂志、合同、书本、试卷和研报等场景上自建数据集训练的高效率版面区域定位模型 | 
👉模型列表详情
* 3类版面检测模型,包含表格、图像、印章| 模型 | 模型下载链接 | mAP(0.5)(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PicoDet-S_layout_3cls | 推理模型/训练模型 | 88.2 | 8.43 / 3.44 | 17.60 / 6.51 | 4.8 | 基于PicoDet-S轻量模型在中英文论文、杂志和研报等场景上自建数据集训练的高效率版面区域定位模型 | 
| PicoDet-L_layout_3cls | 推理模型/训练模型 | 89.0 | 12.80 / 9.57 | 45.04 / 23.86 | 22.6 | 基于PicoDet-L在中英文论文、杂志和研报等场景上自建数据集训练的效率精度均衡版面区域定位模型 | 
| RT-DETR-H_layout_3cls | 推理模型/训练模型 | 95.8 | 114.80 / 25.65 | 924.38 / 924.38 | 470.1 | 基于RT-DETR-H在中英文论文、杂志和研报等场景上自建数据集训练的高精度版面区域定位模型 | 
| 模型 | 模型下载链接 | mAP(0.5)(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PicoDet-S_layout_17cls | 推理模型/训练模型 | 87.4 | 8.80 / 3.62 | 17.51 / 6.35 | 4.8 | 基于PicoDet-S轻量模型在中英文论文、杂志和研报等场景上自建数据集训练的高效率版面区域定位模型 | 
| PicoDet-L_layout_17cls | 推理模型/训练模型 | 89.0 | 12.60 / 10.27 | 43.70 / 24.42 | 22.6 | 基于PicoDet-L在中英文论文、杂志和研报等场景上自建数据集训练的效率精度均衡版面区域定位模型 | 
| RT-DETR-H_layout_17cls | 推理模型/训练模型 | 98.3 | 115.29 / 101.18 | 964.75 / 964.75 | 470.2 | 基于RT-DETR-H在中英文论文、杂志和研报等场景上自建数据集训练的高精度版面区域定位模型 | 
文档图像方向分类模块(可选):
| 模型 | 模型下载链接 | Top-1 Acc(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-LCNet_x1_0_doc_ori | 推理模型/训练模型 | 99.06 | 2.62 / 0.59 | 3.24 / 1.19 | 7 | 基于PP-LCNet_x1_0的文档图像分类模型,含有四个类别,即0度,90度,180度,270度 | 
文本图像矫正模块(可选):
| 模型 | 模型下载链接 | CER | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| UVDoc | 推理模型/训练模型 | 0.179 | 19.05 / 19.05 | - / 869.82 | 30.3 | 高精度文本图像矫正模型 | 
印章文本检测模块:
| 模型 | 模型下载链接 | 检测Hmean(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-OCRv4_server_seal_det | 推理模型/训练模型 | 98.40 | 124.64 / 91.57 | 545.68 / 439.86 | 109 | PP-OCRv4的服务端印章文本检测模型,精度更高,适合在较好的服务器上部署 | 
| PP-OCRv4_mobile_seal_det | 推理模型/训练模型 | 96.36 | 9.70 / 3.56 | 50.38 / 19.64 | 4.7 | PP-OCRv4的移动端印章文本检测模型,效率更高,适合在端侧部署 | 
文本识别模块:
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-OCRv5_server_rec | 推理模型/训练模型 | 86.38 | 8.46 / 2.36 | 31.21 / 31.21 | 81 | PP-OCRv5_rec 是新一代文本识别模型。该模型致力于以单一模型高效、精准地支持简体中文、繁体中文、英文、日文四种主要语言,以及手写、竖版、拼音、生僻字等复杂文本场景的识别。在保持识别效果的同时,兼顾推理速度和模型鲁棒性,为各种场景下的文档理解提供高效、精准的技术支撑。 | 
| PP-OCRv5_mobile_rec | 推理模型/训练模型 | 81.29 | 5.43 / 1.46 | 21.20 / 5.32 | 16 | |
| PP-OCRv4_server_rec_doc | 推理模型/训练模型 | 86.58 | 8.69 / 2.78 | 37.93 / 37.93 | 182 | PP-OCRv4_server_rec_doc是在PP-OCRv4_server_rec的基础上,在更多中文文档数据和PP-OCR训练数据的混合数据训练而成,增加了部分繁体字、日文、特殊字符的识别能力,可支持识别的字符为1.5万+,除文档相关的文字识别能力提升外,也同时提升了通用文字的识别能力 | 
| PP-OCRv4_mobile_rec | 推理模型/训练模型 | 78.74 | 5.26 / 1.12 | 17.48 / 3.61 | 10.5 | PP-OCRv4的轻量级识别模型,推理效率高,可以部署在包含端侧设备的多种硬件设备中 | 
| PP-OCRv4_server_rec | 推理模型/训练模型 | 85.19 | 8.75 / 2.49 | 36.93 / 36.93 | 173 | PP-OCRv4的服务器端模型,推理精度高,可以部署在多种不同的服务器上 | 
| en_PP-OCRv4_mobile_rec | 推理模型/训练模型 | 70.39 | 4.81 / 1.23 | 17.20 / 4.18 | 7.5 | 基于PP-OCRv4识别模型训练得到的超轻量英文识别模型,支持英文、数字识别 | 
👉模型列表详情
* PP-OCRv5 多场景模型| 模型 | 模型下载链接 | 中文识别 Avg Accuracy(%) | 英文识别 Avg Accuracy(%) | 繁体中文识别 Avg Accuracy(%) | 日文识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|---|---|---|
| PP-OCRv5_server_rec | 推理模型/训练模型 | 86.38 | 64.70 | 93.29 | 60.35 | 8.46 / 2.36 | 31.21 / 31.21 | 81 | PP-OCRv5_rec 是新一代文本识别模型。该模型致力于以单一模型高效、精准地支持简体中文、繁体中文、英文、日文四种主要语言,以及手写、竖版、拼音、生僻字等复杂文本场景的识别。在保持识别效果的同时,兼顾推理速度和模型鲁棒性,为各种场景下的文档理解提供高效、精准的技术支撑。 | 
| PP-OCRv5_mobile_rec | 推理模型/训练模型 | 81.29 | 66.00 | 83.55 | 54.65 | 5.43 / 1.46 | 21.20 / 5.32 | 16 | 
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| PP-OCRv4_server_rec_doc | 推理模型/训练模型 | 86.58 | 8.69 / 2.78 | 37.93 / 37.93 | 182 | PP-OCRv4_server_rec_doc是在PP-OCRv4_server_rec的基础上,在更多中文文档数据和PP-OCR训练数据的混合数据训练而成,增加了部分繁体字、日文、特殊字符的识别能力,可支持识别的字符为1.5万+,除文档相关的文字识别能力提升外,也同时提升了通用文字的识别能力 | 
| PP-OCRv4_mobile_rec | 推理模型/训练模型 | 78.74 | 5.26 / 1.12 | 17.48 / 3.61 | 10.5 | PP-OCRv4的轻量级识别模型,推理效率高,可以部署在包含端侧设备的多种硬件设备中 | 
| PP-OCRv4_server_rec | 推理模型/训练模型 | 85.19 | 8.75 / 2.49 | 36.93 / 36.93 | 173 | PP-OCRv4的服务器端模型,推理精度高,可以部署在多种不同的服务器上 | 
| PP-OCRv3_mobile_rec | 推理模型/训练模型 | 72.96 | 3.89 / 1.16 | 8.72 / 3.56 | 10.3 | PP-OCRv3的轻量级识别模型,推理效率高,可以部署在包含端侧设备的多种硬件设备中 | 
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| ch_SVTRv2_rec | 推理模型/训练模型 | 68.81 | 10.38 / 8.31 | 66.52 / 30.83 | 80.5 | SVTRv2 是一种由复旦大学视觉与学习实验室(FVL)的OpenOCR团队研发的服务端文本识别模型,其在PaddleOCR算法模型挑战赛 - 赛题一:OCR端到端识别任务中荣获一等奖,A榜端到端识别精度相比PP-OCRv4提升6%。 | 
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| ch_RepSVTR_rec | 推理模型/训练模型 | 65.07 | 6.29 / 1.57 | 20.64 / 5.40 | 48.8 | RepSVTR 文本识别模型是一种基于SVTRv2 的移动端文本识别模型,其在PaddleOCR算法模型挑战赛 - 赛题一:OCR端到端识别任务中荣获一等奖,B榜端到端识别精度相比PP-OCRv4提升2.5%,推理速度持平。 | 
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| en_PP-OCRv4_mobile_rec | 推理模型/训练模型 | 70.39 | 4.81 / 1.23 | 17.20 / 4.18 | 7.5 | 基于PP-OCRv4识别模型训练得到的超轻量英文识别模型,支持英文、数字识别 | 
| en_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 70.69 | 3.56 / 0.78 | 8.44 / 5.78 | 17.3 | 基于PP-OCRv3识别模型训练得到的超轻量英文识别模型,支持英文、数字识别 | 
| 模型 | 模型下载链接 | 识别 Avg Accuracy(%) | GPU推理耗时(ms) [常规模式 / 高性能模式]  | 
CPU推理耗时(ms) [常规模式 / 高性能模式]  | 
模型存储大小(MB) | 介绍 | 
|---|---|---|---|---|---|---|
| korean_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 60.21 | 3.73 / 0.98 | 8.76 / 2.91 | 9.6 | 基于PP-OCRv3识别模型训练得到的超轻量韩文识别模型,支持韩文、数字识别 | 
| japan_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 45.69 | 3.86 / 1.01 | 8.62 / 2.92 | 9.8 | 基于PP-OCRv3识别模型训练得到的超轻量日文识别模型,支持日文、数字识别 | 
| chinese_cht_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 82.06 | 3.90 / 1.16 | 9.24 / 3.18 | 10.8 | 基于PP-OCRv3识别模型训练得到的超轻量繁体中文识别模型,支持繁体中文、数字识别 | 
| te_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 95.88 | 3.59 / 0.81 | 8.28 / 6.21 | 8.7 | 基于PP-OCRv3识别模型训练得到的超轻量泰卢固文识别模型,支持泰卢固文、数字识别 | 
| ka_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 96.96 | 3.49 / 0.89 | 8.63 / 2.77 | 17.4 | 基于PP-OCRv3识别模型训练得到的超轻量卡纳达文识别模型,支持卡纳达文、数字识别 | 
| ta_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 76.83 | 3.49 / 0.86 | 8.35 / 3.41 | 8.7 | 基于PP-OCRv3识别模型训练得到的超轻量泰米尔文识别模型,支持泰米尔文、数字识别 | 
| latin_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 76.93 | 3.53 / 0.78 | 8.50 / 6.83 | 8.7 | 基于PP-OCRv3识别模型训练得到的超轻量拉丁文识别模型,支持拉丁文、数字识别 | 
| arabic_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 73.55 | 3.60 / 0.83 | 8.44 / 4.69 | 17.3 | 基于PP-OCRv3识别模型训练得到的超轻量阿拉伯字母识别模型,支持阿拉伯字母、数字识别 | 
| cyrillic_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 94.28 | 3.56 / 0.79 | 8.22 / 2.76 | 8.7 | 基于PP-OCRv3识别模型训练得到的超轻量斯拉夫字母识别模型,支持斯拉夫字母、数字识别 | 
| devanagari_PP-OCRv3_mobile_rec | 推理模型/训练模型 | 96.44 | 3.60 / 0.78 | 6.95 / 2.87 | 8.7 | 基于PP-OCRv3识别模型训练得到的超轻量梵文字母识别模型,支持梵文字母、数字识别 | 
测试环境说明:
- 性能测试环境
          
- 测试数据集:
             
                
- 文档图像方向分类模型:自建的内部数据集,覆盖证件和文档等多个场景,包含 1000 张图片。
 - 文本图像矫正模型:DocUNet。
 - 版面区域检测模型:PaddleOCR 自建的版面区域检测数据集,包含中英文论文、杂志、合同、书本、试卷和研报等常见的 500 张文档类型图片。
 - 3类版面检测模型:PaddleOCR 自建的版面区域检测数据集,包含中英文论文、杂志和研报等常见的 1154 张文档类型图片。
 - 17类区域检测模型:PaddleOCR 自建的版面区域检测数据集,包含中英文论文、杂志和研报等常见的 892 张文档类型图片。
 - 文本检测模型:PaddleOCR 自建的中文数据集,覆盖街景、网图、文档、手写多个场景,其中检测包含 500 张图片。
 - 中文识别模型: PaddleOCR 自建的中文数据集,覆盖街景、网图、文档、手写多个场景,其中文本识别包含 1.1w 张图片。
 - ch_SVTRv2_rec:PaddleOCR算法模型挑战赛 - 赛题一:OCR端到端识别任务A榜评估集。
 - ch_RepSVTR_rec:PaddleOCR算法模型挑战赛 - 赛题一:OCR端到端识别任务B榜评估集。
 - 英文识别模型:自建的内部英文数据集。
 - 多语言识别模型:自建的内部多语种数据集。
 - 文本行方向分类模型:自建的内部数据集,覆盖证件和文档等多个场景,包含 1000 张图片。
 - 印章文本检测模型:自建的内部数据集,包含500张圆形印章图像。
 
 - 硬件配置:
                  
- GPU:NVIDIA Tesla T4
 - CPU:Intel Xeon Gold 6271C @ 2.60GHz
 
 - 软件环境:
                  
- Ubuntu 20.04 / CUDA 11.8 / cuDNN 8.9 / TensorRT 8.6.1.6
 - paddlepaddle 3.0.0 / paddleocr 3.0.3
 
 
 - 测试数据集:
             
                
 - 推理模式说明
 
| 模式 | GPU配置 | CPU配置 | 加速技术组合 | 
|---|---|---|---|
| 常规模式 | FP32精度 / 无TRT加速 | FP32精度 / 8线程 | PaddleInference | 
| 高性能模式 | 选择先验精度类型和加速策略的最优组合 | FP32精度 / 8线程 | 选择先验最优后端(Paddle/OpenVINO/TRT等) | 
如您更考虑模型精度,请选择精度较高的模型,如您更考虑模型推理速度,请选择推理速度较快的模型,如您更考虑模型存储大小,请选择存储大小较小的模型。
2. 快速开始¶
在本地使用印章文本识别产线前,请确保您已经按照安装教程完成了wheel包安装。如果您希望选择性安装依赖,请参考安装教程中的相关说明。该产线对应的依赖分组为 doc-parser。安装完成后,可以在本地使用命令行体验或 Python 集成。
请注意,如果在执行过程中遇到程序失去响应、程序异常退出、内存资源耗尽、推理速度极慢等问题,请尝试参考文档调整配置,例如关闭不需要使用的功能或使用更轻量的模型。
2.1 命令行方式体验¶
一行命令即可快速体验 seal_recognition 产线效果:
paddleocr seal_recognition -i https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/seal_text_det.png \
    --use_doc_orientation_classify False \
    --use_doc_unwarping False
# 通过 --device 指定模型推理时使用 GPU
paddleocr seal_recognition -i ./seal_text_det.png --device gpu
命令行支持更多参数设置,点击展开以查看命令行参数的详细说明
| 参数 | 参数说明 | 参数类型 | 默认值 | 
|---|---|---|---|
input | 
待预测数据,必填。
如图像文件或者PDF文件的本地路径:/root/data/img.jpg;如URL链接,如图像文件或PDF文件的网络URL:示例;如本地目录,该目录下需包含待预测图像,如本地路径:/root/data/(当前不支持目录中包含PDF文件的预测,PDF文件需要指定到具体文件路径)。
 | 
str | 
|
save_path | 
指定推理结果文件保存的路径。如果不设置,推理结果将不会保存到本地。 | str | 
|
doc_orientation_classify_model_name | 
文档方向分类模型的名称。如果不设置,将会使用产线默认模型。 | str | 
|
doc_orientation_classify_model_dir | 
文档方向分类模型的目录路径。如果不设置,将会下载官方模型。 | str | 
|
doc_unwarping_model_name | 
文本图像矫正模型的名称。如果不设置,将会使用产线默认模型。 | str | 
|
doc_unwarping_model_dir | 
文本图像矫正模型的目录路径。如果不设置,将会下载官方模型。 | str | 
|
layout_detection_model_name | 
版面检测模型的名称。如果不设置,将会使用产线默认模型。 | str | 
|
layout_detection_model_dir | 
版面检测模型的目录路径。如果不设置,将会下载官方模型。 | str | 
|
seal_text_detection_model_name | 
印章文本检测模型的名称。如果不设置,将会使用产线默认模型。 | str | 
|
seal_text_detection_model_dir | 
印章文本检测模型的目录路径。如果不设置,将会下载官方模型。 | str | 
|
text_recognition_model_name | 
文本识别模型的名称。如果不设置,将会使用产线默认模型。 | str | 
|
text_recognition_model_dir | 
文本识别模型的目录路径。如果不设置,将会下载官方模型。 | str | 
|
text_recognition_batch_size | 
文本识别模型的batch size。如果不设置,将默认设置batch size为1。 | 
int | 
|
use_doc_orientation_classify | 
是否加载并使用文档方向分类模块。如果不设置,将使用产线初始化的该参数值,默认初始化为True。 | 
bool | 
|
use_doc_unwarping | 
是否加载并使用文本图像矫正模块。如果不设置,将使用产线初始化的该参数值,默认初始化为True。 | 
bool | 
|
use_layout_detection | 
是否加载并使用版面检测模块。如果不设置,将使用产线初始化的该参数值,默认初始化为True。 | 
bool | 
|
layout_threshold | 
版面模型得分阈值。0-1 之间的任意浮点数。如果不设置,将使用产线初始化的该参数值,默认初始化为 0.5。
 | 
float | 
|
layout_nms | 
版面检测是否使用后处理NMS。如果不设置,将使用产线初始化的该参数值,默认初始化为True。 | 
bool | 
|
layout_unclip_ratio | 
检测框的边长缩放倍数。 大于0的浮点数,如 1.1 ,表示将模型输出的检测框中心不变,宽和高都扩张1.1倍如果不设置,将使用产线初始化的该参数值,默认初始化为1.0。 | float | 
|
layout_merge_bboxes_mode | 
版面检测中模型输出的检测框的合并处理模式。
 large。
 | 
str | 
|
seal_det_limit_side_len | 
印章文本检测的图像边长限制。
大于 0 的任意整数。如果不设置,将使用产线初始化的该参数值,默认初始化为 736。
 | 
int | 
|
seal_det_limit_type | 
印章文本检测的图像边长限制类型。
支持 min 和 max,min 表示保证图像最短边不小于 det_limit_side_len,max 表示保证图像最长边不大于 limit_side_len。如果不设置,将使用产线初始化的该参数值,默认初始化为 min。
 | 
str | 
|
seal_det_thresh | 
检测像素阈值,输出的概率图中,得分大于该阈值的像素点才会被认为是文字像素点。大于0的任意浮点数
。如果不设置,将默认使用产线初始化的该参数值 0.2。
 | 
float | 
|
seal_det_box_thresh | 
检测框阈值,检测结果边框内,所有像素点的平均得分大于该阈值时,该结果会被认为是文字区域。
大于0的任意浮点数
。如果不设置,将默认使用产线初始化的该参数值 0.6。
 | 
float | 
|
seal_det_unclip_ratio | 
印章文本检测扩张系数,使用该方法对文字区域进行扩张,该值越大,扩张的面积越大。
大于0的任意浮点数
。如果不设置,将默认使用产线初始化的该参数值 0.5。
 | 
float | 
|
seal_rec_score_thresh | 
文本识别阈值,得分大于该阈值的文本结果会被保留。大于0的任意浮点数
。如果不设置,将默认使用产线初始化的该参数值 0.0。即不设阈值。
 | 
float | 
|
device | 
用于推理的设备。支持指定具体卡号:
  | 
str | 
|
enable_hpi | 
是否启用高性能推理。 | bool | 
False | 
use_tensorrt | 
是否启用 Paddle Inference 的 TensorRT 子图引擎。如果模型不支持通过 TensorRT 加速,即使设置了此标志,也不会使用加速。 对于 CUDA 11.8 版本的飞桨,兼容的 TensorRT 版本为 8.x(x>=6),建议安装 TensorRT 8.6.1.6。  | 
bool | 
False | 
precision | 
计算精度,如 fp32、fp16。 | str | 
fp32 | 
enable_mkldnn | 
是否启用 MKL-DNN 加速推理。如果 MKL-DNN 不可用或模型不支持通过 MKL-DNN 加速,即使设置了此标志,也不会使用加速。 | bool | 
True | 
mkldnn_cache_capacity | 
MKL-DNN 缓存容量。 | int | 
10 | 
cpu_threads | 
在 CPU 上进行推理时使用的线程数。 | int | 
8 | 
paddlex_config | 
PaddleX产线配置文件路径。 | str | 
运行结果会被打印到终端上,默认配置的 seal_recognition 产线的运行结果如下:
{'res': {'input_path': './seal_text_det.png', 'model_settings': {'use_doc_preprocessor': True, 'use_layout_detection': True}, 'doc_preprocessor_res': {'input_path': None, 'page_index': None, 'model_settings': {'use_doc_orientation_classify': False, 'use_doc_unwarping': False}, 'angle': -1}, 'layout_det_res': {'input_path': None, 'page_index': None, 'boxes': [{'cls_id': 16, 'label': 'seal', 'score': 0.975529670715332, 'coordinate': [6.191284, 0.16680908, 634.39325, 628.85345]}]}, 'seal_res_list': [{'input_path': None, 'page_index': None, 'model_settings': {'use_doc_preprocessor': False, 'use_textline_orientation': False}, 'dt_polys': [array([[320,  38],
       ...,
       [315,  38]]), array([[461, 347],
       ...,
       [456, 346]]), array([[439, 445],
       ...,
       [434, 444]]), array([[158, 468],
       ...,
       [154, 466]])], 'text_det_params': {'limit_side_len': 736, 'limit_type': 'min', 'thresh': 0.2, 'max_side_limit': 4000, 'box_thresh': 0.6, 'unclip_ratio': 0.5}, 'text_type': 'seal', 'textline_orientation_angles': array([-1, ..., -1]), 'text_rec_score_thresh': 0, 'rec_texts': ['天津君和缘商贸有限公司', '发票专用章', '吗繁物', '5263647368706'], 'rec_scores': array([0.99340463, ..., 0.9916274 ]), 'rec_polys': [array([[320,  38],
       ...,
       [315,  38]]), array([[461, 347],
       ...,
       [456, 346]]), array([[439, 445],
       ...,
       [434, 444]]), array([[158, 468],
       ...,
       [154, 466]])], 'rec_boxes': array([], dtype=float64)}]}}
可视化结果保存在save_path下,其中印章OCR的可视化结果如下:

2.2 Python脚本方式集成¶
命令行方式是为了快速体验查看效果,一般来说,在项目中,往往需要通过代码集成,您可以通过几行代码即可完成产线的快速推理,推理代码如下:
from paddleocr import SealRecognition
pipeline = SealRecognition(
    use_doc_orientation_classify=False, # 通过 use_doc_orientation_classify 指定是否使用文档方向分类模型
    use_doc_unwarping=False, # 通过 use_doc_unwarping 指定是否使用文本图像矫正模块
)
# ocr = SealRecognition(device="gpu") # 通过 device 指定模型推理时使用 GPU
output = pipeline.predict("./seal_text_det.png")
for res in output:
    res.print() ## 打印预测的结构化输出
    res.save_to_img("./output/")
    res.save_to_json("./output/")
在上述 Python 脚本中,执行了如下几个步骤:
(1)通过 SealRecognition() 实例化 印章文本识别 产线对象,具体参数说明如下:
| 参数 | 参数说明 | 参数类型 | 默认值 | 
|---|---|---|---|
doc_orientation_classify_model_name | 
文档方向分类模型的名称。如果设置为None,将会使用产线默认模型。 | 
str|None | 
None | 
doc_orientation_classify_model_dir | 
文档方向分类模型的目录路径。如果设置为None,将会下载官方模型。 | 
str|None | 
None | 
doc_unwarping_model_name | 
文本图像矫正模型的名称。如果设置为None,将会使用产线默认模型。 | 
str|None | 
None | 
doc_unwarping_model_dir | 
文本图像矫正模型的目录路径。如果设置为None,将会下载官方模型。 | 
str|None | 
None | 
layout_detection_model_name | 
版面检测模型的名称。如果设置为None,将会使用产线默认模型。 | 
str|None | 
None | 
layout_detection_model_dir | 
版面检测模型的目录路径。如果设置为None,将会下载官方模型。 | 
str|None | 
None | 
seal_text_detection_model_name | 
印章文本检测模型的名称。如果设置为None,将会使用产线默认模型。 | 
str|None | 
None | 
seal_text_detection_model_dir | 
印章文本检测模型的目录路径。如果设置为None,将会下载官方模型。 | 
str|None | 
None | 
text_recognition_model_name | 
文本识别模型的名称。如果设置为None,将会使用产线默认模型。 | 
str|None | 
None | 
text_recognition_model_dir | 
文本识别模型的目录路径。如果设置为None,将会下载官方模型。 | 
str|None | 
None | 
text_recognition_batch_size | 
文本识别模型的batch size。如果设置为None,将默认设置batch size为1。 | 
int|None | 
None | 
use_doc_orientation_classify | 
是否加载并使用文档方向分类模块。如果设置为None,将使用产线初始化的该参数值,默认初始化为True。 | 
bool|None | 
None | 
use_doc_unwarping | 
是否加载并使用文本图像矫正模块。如果设置为None,将使用产线初始化的该参数值,默认初始化为True。 | 
bool|None | 
None | 
use_layout_detection | 
是否加载并使用版面检测模块。如果设置为None,将使用产线初始化的该参数值,默认初始化为True。 | 
bool|None | 
None | 
layout_threshold | 
版面检测置信度阈值,得分大于该阈值才会被输出。
  | 
float|dict|None | 
None | 
layout_nms | 
版面检测是否使用后处理NMS。如果设置为None,将使用产线初始化的该参数值,默认初始化为True。 | 
bool|None | 
None | 
layout_unclip_ratio | 
版面区域检测模型检测框的扩张系数。
  | 
float|Tuple[float,float]|dict|None | 
None | 
layout_merge_bboxes_mode | 
版面区域检测的重叠框过滤方式。
  | 
str|dict|None | 
None | 
seal_det_limit_side_len | 
印章文本检测的图像边长限制。
  | 
int|None | 
None | 
seal_det_limit_type | 
印章文本检测的图像边长限制类型。
  | 
str|None | 
None | 
seal_det_thresh | 
检测像素阈值,输出的概率图中,得分大于该阈值的像素点才会被认为是文字像素点。
  | 
float|None | 
None | 
seal_det_box_thresh | 
检测框阈值,检测结果边框内,所有像素点的平均得分大于该阈值时,该结果会被认为是文字区域。
  | 
float|None | 
None | 
seal_det_unclip_ratio | 
印章文本检测扩张系数,使用该方法对文字区域进行扩张,该值越大,扩张的面积越大。
  | 
float|None | 
None | 
seal_rec_score_thresh | 
文本识别阈值,得分大于该阈值的文本结果会被保留。
  | 
float|None | 
None | 
device | 
用于推理的设备。支持指定具体卡号:
  | 
str|None | 
None | 
enable_hpi | 
是否启用高性能推理。 | bool | 
False | 
use_tensorrt | 
是否启用 Paddle Inference 的 TensorRT 子图引擎。如果模型不支持通过 TensorRT 加速,即使设置了此标志,也不会使用加速。 对于 CUDA 11.8 版本的飞桨,兼容的 TensorRT 版本为 8.x(x>=6),建议安装 TensorRT 8.6.1.6。  | 
bool | 
False | 
precision | 
计算精度,如 fp32、fp16。 | str | 
"fp32" | 
enable_mkldnn | 
是否启用 MKL-DNN 加速推理。如果 MKL-DNN 不可用或模型不支持通过 MKL-DNN 加速,即使设置了此标志,也不会使用加速。 | bool | 
True | 
mkldnn_cache_capacity | 
MKL-DNN 缓存容量。 | int | 
10 | 
cpu_threads | 
在 CPU 上进行推理时使用的线程数。 | int | 
8 | 
paddlex_config | 
PaddleX产线配置文件路径。 | str|None | 
None | 
(2)调用 印章文本识别 产线对象的 predict() 方法进行推理预测,该方法会返回一个结果列表。
另外,产线还提供了 predict_iter() 方法。两者在参数接受和结果返回方面是完全一致的,区别在于 predict_iter() 返回的是一个 generator,能够逐步处理和获取预测结果,适合处理大型数据集或希望节省内存的场景。可以根据实际需求选择使用这两种方法中的任意一种。
以下是 predict() 方法的参数及其说明:
| 参数 | 参数说明 | 参数类型 | 默认值 | 
|---|---|---|---|
input | 
待预测数据,支持多种输入类型,必填。
  | 
Python Var|str|list | 
|
use_doc_orientation_classify | 
是否在推理时使用文档方向分类模块。 | bool|None | 
None | 
use_doc_unwarping | 
是否在推理时使用文本图像矫正模块。 | bool|None | 
None | 
use_layout_detection | 
是否在推理时使用版面检测模块。 | bool|None | 
None | 
layout_threshold | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|dict|None | 
None | 
layout_nms | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
bool|None | 
None | 
layout_unclip_ratio | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|Tuple[float,float]|dict|None | 
None | 
layout_merge_bboxes_mode | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
str|dict|None | 
None | 
seal_det_limit_side_len | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
int|None | 
None | 
seal_det_limit_type | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
str|None | 
None | 
seal_det_thresh | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|None | 
None | 
seal_det_box_thresh | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|None | 
None | 
seal_det_unclip_ratio | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|None | 
None | 
seal_rec_score_thresh | 
参数含义与实例化参数基本相同。设置为None表示使用实例化参数,否则该参数优先级更高。 | 
float|None | 
None | 
(3)对预测结果进行处理,每个样本的预测结果均为对应的Result对象,且支持打印、保存为图片、保存为json文件的操作:
| 方法 | 方法说明 | 参数 | 参数类型 | 参数说明 | 默认值 | 
|---|---|---|---|---|---|
print() | 
打印结果到终端 | format_json | 
bool | 
是否对输出内容进行使用 JSON 缩进格式化。 | 
True | 
indent | 
int | 
指定缩进级别,以美化输出的 JSON 数据,使其更具可读性,仅当 format_json 为 True 时有效。 | 
4 | ||
ensure_ascii | 
bool | 
控制是否将非 ASCII 字符转义为 Unicode。设置为 True 时,所有非 ASCII 字符将被转义;False 则保留原始字符,仅当format_json为True时有效。 | 
False | 
||
save_to_json() | 
将结果保存为json格式的文件 | save_path | 
str | 
保存的文件路径,当为目录时,保存文件命名与输入文件类型命名一致。 | 无 | 
indent | 
int | 
指定缩进级别,以美化输出的 JSON 数据,使其更具可读性,仅当 format_json 为 True 时有效。 | 
4 | ||
ensure_ascii | 
bool | 
控制是否将非 ASCII 字符转义为 Unicode。设置为 True 时,所有非 ASCII 字符将被转义;False 则保留原始字符,仅当format_json为True时有效。 | 
False | 
||
save_to_img() | 
将结果保存为图像格式的文件 | save_path | 
str | 
保存的文件路径,支持目录或文件路径。 | 无 | 
- 
调用
print()方法会将结果打印到终端,打印到终端的内容解释如下:- 
input_path:(str)待预测图像的输入路径 - 
page_index:(Union[int, None])如果输入是PDF文件,则表示当前是PDF的第几页,否则为None - 
model_settings:(Dict[str, bool])配置产线所需的模型参数use_doc_preprocessor:(bool)控制是否启用文档预处理子产线use_layout_detection:(bool)控制是否启用版面检测子模块layout_det_res:(Dict[str, Union[List[numpy.ndarray], List[float]]])版面检测子模块的输出结果。仅当use_layout_detection=True时存在
input_path:(Union[str, None])版面检测区域模块接受的图像路径,当输入为numpy.ndarray时,保存为Nonepage_index:(Union[int, None])如果输入是PDF文件,则表示当前是PDF的第几页,否则为Noneboxes:(List[Dict])版面印章区域的检测框列表,每个列表中的元素,包含以下字段cls_id:(int)检测框的印章类别idscore:(float)检测框的置信度coordinate:(List[float])检测框的四个顶点坐标,顺序为x1,y1,x2,y2表示左上角的x坐标,左上角的y坐标,右下角x坐标,右下角的y坐标seal_res_list:List[Dict]印章文本识别的结果列表,每个元素包含以下字段
input_path:(Union[str, None])印章文本识别产线接受的图像路径,当输入为numpy.ndarray时,保存为Nonepage_index:(Union[int, None])如果输入是PDF文件,则表示当前是PDF的第几页,否则为Nonemodel_settings:(Dict[str, bool])印章文本识别产线的模型配置参数use_doc_preprocessor:(bool)控制是否启用文档预处理子产线use_textline_orientation:(bool)控制是否启用文本行方向分类子模块doc_preprocessor_res:(Dict[str, Union[str, Dict[str, bool], int]])文档预处理子产线的输出结果。仅当use_doc_preprocessor=True时存在
input_path:(Union[str, None])图像预处理子产线接受的图像路径,当输入为numpy.ndarray时,保存为Nonemodel_settings:(Dict)预处理子产线的模型配置参数use_doc_orientation_classify:(bool)控制是否启用文档方向分类use_doc_unwarping:(bool)控制是否启用文本图像矫正
angle:(int)文档方向分类的预测结果。启用时取值为[0,1,2,3],分别对应[0°,90°,180°,270°];未启用时为-1
 - 
dt_polys:(List[numpy.ndarray])印章文本检测的多边形框列表。每个检测框由多个顶点坐标构成的numpy数组表示,数组shape为(n, 2) - 
dt_scores:(List[float])文本检测框的置信度列表 - 
text_det_params:(Dict[str, Dict[str, int, float]])文本检测模块的配置参数limit_side_len:(int)图像预处理时的边长限制值limit_type:(str)边长限制的处理方式thresh:(float)文本像素分类的置信度阈值box_thresh:(float)文本检测框的置信度阈值unclip_ratio:(float)文本检测框的膨胀系数text_type:(str)印章文本检测的类型,当前固定为"seal"
 - 
text_rec_score_thresh:(float)文本识别结果的过滤阈值 - 
rec_texts:(List[str])文本识别结果列表,仅包含置信度超过text_rec_score_thresh的文本 - 
rec_scores:(List[float])文本识别的置信度列表,已按text_rec_score_thresh过滤 - 
rec_polys:(List[numpy.ndarray])经过置信度过滤的文本检测框列表,格式同dt_polys - 
rec_boxes:(numpy.ndarray)检测框的矩形边界框数组,印章识别产线为空数组 
 - 
 - 
调用
save_to_json()方法会将上述内容保存到指定的save_path中,如果指定为目录,则保存的路径为save_path/{your_img_basename}_res.json,如果指定为文件,则直接保存到该文件中。由于json文件不支持保存numpy数组,因此会将其中的numpy.array类型转换为列表形式。 - 
调用
save_to_img()方法会将可视化结果保存到指定的save_path中,如果指定为目录,则保存的路径为save_path/{your_img_basename}_seal_res_region1.{your_img_extension},如果指定为文件,则直接保存到该文件中。(产线通常包含较多结果图片,不建议直接指定为具体的文件路径,否则多张图会被覆盖,仅保留最后一张图) - 
此外,也支持通过属性获取带结果的可视化图像和预测结果,具体如下:
 
| 属性 | 属性说明 | 
|---|---|
json | 
获取预测的 json 格式的结果 | 
img | 
获取格式为 dict 的可视化图像 | 
json属性获取的预测结果为dict类型的数据,相关内容与调用save_to_json()方法保存的内容一致。img属性返回的预测结果是一个dict类型的数据。其中,键分别为layout_det_res、seal_res_region1和preprocessed_img,对应的值是三个Image.Image对象:一个用于显示版面检测可视化,一个用于显示印章文本识别结果的可视化图像,另一个用于展示图像预处理的可视化图像。如果没有使用图像预处理子模块,则dict中不包含preprocessed_img,如果没有使用版面区域检测模块,则dict中不包含layout_det_res。
3. 开发集成/部署¶
如果产线可以达到您对产线推理速度和精度的要求,您可以直接进行开发集成/部署。
若您需要将产线直接应用在您的Python项目中,可以参考 2.2 Python脚本方式中的示例代码。
此外,PaddleOCR 也提供了其他两种部署方式,详细说明如下:
🚀 高性能推理:在实际生产环境中,许多应用对部署策略的性能指标(尤其是响应速度)有着较严苛的标准,以确保系统的高效运行与用户体验的流畅性。为此,PaddleOCR 提供高性能推理功能,旨在对模型推理及前后处理进行深度性能优化,实现端到端流程的显著提速,详细的高性能推理流程请参考高性能推理。
☁️ 服务化部署:服务化部署是实际生产环境中常见的一种部署形式。通过将推理功能封装为服务,客户端可以通过网络请求来访问这些服务,以获取推理结果。详细的产线服务化部署流程请参考服务化部署。
以下是基础服务化部署的API参考与多语言服务调用示例:
API参考
对于服务提供的主要操作:
- HTTP请求方法为POST。
 - 请求体和响应体均为JSON数据(JSON对象)。
 - 当请求处理成功时,响应状态码为
200,响应体的属性如下: 
| 名称 | 类型 | 含义 | 
|---|---|---|
logId | 
string | 
请求的UUID。 | 
errorCode | 
integer | 
错误码。固定为0。 | 
errorMsg | 
string | 
错误说明。固定为"Success"。 | 
result | 
object | 
操作结果。 | 
- 当请求处理未成功时,响应体的属性如下:
 
| 名称 | 类型 | 含义 | 
|---|---|---|
logId | 
string | 
请求的UUID。 | 
errorCode | 
integer | 
错误码。与响应状态码相同。 | 
errorMsg | 
string | 
错误说明。 | 
服务提供的主要操作如下:
infer
获取印章文本识别结果。
POST /seal-recognition
- 请求体的属性如下:
 
| 名称 | 类型 | 含义 | 是否必填 | 
|---|---|---|---|
file | 
string | 
服务器可访问的图像文件或PDF文件的URL,或上述类型文件内容的Base64编码结果。默认对于超过10页的PDF文件,只有前10页的内容会被处理。 要解除页数限制,请在产线配置文件中添加以下配置: 
 | 
是 | 
fileType | 
integer | null | 
文件类型。0表示PDF文件,1表示图像文件。若请求体无此属性,则将根据URL推断文件类型。 | 
否 | 
useDocOrientationClassify | 
boolean | null | 
请参阅产线对象中 predict 方法的 use_doc_orientation_classify 参数相关说明。 | 
否 | 
useDocUnwarping | 
boolean | null | 
请参阅产线对象中 predict 方法的 use_doc_unwarping 参数相关说明。 | 
否 | 
useLayoutDetection | 
boolean | null | 
请参阅产线对象中 predict 方法的 use_layout_detection 参数相关说明。 | 
否 | 
layoutThreshold | 
number | null | 
请参阅产线对象中 predict 方法的 layout_threshold 参数相关说明。 | 
否 | 
layoutNms | 
boolean | null | 
请参阅产线对象中 predict 方法的 layout_nms 参数相关说明。 | 
否 | 
layoutUnclipRatio | 
number | array | null | 
请参阅产线对象中 predict 方法的 layout_unclip_ratio 参数相关说明。 | 
否 | 
layoutMergeBboxesMode | 
string | null | 
请参阅产线对象中 predict 方法的 layout_merge_bboxes_mode 参数相关说明。 | 
否 | 
sealDetLimitSideLen | 
integer | null | 
请参阅产线对象中 predict 方法的 seal_det_limit_side_len 参数相关说明。 | 
否 | 
sealDetLimitType | 
string | null | 
请参阅产线对象中 predict 方法的 seal_det_limit_type 参数相关说明。 | 
否 | 
sealDetThresh | 
number | null | 
请参阅产线对象中 predict 方法的 seal_det_thresh 参数相关说明。 | 
否 | 
sealDetBoxThresh | 
number | null | 
请参阅产线对象中 predict 方法的 seal_det_box_thresh 参数相关说明。 | 
否 | 
sealDetUnclipRatio | 
number | null | 
请参阅产线对象中 predict 方法的 seal_det_unclip_ratio 参数相关说明。 | 
否 | 
sealRecScoreThresh | 
number | null | 
请参阅产线对象中 predict 方法的 seal_rec_score_thresh 参数相关说明。 | 
否 | 
visualize | 
boolean | null | 
是否返回可视化结果图以及处理过程中的中间图像等。
 例如,在产线配置文件中添加如下字段: 
将默认不返回图像,通过请求体中的visualize参数可以覆盖默认行为。如果请求体和配置文件中均未设置(或请求体传入null、配置文件中未设置),则默认返回图像。
 | 
否 | 
- 请求处理成功时,响应体的
result具有如下属性: 
| 名称 | 类型 | 含义 | 
|---|---|---|
sealRecResults | 
object | 
印章文本识别结果。数组长度为1(对于图像输入)或实际处理的文档页数(对于PDF输入)。对于PDF输入,数组中的每个元素依次表示PDF文件中实际处理的每一页的结果。 | 
dataInfo | 
object | 
输入数据信息。 | 
sealRecResults中的每个元素为一个object,具有如下属性:
| 名称 | 类型 | 含义 | 
|---|---|---|
prunedResult | 
object | 
产线对象的 predict 方法生成结果的 JSON 表示中 res 字段的简化版本,其中去除了 input_path 和 page_index 字段。 | 
outputImages | 
object | null | 
参见产线预测结果的 img 属性说明。图像为JPEG格式,使用Base64编码。 | 
inputImage | 
string | null | 
输入图像。图像为JPEG格式,使用Base64编码。 | 
多语言调用服务示例
Python
import base64
import requests
API_URL = "http://localhost:8080/seal-recognition"
file_path = "./demo.jpg"
with open(file_path, "rb") as file:
    file_bytes = file.read()
    file_data = base64.b64encode(file_bytes).decode("ascii")
payload = {"file": file_data, "fileType": 1}
response = requests.post(API_URL, json=payload)
assert response.status_code == 200
result = response.json()["result"]
for i, res in enumerate(result["sealRecResults"]):
    print(res["prunedResult"])
    for img_name, img in res["outputImages"].items():
        img_path = f"{img_name}_{i}.jpg"
        with open(img_path, "wb") as f:
            f.write(base64.b64decode(img))
        print(f"Output image saved at {img_path}")
C++
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "cpp-httplib/httplib.h" // https://github.com/Huiyicc/cpp-httplib
#include "nlohmann/json.hpp" // https://github.com/nlohmann/json
#include "base64.hpp" // https://github.com/tobiaslocker/base64
int main() {
    httplib::Client client("localhost", 8080);
    const std::string filePath = "./demo.jpg";
    std::ifstream file(filePath, std::ios::binary | std::ios::ate);
    if (!file) {
        std::cerr << "Error opening file: " << filePath << std::endl;
        return 1;
    }
    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector buffer(size);
    if (!file.read(buffer.data(), size)) {
        std::cerr << "Error reading file." << std::endl;
        return 1;
    }
    std::string bufferStr(buffer.data(), static_cast(size));
    std::string encodedFile = base64::to_base64(bufferStr);
    nlohmann::json jsonObj;
    jsonObj["file"] = encodedFile;
    jsonObj["fileType"] = 1;
    auto response = client.Post("/seal-recognition", jsonObj.dump(), "application/json");
    if (response && response->status == 200) {
        nlohmann::json jsonResponse = nlohmann::json::parse(response->body);
        auto result = jsonResponse["result"];
        if (!result.is_object() || !result["sealRecResults"].is_array()) {
            std::cerr << "Unexpected response format." << std::endl;
            return 1;
        }
        for (size_t i = 0; i < result["sealRecResults"].size(); ++i) {
            auto res = result["sealRecResults"][i];
            if (res.contains("prunedResult")) {
                std::cout << "Recognized seal result: " << res["prunedResult"].dump() << std::endl;
            }
            if (res.contains("outputImages") && res["outputImages"].is_object()) {
                for (auto& [imgName, imgData] : res["outputImages"].items()) {
                    std::string outputPath = imgName + "_" + std::to_string(i) + ".jpg";
                    std::string decodedImage = base64::from_base64(imgData.get());
                    std::ofstream outFile(outputPath, std::ios::binary);
                    if (outFile.is_open()) {
                        outFile.write(decodedImage.c_str(), decodedImage.size());
                        outFile.close();
                        std::cout << "Saved image: " << outputPath << std::endl;
                    } else {
                        std::cerr << "Failed to write image: " << outputPath << std::endl;
                    }
                }
            }
        }
    } else {
        std::cerr << "Request failed." << std::endl;
        if (response) {
            std::cerr << "HTTP status: " << response->status << std::endl;
            std::cerr << "Response body: " << response->body << std::endl;
        }
        return 1;
    }
    return 0;
}
   Java
import okhttp3.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Base64;
public class Main {
    public static void main(String[] args) throws IOException {
        String API_URL = "http://localhost:8080/seal-recognition";
        String imagePath = "./demo.jpg";
        File file = new File(imagePath);
        byte[] fileContent = java.nio.file.Files.readAllBytes(file.toPath());
        String base64Image = Base64.getEncoder().encodeToString(fileContent);
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode payload = objectMapper.createObjectNode();
        payload.put("file", base64Image);
        payload.put("fileType", 1);
        OkHttpClient client = new OkHttpClient();
        MediaType JSON = MediaType.get("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, payload.toString());
        Request request = new Request.Builder()
                .url(API_URL)
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                String responseBody = response.body().string();
                JsonNode root = objectMapper.readTree(responseBody);
                JsonNode result = root.get("result");
                JsonNode sealRecResults = result.get("sealRecResults");
                for (int i = 0; i < sealRecResults.size(); i++) {
                    JsonNode item = sealRecResults.get(i);
                    int finalI = i;
                    JsonNode prunedResult = item.get("prunedResult");
                    System.out.println("Pruned Result [" + i + "]: " + prunedResult.toString());
                    JsonNode outputImages = item.get("outputImages");
                    if (outputImages != null && outputImages.isObject()) {
                        outputImages.fieldNames().forEachRemaining(imgName -> {
                            try {
                                String imgBase64 = outputImages.get(imgName).asText();
                                byte[] imgBytes = Base64.getDecoder().decode(imgBase64);
                                String imgPath = imgName + "_" + finalI + ".jpg";
                                try (FileOutputStream fos = new FileOutputStream(imgPath)) {
                                    fos.write(imgBytes);
                                    System.out.println("Saved image: " + imgPath);
                                }
                            } catch (IOException e) {
                                System.err.println("Failed to save image: " + e.getMessage());
                            }
                        });
                    }
                }
            } else {
                System.err.println("Request failed with HTTP code: " + response.code());
            }
        }
    }
}
Go
package main
import (
    "bytes"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)
func main() {
    API_URL := "http://localhost:8080/seal-recognition"
    filePath := "./demo.jpg"
    fileBytes, err := ioutil.ReadFile(filePath)
    if err != nil {
        fmt.Printf("Error reading file: %v\n", err)
        return
    }
    fileData := base64.StdEncoding.EncodeToString(fileBytes)
    payload := map[string]interface{}{
        "file":     fileData,
        "fileType": 1,
    }
    payloadBytes, err := json.Marshal(payload)
    if err != nil {
        fmt.Printf("Error marshaling payload: %v\n", err)
        return
    }
    client := &http.Client{}
    req, err := http.NewRequest("POST", API_URL, bytes.NewBuffer(payloadBytes))
    if err != nil {
        fmt.Printf("Error creating request: %v\n", err)
        return
    }
    req.Header.Set("Content-Type", "application/json")
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("Error sending request: %v\n", err)
        return
    }
    defer resp.Body.Close()
    if resp.StatusCode != http.StatusOK {
        fmt.Printf("Unexpected status code: %d\n", resp.StatusCode)
        return
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Error reading response body: %v\n", err)
        return
    }
    type SealResult struct {
        PrunedResult map[string]interface{}   `json:"prunedResult"`
        OutputImages map[string]string        `json:"outputImages"`
        InputImage   *string                  `json:"inputImage"`
    }
    type Response struct {
        Result struct {
            SealRecResults []SealResult  `json:"sealRecResults"`
            DataInfo       interface{}   `json:"dataInfo"`
        } `json:"result"`
    }
    var respData Response
    if err := json.Unmarshal(body, &respData); err != nil {
        fmt.Printf("Error unmarshaling response: %v\n", err)
        return
    }
    for i, res := range respData.Result.SealRecResults {
        fmt.Printf("Pruned Result %d: %+v\n", i, res.PrunedResult)
        for name, imgBase64 := range res.OutputImages {
            imgBytes, err := base64.StdEncoding.DecodeString(imgBase64)
            if err != nil {
                fmt.Printf("Error decoding image %s: %v\n", name, err)
                continue
            }
            filename := fmt.Sprintf("%s_%d.jpg", name, i)
            if err := ioutil.WriteFile(filename, imgBytes, 0644); err != nil {
                fmt.Printf("Error saving image %s: %v\n", filename, err)
                continue
            }
            fmt.Printf("Output image saved at %s\n", filename)
        }
    }
}
C#
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
class Program
{
    static readonly string API_URL = "http://localhost:8080/seal-recognition";
    static readonly string inputFilePath = "./demo.jpg";
    static async Task Main(string[] args)
    {
        var httpClient = new HttpClient();
        byte[] fileBytes = File.ReadAllBytes(inputFilePath);
        string fileData = Convert.ToBase64String(fileBytes);
        var payload = new JObject
        {
            { "file", fileData },
            { "fileType", 1 }
        };
        var content = new StringContent(payload.ToString(), Encoding.UTF8, "application/json");
        HttpResponseMessage response = await httpClient.PostAsync(API_URL, content);
        response.EnsureSuccessStatusCode();
        string responseBody = await response.Content.ReadAsStringAsync();
        JObject jsonResponse = JObject.Parse(responseBody);
        JArray sealRecResults = (JArray)jsonResponse["result"]["sealRecResults"];
        for (int i = 0; i < sealRecResults.Count; i++)
        {
            var res = sealRecResults[i];
            Console.WriteLine($"[{i}] prunedResult:\n{res["prunedResult"]}");
            JObject outputImages = res["outputImages"] as JObject;
            if (outputImages != null)
            {
                foreach (var img in outputImages)
                {
                    string imgName = img.Key;
                    string base64Img = img.Value?.ToString();
                    if (!string.IsNullOrEmpty(base64Img))
                    {
                        string imgPath = $"{imgName}_{i}.jpg";
                        byte[] imageBytes = Convert.FromBase64String(base64Img);
                        File.WriteAllBytes(imgPath, imageBytes);
                        Console.WriteLine($"Output image saved at {imgPath}");
                    }
                }
            }
        }
    }
}
Node.js
const axios = require('axios');
const fs = require('fs');
const path = require('path');
const API_URL = 'http://localhost:8080/seal-recognition';
const imagePath = './demo.jpg';
function encodeImageToBase64(filePath) {
  const bitmap = fs.readFileSync(filePath);
  return Buffer.from(bitmap).toString('base64');
}
const payload = {
  file: encodeImageToBase64(imagePath),
  fileType: 1
};
axios.post(API_URL, payload)
  .then((response) => {
    const result = response.data["result"];
    const sealRecResults = result["sealRecResults"];
    sealRecResults.forEach((res, i) => {
      console.log(`\n[${i}] prunedResult:\n`, res["prunedResult"]);
      const outputImages = res["outputImages"];
      if (outputImages) {
        for (const [imgName, base64Img] of Object.entries(outputImages)) {
          const imgBuffer = Buffer.from(base64Img, 'base64');
          const fileName = `${imgName}_${i}.jpg`;
          fs.writeFileSync(fileName, imgBuffer);
          console.log(`Output image saved at ${fileName}`);
        }
      } else {
        console.log(`[${i}] No outputImages found.`);
      }
    });
  })
  .catch((error) => {
    console.error('Error occurred while calling the API:', error.message);
  });
PHP
<?php
$API_URL = "http://localhost:8080/seal-recognition";
$image_path = "./demo.jpg";
$image_data = base64_encode(file_get_contents($image_path));
$payload = array("file" => $image_data, "fileType" => 1);
$ch = curl_init($API_URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true)["result"]["sealRecResults"];
foreach ($result as $i => $item) {
    echo "[$i] prunedResult:\n";
    print_r($item["prunedResult"]);
    if (!empty($item["outputImages"])) {
        foreach ($item["outputImages"] as $img_name => $base64_img) {
            if (!empty($base64_img)) {
                $output_path = "{$img_name}_{$i}.jpg";
                file_put_contents($output_path, base64_decode($base64_img));
                echo "Output image saved at $output_path\n";
            }
        }
    } else {
        echo "No outputImages found for item $i\n";
    }
}
?>
4. 二次开发¶
如果印章文本识别产线提供的默认模型权重在您的场景中,精度或速度不满意,您可以尝试利用您自己拥有的特定领域或应用场景的数据对现有模型进行进一步的微调,以提升印章文本识别产线的在您的场景中的识别效果。
4.1 模型微调¶
由于印章文本识别产线包含若干模块,模型产线的效果如果不及预期,可能来自于其中任何一个模块。您可以对识别效果差的图片进行分析,进而确定是哪个模块存在问题,并参考以下表格中对应的微调教程链接进行模型微调。
| 情形 | 微调模块 | 微调参考链接 | 
|---|---|---|
| 印章位置检测不准或未检出 | 版面检测模块 | 链接 | 
| 印章文本存在漏检 | 印章文本检测模块 | 链接 | 
| 文本内容不准 | 文本识别模块 | 链接 | 
| 整图旋转矫正不准 | 文档图像方向分类模块 | 链接 | 
| 图像扭曲矫正不准 | 文本图像矫正模块 | 暂不支持微调 | 
4.2 模型应用¶
当您使用私有数据集完成微调训练后,可获得本地模型权重文件,然后可以通过参数指定本地模型保存路径的方式,或者通过自定义产线配置文件的方式,使用微调后的模型权重。
4.2.1 通过参数指定本地模型路径¶
在初始化产线对象时,通过参数指定本地模型路径。以文本检测模型微调后的权重的使用方法为例,示例如下:
命令行方式:
# 通过 --doc_orientation_classify_model_dir 指定本地模型路径
paddleocr seal_recognition -i ./seal_text_det.png --doc_orientation_classify_model_dir your_orientation_classify_model_path
# 默认使用 PP-LCNet_x1_0_doc_ori 模型作为默认文本检测模型,如果微调的不是该模型,通过 --text_detection_model_name 修改模型名称
paddleocr seal_recognition -i ./seal_text_det.png --doc_orientation_classify_model_name PP-LCNet_x1_0_doc_ori --doc_orientation_classify_model_dir your_orientation_classify_model_path
脚本方式:
from paddleocr import SealRecognition
# 通过 doc_orientation_classify_model_dir 指定本地模型路径
pipeline = SealRecognition(doc_orientation_classify_model_dir ="./your_orientation_classify_model_path")
# 默认使用 PP-LCNet_x1_0_doc_ori 模型作为默认文本检测模型,如果微调的不是该模型,通过 doc_orientation_classify_model_name 修改模型名称
# pipeline = SealRecognition(doc_orientation_classify_model_name="PP-LCNet_x1_0_doc_ori", doc_orientation_classify_model_dir="./your_orientation_classify_model_path")
4.2.2 通过配置文件指定本地模型路径¶
- 获取产线配置文件
 
可调用 PaddleOCR 中 通用OCR 产线对象的 export_paddlex_config_to_yaml 方法,将当前产线配置导出为 YAML 文件:
from paddleocr import SealRecognition
pipeline = SealRecognition()
pipeline.export_paddlex_config_to_yaml("SealRecognition.yaml")
- 修改配置文件
 
在得到默认的产线配置文件后,将微调后模型权重的本地路径替换至产线配置文件中的对应位置即可。例如
......
SubPipelines:
  DocPreprocessor:
    SubModules:
      DocOrientationClassify:
        model_dir: null  # 替换为微调后的文档方向分类模型权重路径
        model_name: PP-LCNet_x1_0_doc_ori # 如果微调的模型名称与默认模型名称不同,请一并修改此处
        module_name: doc_text_orientation
      DocUnwarping:
        model_dir: null  # 替换为微调后的文档矫正模型权重路径
        model_name: UVDoc # 如果微调的模型名称与默认模型名称不同,请一并修改此处
        module_name: image_unwarping
    pipeline_name: doc_preprocessor
    use_doc_orientation_classify: true
    use_doc_unwarping: true
......
在产线配置文件中,不仅包含 SealRecognition CLI 和 Python API 支持的参数,还可进行更多高级配置,具体信息可在 PaddleX模型产线使用概览 中找到对应的产线使用教程,参考其中的详细说明,根据需求调整各项配置。
- 在 CLI 中加载产线配置文件
 
在修改完成配置文件后,通过命令行的 --paddlex_config 参数指定修改后的产线配置文件的路径,PaddleOCR 会读取其中的内容作为产线配置。示例如下:
- 在 Python API 中加载产线配置文件
 
初始化产线对象时,可通过 paddlex_config 参数传入 PaddleX 产线配置文件路径或配置dict,PaddleOCR 会读取其中的内容作为产线配置。示例如下:
from paddleocr import SealRecognition
pipeline = SealRecognition(paddlex_config="SealRecognition.yaml")