扫描仪盖板没压实或者翻拍时纸没摆正,页面就会带一点倾斜。识别前要不要先纠斜?我把同一页按 0°、1°、3°、5° 各转一遍再分别交给三个识别器去认。结果这个问题得先问「后面接的是哪个识别器」。歪 3° 时 Tesseract 在不加噪的英文页上只从 98.9% 降到 98.1%。macOS 自带的文字识别几乎没变。浏览器端的 PP-OCR 却把行序排乱了,中文页错字从 2 个涨到 175 个。
两页样本和打分方式
样本是两页清晰的出版物扫描。中文页取自国家语言文字工作委员会 1986 年《关于重新发表〈简化字总表〉的说明》那一页的 557 个字。英文页是 H. G. Wells《The Time Machine》1895 年版第 8 页,归一后有 1,002 个字符。两页都只有一栏而且字号适中。倾斜是程序转出来的而不是真的扫歪了。打分用字符级编辑距离:多一个字、少一个字、错一个字各记 1。字符准确率就是 1 减去编辑距离与原文字数之比。我还单算了一个「丢字数」,只数原文里有多少字在输出里找不到,不管顺序。有了它就能分开「字没认出来」和「字都在但顺序乱了」这两种坏法。
转页面本身很简单,要留意的是画布得扩大并把空出来的角填白。不然四个角要么被裁掉要么变成黑块,黑块也会被当成内容去认。下面是按这个定义简化的示意,表里的数来自完整脚本:
from PIL import Image
src = Image.open("page.png").convert("L")
for deg in (1, 3, 5):
# 绕页面中心转,expand 保住四个角,空白处填白
tilted = src.rotate(deg, resample=Image.BICUBIC, expand=True, fillcolor=255)
tilted.save(f"page_rot{deg}.png")
第一个识别器是 Tesseract 5.5.3,只装了英文语言包,中文页没测。第二个是 macOS 自带的文字识别,用的是系统 Vision 框架的精确模式。第三个是浏览器端的 PP-OCR。这一路我用的是图映 ImgIng imging.cn/ 的 PDF 内容提取,选默认的专业档。页面上写的模型是 PP-OCRv6 small。识别在电脑的桌面浏览器里完成。机器是一台 Apple M4 的 Mac,每组都只跑一次。
Tesseract对3度倾斜不太敏感
先看 Tesseract:英文页存成 PNG 且不加噪声时,0°、1°、3°、5° 依次是 98.9%、99.5%、98.1%、96.2%。歪 3° 掉 0.8 个点而歪 5° 掉 2.7 个点,比我预想的温和得多。加上 σ=25 的高斯噪声后四个角度变成 97.9%、96.8%、95.2%、92.9%。倾斜和噪声叠在一起才开始明显往下走。只做纠斜就能把不加噪的 5° 拉回 99.0%。投影法给 3° 那张估出的角是 3.3°。多出来的 0.3° 是原页自带的歪。
1° 反而比 0° 高 0.6 个点。这个我没搞懂。原页本来带着约 0.3° 的倾斜而且每组只跑一次。我不敢把它解释成「歪一点反而好」,先当成波动记着。Tesseract 更怕的其实是噪声:同一页撒上 5% 的椒盐噪声后不歪也只剩 75.5%。跟它一比 3° 的倾斜几乎算不上事。
macOS自带识别几乎不受倾斜影响
macOS 自带的文字识别是另一种反应。中文页 0°、1°、3°、5° 的错字数是 5、4、8、5。英文页 0°、3°、5° 是 0、1、0,一直在同一个水平上晃。在中文页另做的 60 组预处理对照里纠斜对它也几乎没贡献。做完 Otsu 二值化它反而一律略差。它也不是什么都扛得住:英文页歪 3° 再加 σ=12 的高斯噪声后错字一下到了 50 个。其中「"Our ancestors had no」这一整行被挪到了下一行后面。
浏览器端PP-OCR歪3度就乱了行序
反应最大的是浏览器端这一路。不歪的时候它在这两页上错得最少。中文错 2 个:单独印出来的偏旁「讠」没认出来,「雠」认成了繁体「讎」。英文只错 1 个,是页码 8 没输出。歪 1° 时中文错 1 个也还正常。
到了 3° 就变了:中文错 175 个、丢 31 个字。我对了一下输出。两行短句整行不见,段首那一行被排到了下一行之后。英文错 400 个,丢字却只有 1 个。字基本都认出来了,只是每段首行跑到了第二行后面,按顺序一比对就全算成了错字。歪 5° 时中文错 362 个、丢 275 个,原文 14 行只剩一半左右。界面上照样显示处理完成而且没有任何提示。
它为什么偏偏在 3° 出问题?我没查清楚。PP-OCR 一般先检测文字框再逐框识别,最后按位置把框拼成行。我猜页面一歪后相邻两行的框在上下位置上交错了,拼行时就排错了顺序。这只是推测。图映内部怎么排行我不知道。1° 到 3° 之间从哪一度开始乱也没测。
能让三个识别器都回来的是预处理。歪 3° 加噪声的页面先做非局部均值去噪再用投影法纠斜,最后做 Otsu 二值化。中文页 macOS 自带错 6 个、浏览器端错 2 个。英文页 macOS 自带错 1 个、Tesseract 错 13 个、浏览器端错 2 个。浏览器端的行序恢复了,错字数回到和原页差不多的水平。
图:同一页旋转后再识别的错字数。样本为国家语言文字工作委员会《简化字总表》1986 年新版说明页(Internet Archive 公有领域标记)与 H. G. Wells《The Time Machine》1895 年版第 8 页(维基共享资源 公有领域)。倾斜和噪声版本是自制的。这张图要看中间两行浅蓝底。歪 3° 和 5° 时两列图映的错字数跳到几百,旁边 macOS 自带识别还是个位数。最后一行做完预处理,两列图映都回到错 2。
图里英文 Tesseract 那一列用的是 JPEG 页面,歪 3° 错 23 个、歪 5° 错 38 个。它和前面 PNG 页面的百分比不是同一张图,两组数别放在一起比。
先测自己用的识别器
这组数的范围要先说清。两页都是清晰的单栏印刷件。倾斜和噪声是程序加的,每组只跑了一次。手机翻拍的透视变形、双栏排版、150 DPI 以下的低分辨率扫描都没测。真扫歪的页面会不会是同一个样子,我还不知道。
在这两页上「歪 3° 掉多少」没有统一答案。Tesseract 掉不到 1 个点,macOS 自带识别基本不掉,浏览器端 PP-OCR 的行序直接乱掉。写预处理之前可以先拿自己的一页样本转 3° 和 5° 各识别一次,同时看错字数和丢字数。在这两页上,丢字少而错字多的是顺序乱了,纠斜后救了回来。丢字也多就是真漏认了,得另想办法。对倾斜敏感的识别器要把纠斜放在识别之前。像 macOS 自带这种不在意倾斜的,省掉这一步影响不大。Otsu 在它身上还可能帮倒忙。
样本署名:中文页为国家语言文字工作委员会《关于重新发表〈简化字总表〉的说明》及《简化字总表》(1986 年新版),Internet Archive 公有领域标记;英文页为 H. G. Wells《The Time Machine》(William Heinemann 1895)第 8 页,维基共享资源公有领域;倾斜、噪声版本为自制。