如何用Python+OpenCV提升Tesseract对粗体数字的OCR识别准确率
屏幕数字OCR识别优化方案
1 先修复现有代码的逻辑bug
你当前版本代码存在逻辑错误:对resized做腐蚀后赋值给了rawImage,但后续HSV阈值处理用的还是未腐蚀的resized,腐蚀操作完全没生效,先修正这个流程问题。
2 替换锐化方案,解决笔画开裂问题
你用的3x3强锐化卷积核对二值化后的图像冲击力过大,容易导致笔画断裂,改用USM(非锐化掩膜)的柔化锐化方式,既提升边缘清晰度,又不会出现开裂:
# 替换原来的硬卷积锐化代码,USM锐化实现 def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0): blurred = cv2.GaussianBlur(image, kernel_size, sigma) sharpened = float(amount + 1) * image - float(amount) * blurred sharpened = np.clip(sharpened, 0, 255).astype(np.uint8) if threshold > 0: low_contrast_mask = np.absolute(image - blurred) < threshold np.copyto(sharpened, image, where=low_contrast_mask) return sharpened # 调用示例,在去噪之后调用即可,amount控制锐化强度,调整范围1.0-2.0 white_range = unsharp_mask(white_range, amount=1.2)
你之前调整卷积核中心值出现全黑,是因为卷积核权重和不为1导致亮度偏移,USM方案不存在这个问题。
3 调整Tesseract识别参数
你现在用的--psm 6是假设输入为单一均匀文本块,你是三行独立数字,更适合用--psm 12(稀疏文本模式),同时补充dpi参数,匹配你放大后的图像:
config='--psm 12 --oem 3 --dpi 300 -c tessedit_char_whitelist=0123456789'
4 可选优化方案(准确率提升更明显)
- 固定区域按行切割:你抓取的区域是固定的,三行数字的垂直位置固定,直接把图像切成三个单行区域,分别识别,彻底避免跨行识别串扰
- 改用模板匹配:你要识别的是固定样式的七段数码管数字,提前做好0-9的数字模板,用模板匹配做识别,准确率可以接近100%,比通用OCR稳定太多
修改后的核心预处理代码示例
with mss.mss() as sct: region = { 'left': 3577, 'top': 146, 'width': 171, 'height': 130 } image = sct.grab(region) mss.tools.to_png(image.rgb, image.size, output='loot1.png') rawImage = cv2.imread('test4.png') # 放大图像,放大场景用INTER_CUBIC比INTER_AREA效果更好 scale_percent = 260 width = int(rawImage.shape[1] * scale_percent / 100) height = int(rawImage.shape[0] * scale_percent / 100) dim = (width, height) resized = cv2.resize(rawImage, dim, interpolation = cv2.INTER_CUBIC) # 提取白色区域,反转成白底黑字 hsv = cv2.cvtColor(resized, cv2.COLOR_BGR2HSV) lower_white = np.array([0,0,235]) higher_white = np.array([255,255,255]) white_range = cv2.inRange(hsv, lower_white, higher_white) white_range = cv2.bitwise_not(white_range) # 轻度腐蚀细化笔画 kernel = np.ones((2, 2), np.uint8) white_range = cv2.erode(white_range, kernel, iterations=1) # 轻度高斯模糊去噪,比均值模糊更能保留边缘 white_range = cv2.GaussianBlur(white_range, (3,3), 0) # USM锐化 def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.2, threshold=0): blurred = cv2.GaussianBlur(image, kernel_size, sigma) sharpened = float(amount + 1) * image - float(amount) * blurred sharpened = np.clip(sharpened, 0, 255).astype(np.uint8) if threshold > 0: low_contrast_mask = np.absolute(image - blurred) < threshold np.copyto(sharpened, image, where=low_contrast_mask) return sharpened white_range = unsharp_mask(white_range) # 识别 data = pytesseract.image_to_string(white_range, lang='eng',config='--psm 12 --oem 3 --dpi 300 -c tessedit_char_whitelist=0123456789') numbers = [ int(m) for line in data.splitlines() if (m := "".join(ch for ch in line if ch.isdigit())).isnumeric() ] cv2.imshow("White", white_range) cv2.waitKey() print(numbers)
内容的提问来源于stack exchange,提问作者Kalween
相关产品推荐
相关产品推荐

