Pytesseract无法识别小数点:兼顾文本识别的十进制数值优化
混合文本与十进制数值场景的Tesseract识别优化方案
核心矛盾说明
全局启用0123456789.的字符白名单时,Tesseract会硬过滤所有不在白名单内的意大利语字母、标点,直接导致普通文本无法正常输出,这也是白名单方案无法适配混合场景的根本原因。以下优化方案可以同时兼顾普通文本识别准确率与小数数值的识别效果。
具体优化步骤
- 采用分块识别替代全局单参数识别
利用pytesseract内置的image_to_data接口,一次性获取图像内所有文本块的坐标、识别内容、置信度,通过块内数字字符的占比做拆分:- 数字占比超60%的块,单独裁剪后使用仅含数字、小数点的白名单参数跑识别
- 其余普通文本块,使用意大利语语言包搭配常规参数跑识别
这种拆分方式彻底绕开了白名单对普通文本的过滤影响,同时让数值块的识别精度达到纯白名单场景的水平。
- 调整基础OCR参数降低基础误判
替换默认的OCR引擎与页面分割参数,使用适配混合排版的配置:
如果仍希望启用白名单,不要仅配置数字与小数点,要把场景内可能出现的意大利语字母、常用标点全部纳入白名单范围,既不会误过滤普通文本,也能减少Tesseract把小数点误判为横杠、下划线的概率。# 参数说明:--oem 3 使用全功能LSTM引擎,--psm 6 按统一文本块排版识别,-l ita 指定意大利语语言包 ocr_config = r'--oem 3 --psm 6 -l ita' - 针对小数点的识别痛点做定向图像增强
实际识别中出现的数字后带—、_的偏差,本质是图像里的小数点尺寸太小、像素特征过弱,被Tesseract误判为长横线的端点。预处理阶段可以通过连通域分析,定位那些面积远小于数字块、形状接近正方形的小连通域(也就是模糊的小数点),对其做轻度膨胀,让像素大小和数字笔画匹配,从源头降低误判。对应的预处理逻辑参考:import cv2 import numpy as np def preprocess_for_mixed_ocr(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化消除光照不均带来的字符边缘模糊 binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # 识别并增强类小数点的小连通域 num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(binary, connectivity=8) for i in range(1, num_labels): area = stats[i, cv2.CC_STAT_AREA] block_w = stats[i, cv2.CC_STAT_WIDTH] block_h = stats[i, cv2.CC_STAT_HEIGHT] # 小数点的典型特征:面积远小于数字块,宽高接近相等 if area < 15 and block_w < 8 and block_h < 8: component = (labels == i).astype(np.uint8) binary[cv2.dilate(component, np.ones((2,2), np.uint8)) == 1] = 255 return binary - 增加规则化后处理修正歧义字符
对初步识别的结果做校验:如果连续内容属于数值块,且相邻两个数字之间出现-、_、—类歧义字符,结合邻接特征判断——如果歧义字符被数字完全包裹、没有和字母相邻,就将其替换为小数点;如果歧义字符和字母相邻(比如文本里的分隔符),就保留原字符,避免出现误替换。
内容的提问来源于stack exchange,提问作者marco
相关产品推荐
相关产品推荐

