图像转MNIST黑字白底格式输出不符的代码修改咨询
MNIST格式图像转换黑字白底效果修复
问题描述
- 转换目标:将输入图像处理为MNIST数据集标准格式,要求28*28尺寸、黑字白底
- 预期效果:

- 运行现有基于PIL、matplotlib编写的预处理代码后,实际输出为:
,存在背景发灰、字迹对比度不足的问题,不符合格式要求。
问题根因
现有代码存在三个核心缺失:
- 未做输入图像的色彩方向校验:如果输入原图为黑底白字,直接粘贴到纯白画布上会出现暗背景残留,和预期的白底效果冲突
- 未做二值化处理:图像缩放、锐化过程中会产生大量介于黑白之间的灰色过渡像素,直接输出就会出现背景发灰、字迹边缘模糊的问题
- 插值参数过时:旧版本Pillow的
Image.ANTIALIAS参数在新版本中兼容性差,缩放后字迹清晰度不足
修改后可直接运行的代码
from PIL import Image, ImageFilter import matplotlib.pyplot as plt def imageprepare(argv): im = Image.open(argv).convert('L') # 自动判断是否需要反色,统一为白底黑字输入 pixel_avg = sum(im.getdata()) / (im.size[0] * im.size[1]) if pixel_avg < 128: im = im.point(lambda x: 255 - x) # 二值化过滤灰边,阈值可根据实际素材效果调整 threshold = 170 im = im.point(lambda x: 255 if x > threshold else 0) width = float(im.size[0]) height = float(im.size[1]) newImage = Image.new('L', (28, 28), (255)) # 生成28*28纯白画布 if width > height: nheight = int(round((20.0 / width * height), 0)) if nheight == 0: nheight = 1 img = im.resize((20, nheight), Image.Resampling.LANCZOS).filter(ImageFilter.SHARPEN) wtop = int(round(((28 - nheight) / 2), 0)) newImage.paste(img, (4, wtop)) else: nwidth = int(round((20.0 / height * width), 0)) if nwidth == 0: nwidth = 1 img = im.resize((nwidth, 20), Image.Resampling.LANCZOS).filter(ImageFilter.SHARPEN) wleft = int(round(((28 - nwidth) / 2), 0)) newImage.paste(img, (wleft, 4)) newImage.save("D:/Desktop/desktop/MNIST/sample1_fixed.png") tv = list(newImage.getdata()) # 按MNIST官方规则归一化:0对应纯白,1对应纯黑 tva = [(255 - x) * 1.0 / 255.0 for x in tv] print(tva) return tva x=imageprepare('D:/Desktop/desktop/MNIST/0/2.bmp') print(len(x)) # 输出784即符合MNIST单张图像的尺寸要求
调整说明
- 新增自动反色逻辑:通过计算图像平均亮度判断底色,自动完成黑底/白底的统一转换,不需要手动提前处理输入图
- 新增固定阈值二值化步骤:过滤缩放、锐化产生的灰色过渡像素,彻底解决背景发灰问题,输出纯黑字、纯白底的效果
- 替换插值参数:将已弃用的
Image.ANTIALIAS替换为Image.Resampling.LANCZOS,适配新版本Pillow,缩放后的字迹边缘更清晰 - 阈值可调:如果输出字迹偏细,可将
threshold调低至150左右;如果背景存在噪点,可将threshold调高至190左右
内容的提问来源于stack exchange,提问作者Lizzie
相关产品推荐
相关产品推荐

