You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于简单全连接架构的MNIST手写数字识别模型自定义图片识别错误问题咨询

解决自定义手写数字图片在MNIST模型上识别错误的问题

你的两个猜测完全说到点子上了——自定义图片和MNIST数据集的分布差异就是识别出错的核心原因,我来帮你拆解清楚,并给出具体的解决步骤:

核心原因分析

  • 灰度与对比度不匹配:MNIST图片是标准的黑底白字,数字和背景的灰度差拉满(数字像素接近255,背景接近0),几乎是二值化的状态;而你的自定义图片偏灰,意味着背景和数字的边界模糊,模型之前学习到的边缘、轮廓特征没法对应上。你代码里做了颜色反转,但如果原始图片不是纯黑纯白,反转后依然存在中间灰度值,和MNIST的特征分布不符。
  • 数字的位置与尺寸偏差:MNIST里的数字都是居中放置,且占画布的比例相对固定(大概70%-80%);如果你的自定义数字要么太小、要么偏移到角落,模型学习到的“数字在中心区域”的先验知识就失效了,自然会识别错误。

针对性解决方法

1. 统一图片灰度风格(模拟MNIST的二值化特征)

先把自定义图片处理成和MNIST一致的黑底白字、高对比度风格:

# 替换你原有的图片处理循环
for file in filenames:
    picture = Image.open(file).convert('L')
    pic_r = picture.resize((28, 28))
    pic = np.array(pic_r)
    
    # 二值化:用阈值把灰度图转成黑白,消除中间灰阶
    threshold = 127  # 可以根据你的图片亮度调整,偏亮的图调大阈值
    pic = np.where(pic > threshold, 255, 0)
    
    # 反转颜色,确保数字是白色、背景是黑色(和MNIST一致)
    pic = 255 - pic
    
    # 归一化
    pic = pic / 255
    pic_eds = np.expand_dims(pic, axis=0)
    data.append(pic)
    data_eds.append(pic_eds)

2. 对齐数字的位置与尺寸(复刻MNIST的布局)

让自定义数字和MNIST一样居中、比例合适,需要做自动裁剪+居中缩放:

def preprocess_custom_image(image_path, target_size=(28,28)):
    img = Image.open(image_path).convert('L')
    
    # 第一步:裁剪掉空白边缘,只保留数字区域
    img_array = np.array(img)
    # 这里假设你的原始图片是白底黑字,若不是请把255改成0
    non_zero_indices = np.where(img_array != 255)
    if len(non_zero_indices[0]) == 0:
        return np.zeros(target_size)
    
    y_min, y_max = non_zero_indices[0].min(), non_zero_indices[0].max()
    x_min, x_max = non_zero_indices[1].min(), non_zero_indices[1].max()
    cropped_img = img.crop((x_min, y_min, x_max+1, y_max+1))
    
    # 第二步:等比例缩放,留20%空白模拟MNIST的边距
    max_dim = max(cropped_img.size)
    scale = target_size[0] / max_dim * 0.8
    new_size = (int(cropped_img.size[0]*scale), int(cropped_img.size[1]*scale))
    resized_img = cropped_img.resize(new_size, Image.Resampling.LANCZOS)
    
    # 第三步:将数字居中放到28x28画布上
    final_img = Image.new('L', target_size, 255)  # 先做白底,后续反转
    paste_x = (target_size[0] - new_size[0]) // 2
    paste_y = (target_size[1] - new_size[1]) // 2
    final_img.paste(resized_img, (paste_x, paste_y))
    
    # 第四步:反转颜色+归一化
    final_array = np.array(final_img)
    final_array = 255 - final_array
    final_array = final_array / 255
    return final_array

# 使用这个函数处理你的图片
for file in filenames:
    pic = preprocess_custom_image(file)
    pic_eds = np.expand_dims(pic, axis=0)
    data.append(pic)
    data_eds.append(pic_eds)

3. 可选:用自定义图片微调模型

如果预处理后仍有错误,可以用你的自定义图片对模型做小幅微调,让模型适应你的手写风格:

# 加载原模型
model = load_model('mnist_model.h5')

# 冻结前面的特征层,只训练最后一层分类器(避免破坏已学习的MNIST特征)
for layer in model.layers[:-1]:
    layer.trainable = False

# 用小学习率重新编译
model.compile(optimizer=keras.optimizers.Adam(learning_rate=0.0001),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

# 假设你有标注好的自定义数据:custom_x(预处理后的数组)、custom_y(one-hot标签)
model.fit(custom_x, custom_y, batch_size=4, epochs=3, validation_split=0.1)

# 保存微调后的模型
model.save('mnist_finetuned_model.h5')

内容的提问来源于stack exchange,提问作者RAU

火山引擎 最新活动