OCR 的版面重建:从一堆文字框还原出行与表格

最近在看浏览器端 OCR 的实现,看到一个容易被忽略的地方:识别模型的输出,和用户想要的结果,中间隔着一层不小的工程。
模型给你的是「文字框 + 内容 + 置信度」,一堆散点。用户想要的是能直接粘进 Word 或 Excel 的东西。这中间的还原过程——判断哪些框属于同一行、哪些行构成一段、哪些列构成一张表——没有模型帮你做,得自己写规则。

一、引擎输出的不是文章,是一堆带坐标的框

把一张图送进 OCR,模型实际做两件事:检测和识别。检测负责找出图里哪些区域有文字,输出一组四边形框;识别负责读出每个框里是什么内容,顺带给一个置信度。

所以原始输出长这样——一组 {坐标, 文本, 置信度}。它是空间上的散点,不带任何"这是第几行第几列"的信息。

这里就出现了那个分水岭:如果直接把这些框按某种顺序(比如从上到下)拼接输出,就得到一坨连续文本。字是对的,但表格塌了、分栏串了、段落粘在一起。很多"识别挺准但结果没法用"的体验,卡在这一步。

要让结果可用,得先把散点还原成结构。

二、版面重建:行、段、表格列各靠什么推

还原用的信息,全在框的几何关系里。

并行。判断两个框是不是同一行,看它们在纵向上有没有重叠、重叠比例够不够。单纯比较框的中心 y 坐标不够稳——同一行里字号可能不同(表头加粗、单位小字),中心点会错开。用重叠区域占行高的比例判断,比用中心点稳。

分段。行并好之后,看相邻两行的纵向留白。行内间距和段间距是有差别的,段落之间通常有明显更大的空白。这个阈值不能写死,得按当前这张图的行高分布来定——同样是 20 像素的间隔,在小字文档里是段落间隔,在大标题里可能只是行距。

切列。表格列比段落难。判断依据是横向间距的突变:一行里相邻两个框之间的空白,如果显著大于该行内的普通字间距,就可能是列边界。然后要跨行验证——单独一行的间隙可能只是这行文字短,多行在同一横向位置都出现间隙,才更像真的列分隔。

图映的 OCR 页面把这套逻辑写得比较明确:识别后根据文字框重叠、行高、横向间距和纵向留白,恢复视觉行、段落与表格列。复制和 TXT 以换行保留原图行,以 Tab 分隔表格列;Markdown 会在连续列结构稳定时生成表格。

注意「连续列结构稳定时」这个限定。列结构不稳定的时候(跨行合并单元格、嵌套表格),它就不硬生成表格了。这个处理是诚实的——硬凑出来的表格比不给表格更麻烦,因为你还得先发现它凑错了。

image

上图是我那张表格截图的识别结果。左边原图上每个识别到的文本块都被框了出来,表格的行列结构在框的分布上一眼可辨;右边是重建后的版面文本,另外提供 TXT、Markdown、JSON 三种导出。JSON 里带坐标和置信度,要自己做后处理的话从这里取。

界面上还有个细节:点击原图里的文字框,右侧会定位到对应的校对行。校对 OCR 结果时这个双向定位很实用——发现某行不对,能马上回到原图确认到底是识别错了还是原图本来就模糊。

三、三档模型:体积、语言和准确率的取舍

浏览器端跑 OCR,模型体积是硬约束——它要下载到用户设备上。图映给了三档 PP-OCRv6:

档位 体积 语言范围 定位
极速 约 6.0 MB 中、英与拉丁语系 移动端
专业 约 31.2 MB 增加日语 桌面默认推荐
极致 约 138.8 MB 增加日语 桌面,复杂小字

分三档的原因,在移动端那一侧最明显:手机浏览器的内存压力大,微信内置浏览器和 Safari 都可能因为内存不足直接把页面干掉。所以移动端只开放极速档,并且限制过大的输入文件。这是个务实的选择——给移动端用户一个 138 MB 的模型,大概率是下载到一半页面就没了。

还有一点值得注意:三档使用固定的模型名称、大小和 SHA-256,不会在运行时静默替换。对于要在浏览器里下载几十兆二进制文件的场景,这条挺重要——校验值固定意味着你可以核对拿到的到底是不是预期的那个模型。

四、放在浏览器里跑,代价是多少

我用专业档跑了一次完整识别,记录如下(桌面 Chrome,2880×1734 的 PNG 截图):

实测值
识别结果 69 行 · 605 字
用时 20.9 秒(含首次模型下载)
后端 WebGPU
检测模型 PP-OCRv6_small_det,约 9.4 MB
识别模型 PP-OCRv6_small_rec,约 20.3 MB
两个模型合计 约 29.7 MB(页面标称约 31.2 MB)
整个过程的 POST 请求数 0

几点说明:

20.9 秒是首次的数字,大头在下载那 29.7 MB 模型。模型按需下载后会独立缓存,同一档位第二次用不再重复下载。所以这个数字不该理解成"识别一张图要 20 秒",而是"第一次用这一档要等模型"。

后端显示 WebGPU,说明优先路径生效了;没有 WebGPU 的环境会自动降级到 WASM,运行时用的是 ort-wasm-simd-threaded.jsep.wasm

POST 请求数为 0 是我特意盯的一项。识别全程在独立 Worker 里完成,图片和识别出的文字都没有出设备——这一条不用信承诺,F12 打开 Network 面板筛 POST 自己看就行,几秒钟的事。

模型和运行时确实要从服务器下载到浏览器,这是 GET;原图和识别结果没有上行。两件事要分开说。

五、它做不到什么

这部分线上页面写得比多数同类产品坦白,值得照抄过来:

手写体不在当前版本的承诺范围。印刷体和手写体的形态差异大,用同一套模型硬做,结果不可预期。

数学公式的语义做不了。公式里的字符可能被识别出来,但上下标、分式结构这些语义关系不会被还原成 LaTeX 之类的形式。

任意复杂的表格关系也不承诺。前面说的列切分对规整表格有效,跨行合并单元格、嵌套表头这类结构,重建结果需要人工核对。

韩文当前的统一模型不含。

我倾向于认为,把这几条写在功能页上,比写十条"精准识别"更有参考价值——你至少知道什么时候不该用它。

六、怎么判断一个 OCR 工具的版面重建做得如何

不用看宣传,拿一张有表格的截图,三步就能试出来:

第一步,复制出来看结构。 直接把识别结果复制到文本编辑器。行还在不在?表格列之间是不是有明确的分隔符(Tab 是常见做法,能直接粘进表格软件)?如果得到的是一坨连续文本,说明它只做了识别没做重建。

第二步,找一处字号不同的地方。 表头加粗、单位用小字,这类地方最容易暴露并行逻辑的粗糙——用中心点判断同行的实现,在这里会把本该同行的内容拆开。

第三步,看它给不给坐标和置信度。 如果输出里有 JSON 带坐标,说明中间结果是完整保留的,你可以自己做后处理;只给纯文本的话,重建效果不满意就没有补救余地了。

顺带一提,如果你的图片涉及合同、证件、内部报表这类不方便外传的内容,还可以加一步:F12 打开 Network 面板,筛 POST,看识别过程有没有上行请求。这个验证只花几秒,但比任何隐私声明都直接。

我用的是图映(imging.cn)的图片文字识别,上面那些数字都是写这篇时实测跑出来的,方法和验证方式都写在正文里,可以自己复现。

posted @ 2026-08-29 11:45  langka  阅读(1)  评论(0)    收藏  举报