为何使用Tesseract无法精准识别清晰可见的数字?
Tesseract数字识别效果不佳的问题
尝试用Tesseract检测数字,图像背景噪声极低、为清晰单行样式,但识别效果始终不理想。已制作最小测试用例,先后对图像执行去除红通道、转灰度、二值化预处理,还尝试了缩放、降噪模糊、膨胀、腐蚀及不同PSM、OEM模式的组合处理。
测试图像

实际识别输出
img: 2 22419 2330 blur: 23 22419 226 16 333 03 Erode: Dilate: 22 22419 266330 Morphology: 2 22419 24 BlurMorphology: 2222419 26 116 BlurErode: BlurDilate: 23 22419 226633 3 03 BlurErodeDilate: 22 22419 226 16 3343 03 BlurErodeDilateMorphology: 2222419 26 116
期望输出
23 22 4 19 2 2 6 11 6 3 3 14 3 4 4 4 10 3 11 9
相关代码
from pytesseract import pytesseract import os import cv2 import numpy as np # 切换工作目录到脚本所在文件夹 os.chdir(r'C:\Users\tesseract') path_to_tesseract = r"C:\Program Files\Tesseract-OCR\tesseract.exe" pytesseract.tesseract_cmd = path_to_tesseract def remove_noise(image): return cv2.medianBlur(image,5) def dilate(image): kernel = np.ones((4,4),np.uint8) return cv2.dilate(image, kernel, iterations = 1) def erode(image): kernel = np.ones((4,4),np.uint8) return cv2.erode(image, kernel, iterations = 1) def morphology(image): kernel = np.ones((5,5),np.uint8) return cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel) def boundingBox(name, img): hImg, wImg, _ = img.shape h, w, c = img.shape boxes = pytesseract.image_to_boxes(img, config = "_char_whitelist=0123456789") for b in boxes.splitlines(): b = b.split(' ') x, y, w, h = int(b[1]), int(b[2]), int(b[3]), int(b[4]) img = cv2.rectangle(img, (x, hImg - y), (w, hImg - h), (0, 255, 0), 2) cv2.putText(img, b[0], (x, hImg - y + 13), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (50, 205, 50), 1) cv2.imshow(name, img) cv2.waitKey(0) def findNumbers(img, name): text = pytesseract.image_to_string(img, config = "-c tessedit" "_char_whitelist=' '0123456789" " --psm 3 " "lang='eng'") # 打印结果 print(str(name) + ": " + str(text)) img = cv2.imread('testData2.png') #------------------------------------------------------------------- # 第一阶段预处理 Blur = remove_noise(img) Erode = erode(img) Dilate = dilate(img) Morphology = morphology(img) # 第二阶段预处理 BlurErode = erode(Blur) BlurDilate = dilate(Blur) BlurMorphology = morphology(Blur) # 第三阶段预处理 BlurErodeDilate = dilate(BlurErode) # 第四阶段预处理 BlurErodeDilateMorphology = morphology(BlurErodeDilate) #------------------------------------------------------------------- # 第一阶段输出 findNumbers(img, "img") findNumbers(Blur, "blur") findNumbers(Erode, "Erode") findNumbers(Dilate, "Dilate") findNumbers(Morphology, "Morphology") # 第二阶段输出 findNumbers(BlurMorphology, "BlurMorphology") findNumbers(BlurErode, "BlurErode") findNumbers(BlurDilate, "BlurDilate") # 第三阶段输出 findNumbers(BlurErodeDilate, "BlurErodeDilate") # 第四阶段输出 findNumbers(BlurErodeDilateMorphology, "BlurErodeDilateMorphology") #------------------------------------------------------------------- # 第一阶段检测框标注 boundingBox('img', img) boundingBox('Blur', Blur) boundingBox('Erode', Erode) boundingBox('Dilate', Dilate) boundingBox('Morphology', Morphology) # 第二阶段检测框标注 boundingBox('BlurErode',BlurErode) boundingBox('BlurDilate',BlurDilate) # 第三阶段检测框标注 boundingBox('BlurErodeDilate',BlurErodeDilate) # 第四阶段检测框标注 boundingBox('BlurErodeDilateMorphology', BlurErodeDilateMorphology)
解决方案
1. 优化预处理流程
当前预处理未落实灰度化和自适应二值化的核心步骤,Tesseract对单通道灰度图识别效果远优于彩色图。调整步骤:
- 先将彩色图转为灰度图
- 采用自适应二值化,避免全局二值化丢失局部细节
- 缩小降噪、形态学操作的核尺寸,防止过度腐蚀/膨胀破坏数字结构
2. 调整Tesseract配置参数
- PSM模式:替换默认的
--psm 3为--psm 7(将图像视为单行文本),匹配图像的单行特征 - 字符白名单:修正语法错误,正确格式为
-c tessedit_char_whitelist=" 0123456789" - OEM模式:添加
--oem 3,启用LSTM+传统引擎的混合模式,提升识别精度
3. 修改后的代码示例
from pytesseract import pytesseract import os import cv2 import numpy as np os.chdir(r'C:\Users\tesseract') path_to_tesseract = r"C:\Program Files\Tesseract-OCR\tesseract.exe" pytesseract.tesseract_cmd = path_to_tesseract def preprocess_image(img): # 转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化 thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 轻度降噪 denoised = cv2.medianBlur(thresh, 3) return denoised def findNumbers(img, name): # 优化后的识别配置 config = r'-c tessedit_char_whitelist=" 0123456789" --psm 7 --oem 3' text = pytesseract.image_to_string(img, config=config, lang='eng') print(f"{name}: {text.strip()}") img = cv2.imread('testData2.png') processed_img = preprocess_image(img) # 测试识别效果 findNumbers(processed_img, "processed_img") # 查看预处理后的图像 cv2.imshow("Processed Image", processed_img) cv2.waitKey(0) cv2.destroyAllWindows()
4. 额外优化建议
- 若存在数字粘连,可尝试垂直形态学梯度分割字符
- 将图像放大1-2倍,提升小数字的识别清晰度
- 针对图像中的字体训练自定义Tesseract字库,进一步优化识别准确率
内容的提问来源于stack exchange,提问作者mak47
相关产品推荐
相关产品推荐

