Python PIL基于像素颜色提取图像清晰文字 适配OCR识别需求
带波动白字的图像文字提取优化方案
问题背景
- 核心需求:移除图像内非文字内容,保留清晰完整的文字,输出结果可被任意OCR程序正常识别
- 现存难点:目标文字为白色,但文字像素RGB值不固定为
(255,255,255),单像素数值存在波动,固定RGB阈值无法精准筛选全部文字像素;尝试过RGB转其他色彩空间、百分比阈值等方案,暂未得到可行实现 - 原有实现缺陷:基于固定RGB上下限的逐像素判断逻辑处理效果不达标,存在文字边缘像素漏判、背景像素误判问题,输出结果无法满足OCR识别要求。原有实现代码如下:
RGB_min=[180,180,180] RGB_max=[245,245,245] def level(img): copy = img.copy() for x in range(img.size[0]): for y in range(img.size[1]): pxl = list(copy.getpixel((x, y))) # if pxl[0] < 220 and pxl[1] < 220: if (pxl[0] < RGB_min[0] and pxl[1] < RGB_min[1] ) or (pxl[0] > RGB_max[0] or pxl[1] >RGB_max[1]) : pxl[0] = 255 pxl[1] = 255 pxl[2] = 255 else: pxl[0] = 0 pxl[1] = 0 pxl[2] = 0 copy.putpixel((x, y), tuple(pxl)) return copy image = Image.open('1.png') leveled = level(image) leveled.save('2.png')
原有代码的核心问题
- 逐像素遍历效率极低,大尺寸图像处理耗时是OpenCV向量化操作的数十倍
- 固定RGB区间判断逻辑未考虑白字抗锯齿、半透明叠加的像素特征,既会漏掉边缘的浅灰色文字像素,也会误判背景中接近白色的噪点
- 没有后处理逻辑,零散噪点、文字边缘缺口会大幅降低OCR识别准确率
- 输出为白字黑底格式,不符合绝大多数OCR模型的输入偏好,识别率会受影响
优化实现方案
整套逻辑基于HSV色彩空间筛选+自适应二值化+形态学后处理实现,不受RGB数值波动影响,能完整保留文字(包括抗锯齿边缘),输出标准黑字白底的OCR友好格式。
实现步骤
- 第一步:将图像从RGB空间转换到HSV空间,白色在HSV空间的特征为饱和度极低、明度极高,特征区间非常稳定,不受RGB单通道数值波动影响,可一次性筛出所有白字像素(包括抗锯齿的浅灰边缘)
- 第二步:使用自适应高斯阈值做二值化,修正图像局部亮度差带来的误判
- 第三步:通过形态学闭运算修补文字边缘缺口,开运算去除零散的背景噪点
- 第四步:反转颜色得到黑字白底的标准输出格式
可直接运行的代码
依赖安装:pip install opencv-python pillow numpy
import cv2 import numpy as np from PIL import Image def extract_text(input_path, output_path): # 读取原始图像 img = cv2.imread(input_path) # 转换到HSV色彩空间 hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义白色的HSV区间:覆盖纯白、浅灰白等所有白字相关像素 lower_white = np.array([0, 0, 170]) upper_white = np.array([180, 35, 255]) # 初筛得到文字掩码 text_mask = cv2.inRange(hsv_img, lower_white, upper_white) # 自适应阈值二值化,适配局部亮度差异 binary_img = cv2.adaptiveThreshold( text_mask, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2 ) # 形态学操作:补文字缺口+去背景噪点 kernel = np.ones((2, 2), np.uint8) binary_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel) binary_img = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel) # 反转得到黑字白底的标准OCR输入格式 result = 255 - binary_img # 保存结果 Image.fromarray(result).save(output_path) # 调用示例 extract_text("1.png", "2.png")
参数调整说明
- 若存在文字漏检、笔画残缺:将
lower_white中的明度值(第三个参数)从170逐步下调,最低可到140 - 若存在背景噪点残留:将
upper_white中的饱和度值(第二个参数)从35逐步下调,最低可到15 - 若文字边缘缺口明显:将形态学卷积核尺寸从
(2,2)调整为(3,3) - 若需要提取其他颜色的文字,只需要修改HSV区间的上下限即可,整套逻辑通用
内容的提问来源于stack exchange,提问作者art
相关产品推荐
相关产品推荐

