为何同版本Tesseract对近似图片的OCR识别结果差异极大?
问题原因
这个差异和复制部署的Tesseract环境本身无关,核心原因是两张图之间1-2的像素差值刚好踩中了Tesseract内置二值化流程的阈值临界点:
- Tesseract调用Leptonica执行识别前,第一步预处理就是图像二值化,默认的自适应二值化算法对灰阶临界值的波动极其敏感。截图里的文字是系统抗锯齿渲染生成的,文字边缘本身就是半透明混合出的过渡灰阶,1-2的像素差就足以让算法把文字边缘像素判定为背景,或是把背景噪点判定为文字笔画,直接打乱后续的字符分割逻辑。
- 这1-2的像素差和Windows显示色彩设置无关,常见诱因是两台设备显卡驱动的伽马校正差异、Pillow ImageGrab抓屏时32位带透明通道帧缓冲转24位RGB的取整误差、系统色彩管理模块的处理差异,这类微小偏移在跨设备抓屏场景下非常普遍。
- 之前尝试的归一化方案无效,是因为该方案仅做全局色阶拉伸,无法消除全域均匀的1-2像素偏移,只要偏移值刚好卡到二值化阈值,就依然会触发识别错误。异常图识别出
ЕВЕ,就是二值化后文字笔画断裂、字符分割错乱,被Tesseract误判为3个独立大写字母导致的。
本次测试使用的Tesseract版本信息如下:
tesseract v5.1.0.20220510 leptonica-1.78.0 libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.3) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0 Found AVX2 Found AVX Found FMA Found SSE4.1 Found libarchive 3.5.0 zlib/1.2.11 liblzma/5.2.3 bz2lib/1.0.6 liblz4/1.7.5 libzstd/1.4.5 Found libcurl/7.77.0-DEV Schannel zlib/1.2.11 zstd/1.4.5 libidn2/2.0.4 nghttp2/1.31.0
测试执行命令为tesseract <good/bad>.png stdout -l rus,正常样图识别结果为Карта получателя,异常样图识别结果为ЕВЕ。
解决方案
- 跳过Tesseract默认的二值化逻辑,在Pillow中提前做固定阈值二值化预处理:抓屏后先将图像转为灰度模式,用固定阈值做二值划分,示例代码为
img = img.point(lambda p: 255 if p > 180 else 0),阈值可根据实际截图在170-190区间调整,确保两张存在1-2像素差的图都能完整保留文字笔画、过滤背景,从根源避开二值化临界点问题。 - 抓屏时直接指定色彩空间转换规则,使用
ImageGrab.grab(bbox=目标区域).convert('L')直接抓取灰度图,跳过系统默认的色彩管理转换链路,从抓屏环节减少像素值偏移。 - 识别单行文本时给Tesseract添加
--psm 7参数,强制启用单行文本识别模式,关闭自动版面分析,避免笔画断裂时被误分割为零散独立字符。
内容的提问来源于stack exchange,提问作者Den Avrondo
相关产品推荐
相关产品推荐

