如何优化Pytesseract从低质量小尺寸数字图像中提取文本的准确率?
如何优化Pytesseract从低质量小尺寸数字图像中提取文本的准确率?
问题背景
我正在尝试用pytesseract从图像中提取数字,它能识别部分数字(1、2、3、5、6、20...),但没法覆盖所有情况。我用的图像尺寸很小(75x26),字体质量一般,但人眼可以清晰识别。
我试过一些预处理,比如对比度增强:
from PIL import Image, ImageEnhance image = Image.open(f"{i}.png") gray = image.convert("L") enhancer = ImageEnhance.Contrast(gray) image_enhanced = enhancer.enhance(2.0) text = pytesseract.image_to_string(image_enhanced, config="--psm 6 -c tessedit_char_whitelist=0123456789") print(text)
也试过用OpenCV做阈值处理,但效果还是不好(比如识别不出1,把11识别成0,把9识别成3...):
img = cv2.imread(f'/content/{i}.png') img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 170, 255, cv2.THRESH_BINARY) text = pytesseract.image_to_string(thresh, config="--psm 6 -c tessedit_char_whitelist=0123456789")
想知道有没有更多预处理步骤能提升识别准确率?我知道可以微调pytesseract,但觉得这应该是基础问题,不想先花太多时间在微调上。
我的解决方案
嘿,我之前也踩过类似小尺寸低质量数字识别的坑,结合实战经验给你几个针对性的优化方向,应该能解决你识别7、11、415这类数字的难题:
- 优先放大图像,解决小尺寸核心问题
Tesseract的训练样本大多是常规尺寸的文本,75x26的小图像特征太模糊,先把图像放大2-4倍(用高质量插值算法,避免边缘锯齿),会让数字的轮廓特征清晰很多。比如用PIL实现:
from PIL import Image, ImageEnhance image = Image.open(f"{i}.png") # 放大3倍,用LANCZOS插值保持清晰度 scaled_image = image.resize((image.width*3, image.height*3), Image.Resampling.LANCZOS) gray = scaled_image.convert("L")
用OpenCV的话可以这么写:
img = cv2.imread(f'/content/{i}.png') img = cv2.resize(img, None, fx=3, fy=3, interpolation=cv2.INTER_LANCZOS4)
- 替换固定阈值为自适应阈值,适配局部明暗
你用的固定阈值(170)没法适配所有图像的明暗差异,自适应阈值会根据每个局部区域的亮度自动调整阈值,对付这类模糊字体效果更好。注意如果你的数字是深色、背景浅色,记得用THRESH_BINARY_INV反转颜色,让数字变成白色、背景黑色,更贴合Tesseract的训练习惯:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应阈值:blockSize选奇数(比如11),C是微调偏移量(比如2) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
- 调整PSM参数,精准匹配单数字串场景
你用的--psm 6是假设图像是一块均匀文本,但对于单数字串,试试--psm 8(假设图像是单个词)或者--psm 10(假设图像是单个字符),这两个参数能让Tesseract更聚焦于你的目标内容:
text = pytesseract.image_to_string(thresh, config="--psm 8 -c tessedit_char_whitelist=0123456789") # 记得strip()去掉多余的换行和空格 print(text.strip())
- 用形态学操作修复字体瑕疵
有些模糊数字会有断笔、毛刺,用OpenCV的闭运算修复断笔,开运算去除毛刺,让数字轮廓更规整:
# 创建3x3的矩形结构元素 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) # 闭运算:先膨胀后腐蚀,填补断笔 thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) # 开运算:先腐蚀后膨胀,去除毛刺 thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
- 组合预处理流程,效果翻倍
把上面的步骤组合起来,完整流程大概是:
- 放大图像 → 2. 转灰度 → 3. 自适应阈值二值化(反转) → 4. 形态学修复 → 5. Tesseract识别
我之前用这套流程解决过类似的小尺寸数字识别问题,识别准确率提升非常明显,不需要微调模型就能覆盖大部分场景。
备注:内容来源于stack exchange,提问作者User_123917425
相关产品推荐
相关产品推荐

