简介:古籍文字识别是古籍数字化项目的关键环节,也是通用OCR最难覆盖的场景之一。本文系统拆解超大规模异体字集、复杂版面结构、低质量图像与语义歧义四大技术难点,梳理字符集建模、版面分析、识别模型与知识后处理等关键技术模块,并给出扫描规范、预处理流水线、评估指标与选型评估框架等工程实践建议,帮助读者有效提升识别率、显著降低人工校对成本。
做过古籍数字化的人几乎都有同样体会:通用OCR识别现代印刷体游刃有余,一遇到古籍就彻底”歇菜”。原因并不玄妙——现代简体中文常用字不过六七千,字符表规整、版面以横排为主、训练语料充足;而古籍的世界是另一套规则:繁体书写、竖排右起、异体字总量以十万计,再叠加纸张残损、透光、批注混排等糟心状况,通用模型自然水土不服。
需要说明的是:对现代印刷体和标准文档,各云厂商提供的通用文字识别服务(如百度智能云的通用OCR类产品)已相当成熟,这类能力解决的是”规整文档”问题;而古籍场景需要的是专门针对古籍特性优化过的识别能力与配套工程流程。本文不评测具体产品,而是把古籍识别拆解为可量化、可验证的技术问题,讲清楚难点在哪、方案由什么构成、工程上如何把识别率真正做上去。
通用OCR的输出层通常只覆盖数千个常用汉字。古籍场景下,字符来源至少包括四类:
若把历代抄刻变体都计入,字形总量可达十几万量级。这带来两个工程问题:其一,模型输出层必须支撑数万级字符表,训练数据要覆盖足够多的字形样本,长尾字形的样本均衡是训练的关键矛盾;其二,识别之后还面临”归一化”问题——例如中医古籍中”脈/脉””癥/症””薑/姜”这类异体字对,究竟保留原字形还是映射为标准字形,需要支持可配置的输出策略,否则后续校勘与全文检索都会受影响。
更进一步的是上下文歧义:同一个”反”字,在医籍语境里可能是”返”的通假字,也可能是本义,判断依据不在字形而在语义。这意味着纯视觉模型存在天花板,必须引入语言层面的后处理。
古籍版面的复杂度远超现代文档:
普通行切分算法面对这些情况的典型故障是:夹注混入正文、列序输出颠倒、批注文字插入错误位置。正确做法是让版面分析引擎独立建模——先用区域检测/语义分割技术切分出”正文列、批注区、图表区”等语义区域,再按古籍阅读顺序对列排序输出。以一本带朱笔眉批的批注本为例,理想输出应当是:正文按列序完整提取,批注单独输出并保留与正文的位置对应关系,图表区域标记为非文本。这三类信息一旦混杂,人工整理成本极高,自动版面分析的价值正在于此。
一句经验之谈:图像质量不行,再好的模型也救不回来。古籍扫描件的典型问题包括:
预处理流水线需要针对性完成倾斜矫正、背景估计、自适应二值化与界行/栏线去除。尤其栏线与界行这类竖向细长直线,若不去除,极易被误切成”一列文字”。
古籍文本还存在大量”字形无误但用字非常规”的现象:避讳改字、通假借用、抄写者个人习惯用字等。共性在于:单看字形无法确定正确输出,必须结合上下文与领域知识(如方剂名、人名、专名词典)校正。这也是成熟方案往往在视觉模型之后挂载”知识增强”后处理层的原因。
一个完整的古籍识别系统,通常由四个模块串联而成。
构建覆盖数万字形的字符表,并为异体字建立映射关系;对未编码字形,映射到最接近的已编码字形,同时保留原图坐标供人工复核,确保信息不丢失。
基于深度学习的区域检测输出结构化版面描述,支持单栏、多栏、批注栏、图表等区域类型,并按古籍阅读顺序重排文本列。核心排序逻辑可用一行代码表达:
def reorder_ancient_columns(lines):"""按古籍'从右至左、从上到下'的阅读顺序重排文本列(示意)"""# lines 中每项含文本及外接框坐标return sorted(lines, key=lambda l: (-l["x_left"], l["y_top"]))
x坐标降序(右列在前)、y坐标升序(上方在前)——一个符号差异,体现了古籍与现代文档在版面逻辑上的本质不同。
主流架构为”CNN特征提取 + 序列建模(BiLSTM或Transformer)+ CTC/注意力解码”。大字符集场景的工程要点在于:类别数达到数万后,输出层规模与样本均衡成为主要矛盾,通常需要字形聚类、样本增广等手段补齐长尾字形。
评估古籍识别效果,业界常用字符准确率(CAR),其计算基于编辑距离:
def levenshtein(ref: str, hyp: str) -> int:"""编辑距离(动态规划示意实现)"""dp = list(range(len(hyp) + 1))for i, rc in enumerate(ref, 1):prev, dp[0] = dp[0], ifor j, hc in enumerate(hyp, 1):cur = min(dp[j] + 1, # 删除dp[j - 1] + 1, # 插入prev + (rc != hc)) # 替换prev, dp[j] = dp[j], curreturn dp[-1]def char_accuracy(ref: str, hyp: str) -> float:"""字符准确率 = 1 - 编辑距离 / 参考文本长度"""return 1.0 - levenshtein(ref, hyp) / max(len(ref), 1)
但只有一个总体CAR远远不够。建议构建分层测试集并分别统计:规范刻本(如大型官修丛书刻印本)、民国铅印/石印本、手抄本三类底本的识别率可能相差数个百分点;再按”常用字/罕见字/异体字”分组统计,才能定位系统真实短板。行业经验表明:成熟的古籍识别方案整体准确率可达90%以上,规范刻本能接近99%,而模糊抄本则明显下滑——底本类型与图像质量,往往比模型本身更决定最终结果。
现实最优解从来不是100%全自动,而是”机器初识别 + 置信度驱动的分层人工校对”:先校版面与列序(结构错误影响整页),再校低置信度字符,最后抽查高置信度片段。这套流程能把人工工作量压缩一个数量级。
无论是评估外部服务还是自研方案,建议按统一矩阵打分,用自建测试集实测,而非轻信宣传数字:
| 评估维度 | 关键问题 |
|---|---|
| 字符覆盖 | 字符表规模、异体字归一化是否可配置 |
| 版面能力 | 多栏/批注/图表区分、阅读顺序还原、双行夹注处理 |
| 准确率 | 自建分层测试集上的CAR及分组表现 |
| 输出格式 | 结构化程度、坐标保留、图文对照支持 |
| 工程能力 | API调用、批量并发、断点续跑、失败重试 |
| 安全合规 | 数据是否用于训练、是否支持私有化部署 |
| 采购合规 | 能否开具正规发票、满足科研报销与审计要求 |
两点特别提醒:其一,务必用自己的底本实测一轮再做决策——别人测出的99%不等于你的99%;其二,关注数据授权条款,古籍项目常涉及馆藏文献授权,数据安全绝非小事。
古籍文字识别不是”一个OCR模型”,而是字符集工程、版面分析、序列识别、语义后处理与人机协同校对的系统工程。技术选型之外,真正拉开效率差距的往往是那些朴素环节:扫描分辨率是否达标、朱批信息是否保留、测试集是否分层、低置信度字符是否被高亮。把图像质量与评估体系做扎实,识别率自然站得住,校对成本自然降得下来——这也是高校与科研机构众多古籍数字化项目反复验证过的共同经验。