【免费下载链接】TurboOCR
TurboOCR, >200 img/s OmnidocBench. TensorRT FP16, PP-OCRv6, HTTP + gRPC
在 TurboOCR 中,OCR 不只是"把字认出来",更要把文档理解出来:哪块是标题、哪块是表格、哪块是公式、正文应该按什么顺序读。这份实战指南带你走一遍 TurboOCR 的布局检测引擎——基于 PP-DocLayoutV3 的 25 类版面解析,以及与之配套的阅读顺序(Reading Order)机制:如何开启、每类版面长什么样、嵌套框怎么处理、结果如何被路由到表格/公式识别器。适合刚接触文档智能的开发者与 API 使用者。
为什么布局检测是文档 OCR 的"大脑"
传统 OCR 只输出一堆文字行,双栏论文、带表格的财报、混排公式的教材都会读成一锅粥。TurboOCR 的做法是:先让版面模型把页面切成 25 类"功能区",再由路由器(Router)把每个区域分发给正确的后端——普通文字走 PP-OCR 识别、表格(class 21)走 SLANeXt 表格识别器、公式(class 5/15)走 PP-FormulaNet 公式识别器。
一句话:没有 layout,pipeline 就不知道哪些框该给文字识别器、哪些给表格、哪些给公式。
下面这张来自项目基准测试的示例页面,就是 PP-DocLayoutV3 实际输出的一页:页眉(header)、正文(text)、段落标题(paragraph_title)、图表(chart)、图题(figure_title)、页脚(footer)、页码(number)全部被正确框出并分类。
PP-DocLayoutV3 的 25 类版面标签详解
PP-DocLayoutV3(RT-DETR-L 变体)在固定 800×800 输入上运行,每个检测框输出class_id、置信度、边界框和阅读顺序索引。25 类标签定义在 layout_types.h 中,顺序与官方模型的label_list完全一致:
| 用途分组 | 类别(class_id) |
|---|---|
| 标题与正文 | doc_title(6)、paragraph_title(17)、text(22)、vertical_text(23)、content(4)、abstract(0)、aside_text(2)、algorithm(1) |
| 页面家具 | header(12)、header_image(13)、footer(8)、footer_image(9)、number(16) |
| 图与表 | table(21)、image(14)、chart(3)、figure_title(7) |
| 公式 | display_formula(5)、inline_formula(15)、formula_number(11) |
| 注释与附录 | footnote(10)、vision_footnote(24)、reference(18)、reference_content(19) |
| 特殊 | seal(20) 印章 |
还有一个"哨兵类":落在所有检测框之外的 OCR 结果会被赋予class_id = -1(SupplementaryRegion),保证每条识别结果都能在 layout 数组中找到归属,与 PaddleX 的兜底行为一致。
如何开启布局检测与阅读顺序:两个参数即可
TurboOCR 的 HTTP API 默认只做文字识别,布局功能是严格显式开启的。完整参数说明见 docs/api/http.md,核心参数如下:
| 参数 | 作用 |
|---|---|
layout=1 | 运行 PP-DocLayoutV3,响应中输出layout数组(每块区域的类别+框) |
reading_order=1 | 按模型预测的阅读顺序排序文本,自动隐含layout=1 |
as_blocks=1 | 输出段落级blocks,自动隐含 layout + reading_order |
tables=1/formulas=1 | 启用表格/公式识别分支,同样自动隐含 layout |
对一份像下面这样的普通文档扫描页,一条 curl 即可拿到"版面 + 阅读顺序 + 表格"的完整解析:
curl -X POST 'http://localhost:8000/ocr/raw?layout=1&reading_order=1&tables=1' \ --data-binary @page.png -H 'Content-Type: image/png'响应中,results[]每条文字都带上所属版面区域的layout_id,layout[]给出每个区域的类别与框,reading_order[]给出区域级阅读顺序。注意:如果服务启动时设置了DISABLE_LAYOUT=1,这些请求会返回400 LAYOUT_DISABLED,错误信息会直接告诉你如何解锁。
阅读顺序是怎么算出来的:模型预测 + XY-cut 兜底
这是 TurboOCR 布局系统最"智能"的部分,核心实现在 reading_order.cpp 与 xy_cut.cpp:
第一优先:模型自带的阅读顺序。PP-DocLayoutV3 的每个检测行第 7 列(read_order)就是模型自己预测的阅读顺序索引。当该信号完整有效时,TurboOCR 直接按它排序——单栏堆叠段落保持从上到下,区域内部文字行按行序排列,落在所有区域之外的行紧随其"正上方区域"之后。
兜底方案:三层分桶 + XY-cut。当模型顺序缺失或退化(所有区域拿不到各自名次)时,几何回退接管。类别先被划入三个"层"(定义见 layout_types.h#L66-L85):
| 层 | 桶 | 包含类别 |
|---|---|---|
| TOP(最先读) | 0 | header(12)、header_image(13) |
| BODY(主区) | 1 | 其余所有类别,含页码number(16) |
| BOTTOM(最后读) | 2 | footer(8)、footer_image(9)、footnote(10)、reference(18)、reference_content(19)、vision_footnote(24) |
页码被刻意留在 BODY 层——因为它可能出现在页面顶部也可能在底部,让 XY-cut 按几何位置自然归位。每个桶内部再运行 XY-cut 递归切分,双栏、斜切栏、跨栏框都能得到从左到右、从上到下的自然顺序;页眉页脚这种"页面家具"无论检测器把它放在哪里,都会落到正确的阅读槽位。相关行为有专门测试覆盖:test_reading_order_buckets.cpp。
嵌套框处理:LAYOUT_MERGE_MODE 三种模式
版面模型经常把公式、标题、脚注有意嵌套在大区域内部(比如公式在正文块里)。后处理阶段(layout_postfilter.h)在 NMS、超大图过滤之后,会按环境变量LAYOUT_MERGE_MODE决定如何协调嵌套框(当 ≥90% 面积重叠时视为"内部框"):
| 模式 | 行为 | 适用场景 |
|---|---|---|
all(默认) | 保留所有框,不做嵌套消解 | 表单、复杂混排版面,什么都不想丢 |
outer | 只保留外层区域,丢弃内嵌框 | 只关心大区域结构的文档解析 |
inner | 只保留最内层框,去掉纯容器 | 想要最小粒度框的场景 |
旧名union/large/small作为弃用别名仍可使用。下面是同一份表单在三种模式下的对比:outer把表单收敛成少数外层容器,inner/all保留内部字段框。
两个贴心细节:
LAYOUT_KEEP_NESTED_CHILDREN=1可在outer/inner模式下额外保留模型的"合法子区域"(figure_title、footnote、formula_number、paragraph_title);- 公式类(5/15)永远不会被视为嵌套在非公式框内,独立的数学内容不会被周围文字或表格区域吞掉。
布局结果去了哪里:路由器把 25 类分发给不同引擎
layout->collect()之后,CPU 侧的 CUA 路由器(cua_router.cpp,纯文本页仅约 50 µs)读取每个布局框的class_id,按下表决定去向(详见 docs/architecture/router.md):
| 类别 | 路由去向 |
|---|---|
21table | 表格识别引擎(SLANeXt),输出 HTML |
5display_formula/ 15inline_formula | 公式识别引擎(PP-FormulaNet),输出 LaTeX |
9footer_image/ 13header_image/ 20seal | 跳过(Skip) |
3chart/ 14image | 默认跳过;若框内检出足够文字则回退为文字识别 |
| 其余所有文本类 | 文字识别(Text) |
路由还带有置信度分层:高置信直接放行;表格在"验证层"会跑一个 <1 ms 的轻量分类器确认"这真的是一张表吗",不是就降级为文字;低置信一律安全降级到文字识别,宁可用慢路径也不丢内容。
性能:为什么布局检测几乎"免费"
布局模型是 DETR 家族,输出数量在执行完之前未知——朴素的实现会在流水线中间同步 GPU,拖垮整条管线。TurboOCR 的解法是把调用拆成两阶段(设计契约见 paddle_layout.h):
enqueue(...)——异步完成预处理、H2D 拷贝、TRT 执行(FP16)和 D2H,只在一个独立的layout_stream_上排队;collect(...)——等识别(rec)跑完之后才执行,此时布局的 GPU 工作通常早已完成,同步等待近乎零开销。
效果就是总耗时受max(layout, cls + rec)约束,文本页的 p50 延迟里布局几乎不可见。整体管线的事件泳道图可参考 docs/architecture/pipeline.md 与 docs/architecture/cuda-streams.md。最终成绩:RTX 5090 上 Funsd 数据集 268.4 img/s、词级 F1 90.1%,OmniDocBench 阅读顺序编辑距离从基线 0.519 一路优化到 0.326(详见 docs/benchmarks/omnidocbench.md)。
相关文件速查
| 内容 | 路径 |
|---|---|
| 布局模型文档(模型卡/时序图) | docs/models/layout.md |
| 25 类标签 + 阅读顺序分桶 | include/turbo_ocr/layout/layout_types.h |
| 布局推理实现(enqueue/collect) | src/layout/paddle_layout.cpp |
| 嵌套框消解后处理 | include/turbo_ocr/layout/layout_postfilter.h |
| XY-cut 几何排序 | src/layout/order/xy_cut.cpp |
| 路由器(类→去向映射) | src/router/cua_router.cpp |
| HTTP 参数与响应示例 | docs/api/http.md |
| 精度回归基线 | docs/benchmarks/omnidocbench.md |
掌握layout=1&reading_order=1这两个开关,再理解 25 类标签与路由去向,你就已经会用 TurboOCR 完成从"扫一张纸"到"结构化文档"的全部链路了。🚀
【免费下载链接】TurboOCR
TurboOCR, >200 img/s OmnidocBench. TensorRT FP16, PP-OCRv6, HTTP + gRPC
相关推荐
PaddleOCR 版面分析模块实战:PP-DocLayoutV2 布局元素检测与阅读顺序还原指南
PaddleOCR 版面分析模块实战:PP DocLayoutV2 布局元素检测与阅读顺序还原指南 版面分析是文档解析系统的核心前置环节:它负责把一页文档"拆解
人工智能计算机视觉OCR深度学习大模型RAGPaddleX 版面分析模块实战指南:PP-DocLayoutV3 实例分割与阅读顺序预测全流程
PaddleX 版面分析模块实战指南:PP DocLayoutV3 实例分割与阅读顺序预测全流程 本指南以 PaddleX 开源仓库中的 版面分析模块教程 ht
人工智能大模型低代码计算机视觉深度学习模型推理服务PaddleX 版面分析模块全攻略:基于 PP-DocLayoutV3 的实例分割与阅读顺序预测实战
PaddleX 版面分析模块全攻略:基于 PP DocLayoutV3 的实例分割与阅读顺序预测实战 导读 本文是 PaddleX 中版面分析(Layout A
人工智能大模型低代码计算机视觉深度学习模型推理服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考