目标:解决第一期遇到的"明明人眼能看清,OCR 却认错"的问题。核心手段是图像预处理和识别参数控制。
1. 图像预处理:OpenCV 三件套
OCR 对图像质量非常敏感。灰度化、去噪、二值化是最基础的预处理组合,能显著提升 Tesseract 等传统引擎的识别率。
python
import cv2
import numpy as np
def preprocess(image_path):
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 放大:小字变大字,对 Tesseract 尤其有效
gray = cv2.resize(gray, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
# 去噪 + Otsu 自动阈值二值化
blur = cv2.GaussianBlur(gray, (5, 5), 0)
_, binary = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return binary
processed = preprocess("receipt.jpg")
cv2.imwrite("processed.png", processed)
如果图片有倾斜,可以先用 cv2.minAreaRect 或霍夫变换做纠偏,再送入 OCR。
2. Tesseract 的 PSM 参数:告诉引擎"这是什么版式"
Tesseract 的 --psm 参数控制页面分割模式。默认模式 3 适合标准文档;如果只识别单行(比如身份证号、金额),用 psm 7;如果图片是稀疏的界面截图或小票,psm 11 往往更稳。
python
# 只识别单行数字,并限定字符白名单
text = pytesseract.image_to_string(
Image.open("amount.png"),
config="--psm 7 -c tessedit_char_whitelist=0123456789."
)
3. 用置信度做过滤
OCR 输出里的置信度分数是调优的重要信号。低于阈值的识别结果,与其硬用,不如标记出来交给人工复核。EasyOCR 和 PaddleOCR 都直接返回置信度,pytesseract 则需要用 image_to_data 获取。
python
# EasyOCR 按置信度过滤
filtered = [(bbox, text, score) for bbox, text, score in result if score > 0.5]
第二期的关键认知是:预处理决定了 OCR 的上限,参数决定了能否触达这个上限。同一张图,预处理前后、PSM 不同取值下的结果可能天差地别。https://github.com/0voice