《大话文渊慧典》:六
技术架构(下)——PPStructure的绣花功夫:布局检测、方向分类、文本检测、阅读顺序重建深度拆解
——大胖老师:“上回咱们把整条文渊慧典的流水线跑了一遍。小菜,你印象最深的是哪个环节?”
——小菜:“版面分析!我就想不通,一页乱七八糟的古籍,电脑是怎么一眼就看出哪儿是正文、哪儿是注的。”
——二黑头也不抬:“因为它不是‘看’出来的,是‘算’出来的。而且算的过程中,踩过的坑比你吃过的盐还多。”
——大胖老师:“二黑说得对。上回咱们只是走马观花,今天就把版面分析这个车间单独拎出来,扒到螺丝钉级别。四个模型,一个算法,外加三个差点让我们翻车的真实案例,一个不落。”
一、版面分析的四个“特种兵”
大胖老师在白板上画了四个小人,分别标注:布局检测、方向分类、文本检测、阅读顺序重建。
“很多人以为PPStructure就是一个模型,丢进去图片,吐出来结果。大错特错。”他敲着白板,“它是一支特种部队,每个队员都有自己的绝活,配合起来才能完成版面分析这个高难度任务。今天咱们就给每位队员单独列个档案,看看他们到底有什么本事,又有什么软肋。”
第一位:布局检测——全局扫描兵
“布局检测是第一个上场的。它的任务是在全图范围内快速定位所有‘有意义’的区域——文字块、表格、图片、印章——用矩形框标出来。只看大局,不管细节。速度要快,不能漏,也不能把墨渍当文字。”
二黑调出一张模型结构图:“它用的是基于ResNet的骨干网络,上面接特征金字塔(FPN)和检测头。ResNet负责提取图像特征,FPN负责融合不同尺度的特征——古籍里的文字块,大的像标题占半页,小的像夹注只有几个字,FPN能同时检测大小目标。检测头则输出每个框的坐标和类别标签。”
“但通用模型直接上古籍,问题很大。”大胖老师接过话,“因为它的训练数据主要是现代文档——横排、单栏、无边框。古籍是竖排、多栏、栏线断断续续、还混杂印章和墨渍。通用模型会把两栏粘在一起,把印章当文字,把栏线当细长行。所以我们做了两件事:微调和后处理。”
微调:二黑打开一张标注示例图,“我们从全国十几家图书馆收集了大约五千页不同时期、不同版式的古籍扫描件,手工标注了每一页的布局。正文、注文、眉批、标题、印章、页码,一个框一个框地标。这批‘古籍版面金标数据集’喂进去微调后,模型对古籍的适应能力大幅提升。正文和夹注的区分准确率从不到70%提升到了90%以上。”
后处理:“模型输出之后,我们还加了一层规则过滤。比如,印章区域通常颜色偏红、形状接近方形或圆形,我们用颜色直方图和形状特征做二次确认。栏线误检的问题,则靠形态学滤波——用OpenCV提取长直线特征,凡是形状接近直线且像素密度均匀的,都从文字候选区里剔除。双管齐下,基本解决了古籍特有的误检问题。”
第二位:方向分类——旋转校正兵
“布局检测给出了每个文字块的位置和类型,但这些块可能是竖的、横的、倒的。”大胖老师指着白板上的第二个小人,“方向分类器就是专门判断文字方向的微型模型。结构很简单,一个轻量级卷积网络,输出四个方向类别的概率:0度、90度、180度、270度。但它对古籍的意义,比很多复杂模型都大。”
“为什么?”小菜追问。
二黑代答:“因为古籍的文字方向不是全局统一的。正文竖排,眉批可能是横排,页码可能是横排,印章可能各种奇怪角度。如果不分块做方向检测,整体旋转90度,正文正了,眉批又歪了。所以方向检测必须精确到每一个文字块。”
大胖老师补充:“而且方向分类器还有一个隐藏功能——过滤误检。有些墨渍或纸张纹理被误检为文字块,送进方向分类器,因为找不到明确的文字方向,置信度会很低。我们设了一个阈值:置信度低于0.6的块,直接丢弃。这就把大量‘假阳性’拦截在了OCR之前,节省了算力,也避免了输出乱码。一石二鸟。”
第三位:文本检测——精细切割兵
“方向摆正之后,每个文字块还是一整坨,不能直接送OCR。需要把块里的每一行文字精确地切出来。”大胖老师把这一步比喻成“切豆腐”——把一整块豆腐切成均匀的长条,每一根条都是一行文字。
“PPStructure内部用的是DB(可微分二值化)文本检测算法。”二黑调出DB的论文截图,“它不是在像素上做二值化,而是让网络学习一个‘概率图’,表示每个像素属于文字的概率,然后用一个可微分的操作把它变成二值图。这样整个流程都是可导的,可以端到端训练。DB的优点是速度快、精度高,尤其对弯曲文本和多方向文本友好。”
“但古籍文本检测有特殊难点。”大胖老师指了指屏幕上的一行双行夹注,“这种小字注文,紧贴着正文,行间距极小。人眼能区分,但模型经常把注文和正文连成一行,或者把注文的两小行当成一行。我们在训练时,特意加大了夹注样本的比例,让模型多见这种‘亲密无间’的文字行。同时调整了DB的阈值参数,让它对小间距文本更敏感。代价是推理速度慢了约10%,但夹注的检测召回率提升了将近20个百分点——值。”
第四位:阅读顺序重建——整队指挥官
“所有文字行都检测出来、识别出来之后,还处在无序状态——东一行西一行。”大胖老师画了一群散乱的小点,“最后这位队员的任务,是把它们按照古人读书的顺序排列好。这是古籍OCR特有的刚需,现代文档根本没有这个需求。”
二黑站起来,在白板上画了一页示意图:“我们设计了一个两阶段排序算法。第一阶段,按列分组。算法扫描全页的文字行坐标,根据右上角的横坐标和纵坐标,把竖直方向上对齐的行归到一组。判断标准是:两行横坐标中心线距离小于阈值,且纵坐标有较大重叠区间。分组之后,列与列之间按横坐标从右到左排序。这就定下了‘从右到左’的大框架。”
“第二阶段,列内排序。同一列里的行,先按纵坐标从上到下排。但如果检测到夹注块——宽度明显小于正文的窄行——就把它们插到正确的位置。算法判断夹注的上边缘和哪一行正文对齐,就把它插到那行正文的后面。这样读的时候,先读正文,紧接着读夹注,读完再跳回下一行正文。”
小菜试着复述:“第一步‘分列排队’,第二步‘列内插队’?”大胖老师哈哈一笑:“用语不太学术,但理解到位。这个算法完全是基于坐标的规则引擎,不需要额外模型,跑起来飞快。对常见的单栏、双栏、夹注版式,准确率超过95%。”
二、差点让版面分析翻车的三个真实案例
讲完四个模型的基本原理,大胖老师话锋一转:“理论讲完了,现在上硬菜。这三个真实案例,每一个都差点让我们的版面分析当场去世。是二黑一个坑一个坑填过来的。”
案例一:明万历刻本的“隐形栏线”
“这套明万历刻本,栏线极细,加上年代久远墨色变淡,扫描后有些栏线在图像上几乎看不见。但看不见不等于不存在——它依然干扰着检测模型。布局检测把它当成细长的文字块,方向分类器因为它没有文字特征而给低置信度,但并没有低到被过滤的阈值。结果就是,这条‘隐形栏线’混进了OCR,输出了一串乱码。”
二黑补充:“我发现问题后,用图像增强把栏线显影出来,生成了一批‘栏线增强版’标注数据,重新微调模型。同时在形态学滤波里加了一条:即使像素密度不够均匀,只要形状是标准的长直线,也剔除。问题解决。这个案例告诉我:古籍版面里有很多‘隐形信息’,人眼能看到是因为有经验,模型没有经验,就得用数据把经验灌给它。”
案例二:乾隆朱墨套印本的“红色陷阱”
“乾隆朱墨套印本,正文是黑色,批注是红色,视觉效果很漂亮,但对二值化来说是个灾难。”大胖老师调出一张原图,“普通二值化把红色和黑色全变成了前景,正文和批注糊成一团。版面分析根本分不清谁是谁。”
二黑的解决方案是:“先用颜色分离,把红色通道和黑色通道分开,分别做二值化,生成两张独立的图片,再分别送版面分析。红色通道的图只包含批注,黑色通道的图只包含正文。最后在后处理里,把两个通道的识别结果按照坐标合并回去。多了一道工序,但效果立竿见影。后来我们把这个功能做成了一个可选项——‘朱墨套印模式’,遇到红黑双色的古籍,王大姐只需要勾选一下,系统自动切换处理管线。”
案例三:民国手抄本的字迹粘连
“某县馆的家谱,手写小楷,连笔严重。版面分析的文本检测把三个连在一起的草书字当成了一个‘超宽字’,切出来的行乱七八糟。”大胖老师叹了口气,“这种手抄本,连人眼都得仔细辨认,更别说模型了。”
二黑想了个不是办法的办法:“对手抄本降低文本检测的合并阈值,宁可把行切碎一点,也不要粘连。然后再靠后处理的阅读顺序算法把切碎的行重新拼回来。虽然增加了后处理的复杂度,但最终输出的文本是通的。这不是技术问题,是手抄本本身的模糊性。用工程手段兜底,比死磕模型更划算。”
三、版面分析的未来:从“模型+规则”到“端到端”
讲完案例,大胖老师让二黑展望一下未来。“你觉得下一代版面分析会是什么样?”
二黑想了想:“现在的方案还是‘模型+规则’的混合体——模型负责检测和识别,规则负责阅读顺序和异常处理。这套方案已经能解决大部分问题,但它有一个根本局限:规则是人写的,永远穷举不了古籍版式的所有变体。”
“我判断,未来三到五年,版面分析会走向端到端的统一模型。输入一页图像,直接输出按阅读顺序排列好的结构化文本,中间不再有独立的布局检测、方向分类、文本检测、阅读顺序重建这些模块。所有这些能力,全部内化在一个大模型里,通过海量古籍数据训练出来。就像ChatGPT从文本生成统一了NLP任务一样,版面分析的未来也是统一。”
“但这需要更大规模、更多样化的训练数据,也需要更强大的算力支撑。短期内,我们的混合方案仍然是最经济、最可控的选择。我们不追求技术上的完美,追求的是‘今天就能用,明天还能更好’的工程合理性。”
四、下期预告
大胖老师看看时间:“今天版面分析这块已经讲透了。四个模型,三个案例,一个未来展望。下一期,咱们进入流水线的最后一站——后处理与输出。”
小菜眼睛一亮:“就是那个把识别结果变成双层PDF、能搜索能复制的魔法环节?”
“对。”二黑翻开笔记本,“后处理里的门道不比版面分析少。置信度分析怎么辅助校对?语言模型怎么自动纠错?避讳字怎么自动补全?双层PDF的透明文字层怎么精确叠加?还有异体字标准化策略——学者要原字原样,普通读者要现代标准字形,怎么平衡?”
大胖老师拍板:“那就下期,主题就叫——”
《OCR的最后一公里:当识别结果遇上置信度分析、上下文纠错、避讳字补全,以及双层PDF里那些看不见的文字是怎么“隐身”的》
“小菜,别忘了约王大姐来听。她上次问的‘为什么识别出来的字有时候繁简混着来’,下期正好解答。还有,把你那个贴了三盒膏药的手腕养好,下一讲的内容密度不比今天低。”
小菜揉了揉手腕,在笔记本上重重记下。窗外夜色已深,实验室的白板上密密麻麻画满了流程图和检测框示意图。二黑已经打开IDE,开始优化昨天发现的阅读顺序bug——那个“三栏加眉批加侧批”的复杂版式,准确率还没达到他的预期。
大胖老师的保温杯第三次续了水。他站在白板前,看着那四个小人和三个案例,忽然笑了:“搞古籍OCR这几年,最大的感受是什么?不是技术有多难,是古籍太聪明了——它们用几百种方式告诉你:别想用一套规则搞定我。”
二黑头也不抬地接了一句:“所以我们要比古籍更聪明。或者,至少比它们更倔。”
小菜补了一刀:“或者,比它们更有耐心。毕竟它们已经等了几百年,不差这几个bug。”
笑声中,键盘声继续。窗外,校图书馆的灯次第亮起。
本文为注水技术版,您看看即可,不必当真,写此文字就是图一乐:-)
