如何使用Numpy修改图像像素颜色,解决Pytesseract对红黄文本OCR识别失败问题
解决彩色文本转黑色以提高Tesseract OCR准确率的问题
你的核心问题主要有两个:一是循环中修改像素的方式不对,无法真正改变原数组,二是颜色判断逻辑覆盖不全,没包含黄色文本的情况。我来帮你逐个解决:
问题分析
- 无法修改像素的原因:你在循环里直接给
pixel赋值[0,0,0,255],但这里的pixel是数组元素的副本,不是对原snippet数组的引用,所以修改不会生效。必须通过索引直接操作原数组的元素。 - 颜色判断逻辑局限:你的条件
test[0] > 190 and test[2] < 100只能匹配部分亮红色,完全没考虑黄色(黄色的R和G值都偏高,B值偏低)。
正确实现方案
方法一:用Numpy向量化操作(推荐,效率更高)
Numpy的向量化操作比Python循环快得多,而且能精准修改数组元素。我们先定义红色和黄色的像素范围,生成掩码后批量修改:
import numpy as np # 截取图像片段 snippet = np_image[top: bottom, field.left: field.right].copy() # 定义红色掩码:R值高,G和B值低 red_mask = (snippet[..., 0] > 150) & (snippet[..., 1] < 100) & (snippet[..., 2] < 100) # 定义黄色掩码:R和G值高,B值低 yellow_mask = (snippet[..., 0] > 150) & (snippet[..., 1] > 150) & (snippet[..., 2] < 100) # 合并两种颜色的掩码 color_mask = red_mask | yellow_mask # 将符合条件的像素转为黑色(保留Alpha通道透明度) snippet[color_mask] = [0, 0, 0, 255] # 进行OCR识别 text = pytesseract.image_to_string(snippet)
方法二:使用Python循环(适合小尺寸图像)
如果你更习惯用循环,需要通过数组的索引(行和列的位置)来修改原元素:
import numpy as np snippet = np_image[top: bottom, field.left: field.right].copy() # 遍历每一行和每一列 for row_idx in range(snippet.shape[0]): for col_idx in range(snippet.shape[1]): # 获取当前像素的RGBA值 r, g, b, a = snippet[row_idx, col_idx] # 判断是否为红色或黄色 is_red = r > 150 and g < 100 and b < 100 is_yellow = r > 150 and g > 150 and b < 100 if is_red or is_yellow: # 直接通过索引修改原像素 snippet[row_idx, col_idx] = [0, 0, 0, 255] text = pytesseract.image_to_string(snippet)
额外优化建议
- 调整阈值:上面代码中的
150、100是参考阈值,你可以根据自己图像的实际颜色深浅微调,确保能准确匹配你的红色/黄色文本。 - 转灰度图再识别:修改完颜色后,把图像转成灰度图可以进一步提高Tesseract的识别准确率:
from PIL import Image # 将修改后的数组转为PIL图像,再转灰度 gray_snippet = Image.fromarray(snippet).convert('L') text = pytesseract.image_to_string(gray_snippet)
内容的提问来源于stack exchange,提问作者Psionman




