从图片表格到成绩录入:一次 OCR 与大模型结合的表格识别实践

在体育测评、青训评估、校园体测等业务场景中,成绩采集往往仍然依赖纸质表格。教练或测评人员在现场手写记录成绩,后续再由运营人员录入系统。这类流程看似简单,但实际存在几个明显问题:录入耗时、人工容易出错、纸质表格格式不统一、手写内容识别困难。

因此,我们希望实现一个能力:用户上传一张表格图片,系统自动识别表头和成绩数据,并转换成系统可接收的成绩录入结构,最终完成成绩提交。

这篇文章整理一下这个过程中的技术方案、关键难点,以及 OCR 和大模型两种方式的取舍。

一、整体流程

整个链路可以拆成五步:

  1. 用户上传图片,前端传入图片 URL
  2. 后端调用 OCR 或视觉大模型识别表格
  3. 解析得到 headersrows
  4. 将识别结果映射到系统中的测评项目、报名人、测评次数
  5. 封装为成绩录入对象并提交

理想的数据结构大致如下:

{
  "headers": [
    "姓名",
    "冲刺跑(5米分段计时)-No.1",
    "冲刺跑(10米分段计时)-No.1"
  ],
  "rows": [
    {
      "姓名": "张三",
      "冲刺跑(5米分段计时)-No.1": "3'95",
      "冲刺跑(10米分段计时)-No.1": "5'21"
    }
  ]
}

看起来很直观,但真正困难的地方并不在接口调用,而在“不稳定输入”到“稳定业务数据”之间的转换。

二、OCR 方案:稳定,但需要大量后处理

OCR 表格识别的优势是:它更像一个确定性的工具,倾向于识别文字、单元格、行列坐标,而不是进行语义发挥。对于成绩录入这类要求准确的数据场景,这是很重要的。

典型 OCR 返回的是一组单元格信息,包括:

  • 单元格文本
  • 行索引
  • 列索引
  • 单元格坐标
  • 可能还有合并单元格信息

后端需要基于这些单元格重建表格结构:

Map<Integer, Map<Integer, String>> table

其中第一层 key 是行号,第二层 key 是列号。

然后再判断哪一行是表头,哪几行是数据。比如如果第一行是“身体能力评价方案”“技术能力评价方案”这类分组标题,就应该忽略这一行,使用下一行作为真实表头。

OCR 的主要问题是细节符号容易丢失。例如图片中 3'95 可能被识别成 395-No.1 可能被识别成 No.1。这不是代码删除了符号,而是 OCR 在识别阶段就漏掉了这些细小字符。

所以 OCR 方案必须配套后处理规则:

  • No.1 自动规范化为 -No.1
  • _No.1 自动规范化为 -No.1
  • 对计时类项目,395 可按规则修正为 3'95
  • 对表头中的括号、中英文符号、空格做统一处理
  • 对重复表头自动补充 -No.2-No.3

但这些修正规则必须谨慎,只能在明确业务场景下生效。比如 395 是否一定是 3'95?只有当表头是“计时类项目”时才合理,如果是分数、距离、次数,就不能随便改。

三、大模型方案:理解能力强,但容易“发挥”

视觉大模型的优势是理解能力强。它能直接看图片,理解表格结构,也能在倾斜、模糊、拍照质量较差的情况下给出相对完整的 JSON。

但大模型最大的问题是:它有时会补全、猜测、纠错,甚至编造数据。

比如表格里明明只有少数几个手写成绩,大模型可能根据上下文补出一整行:

{
  "冲刺跑(5米)": "1",
  "冲刺跑(10米)": "11",
  "冲刺跑(20米)": "22"
}

这在内容生成场景里可能叫“合理推断”,但在成绩录入场景里就是严重错误。

所以使用大模型时,提示词必须非常克制:

  • 只识别图片中真实可见的内容
  • 空白单元格必须为空
  • 不确定就返回空字符串
  • 不要根据相邻单元格、规律、示例或常识补数据
  • headers 只来自图片原文
  • 不要参考系统项目配置
  • 不要替换、纠错、发挥

更重要的是,系统项目匹配不应该交给大模型完成。大模型只负责识别图片内容,业务标准化应该由后端代码完成。

四、为什么项目匹配应该放在后端

识别出来的表头可能是:

冲刺跑(5米分段计时)No.1

而系统项目可能是:

冲刺跑(5米分段计时)-No.1

或者系统只存项目名:

冲刺跑(5米分段计时)

如果让大模型去匹配系统项目,它很容易把整个系统项目列表都返回到 headers 中,导致表格列数暴增。更好的做法是:

  1. 大模型或 OCR 只返回图片识别结果
  2. 后端清洗表头
  3. 后端根据项目名称模糊匹配系统项目
  4. -No.1-No.2 等测评次数优先保留图片识别结果
  5. 匹配成功后再生成系统内部成绩对象

这样职责更清晰,也更可控。

五、成绩录入前的关键校验

识别只是第一步,真正入库前还需要做多层校验:

  • 是否识别到有效表头
  • 是否识别到有效数据行
  • 姓名是否能匹配到报名人
  • 表头是否能匹配到测评项目
  • 测评次数是否能解析
  • 空白成绩是否跳过
  • 同一个报名人是否存在多个成绩项
  • 图片表格中不存在的列不能凭空生成

对于无法识别的内容,系统不应该强行提交,而应该提示用户重新拍照或人工修正。

在成绩录入场景里,“少录一项,人工补录”通常比“错录一项,后续排查”更可接受。

六、OCR 与大模型如何取舍

如果表格比较规整,推荐优先使用 OCR。它更稳定、更可控,也更适合结构化录入。

如果图片质量较差、表格不规则、存在复杂合并单元格,可以考虑视觉大模型。但大模型最好只作为识别辅助,不要让它承担业务判断。

更稳的组合方式是:

  • OCR 负责行列结构和单元格文本
  • 大模型辅助判断表头区域、纠正明显 OCR 错误
  • 后端负责项目匹配、次数解析、成绩校验和提交

也可以进一步升级为“切格识别”:先用 OpenCV 或 OCR 坐标切出每个单元格,再对单个单元格做识别。单格识别比整图识别更不容易串行、串列,也更不容易让模型脑补整行数据。

七、总结

图片表格自动录入并不是简单地“调一个 OCR 接口”或“让大模型返回 JSON”。真正的难点在于:

  • 表格结构不稳定
  • 手写内容不稳定
  • OCR 会漏符号
  • 大模型会发挥
  • 业务项目需要精确匹配
  • 成绩数据不能容忍编造

比较合理的设计原则是:

  • 识别层只负责“看见什么识别什么”
  • 标准化层负责表头清洗、符号修正
  • 业务层负责项目匹配、报名人匹配和成绩封装
  • 校验层负责拦截低质量识别结果

对于成绩录入这类高准确性场景,系统应该宁可保守,不要聪明过头。自动化的目标不是完全替代人工判断,而是把大部分清晰、标准、重复的录入工作自动完成,把不确定的部分留给人工确认。

《从图片表格到成绩录入:一次 OCR 与大模型结合的表格识别实践》有1条评论

发表评论