运行Keras图像识别教程代码遇双重报错及H5文件写入异常
解决Keras图像识别代码的KeyError和ValueError问题
看起来你遇到的问题主要出在路径解析和标签处理上,咱们一步步拆解解决:
问题根源分析
- KeyError: 'imgs':这其实是第一次运行代码时的正常现象——因为
X.h5文件还没生成,里面自然没有imgs数据集,所以代码会进入异常处理流程去处理原始图片,这个本身不是bug,但后面的ValueError才是阻碍数据生成的关键。 - ValueError: 无法将'Final_Training'转为整数:你的
get_class函数用img_path.split('/')[-2]取分类文件夹名,但由于路径分隔符适配问题(比如Windows下是\而不是/),或者路径结构解析错误,导致你取到的不是分类文件夹的数字名称,而是Final_Training这个字符串,转int自然失败。 - 移除int转换后
X.h5仍无法正确写入:因为标签变成了字符串,而np.eye(NUM_CLASSES)[labels]要求索引必须是整数,这会导致one-hot编码失败,最终无法生成有效的Y数组,写入h5自然出问题。
修复方案
1. 修复分类标签获取函数
用Python标准库的os.path工具来解析路径,它会自动适配Windows/macOS/Linux的路径分隔符,确保正确获取分类文件夹名:
def get_class(img_path): # 先获取图片的父文件夹路径 parent_dir = os.path.dirname(img_path) # 再提取父文件夹的名称(也就是分类标签的字符串形式) class_str = os.path.basename(parent_dir) try: return int(class_str) except ValueError: print(f"警告:路径{img_path}中的分类名称{class_str}不是整数,跳过该图片") return None # 返回None方便后续过滤
2. 完善数据处理流程,添加校验
在循环处理图片时,增加对图片形状、标签有效性的校验,避免生成无效数据:
import os import glob import numpy as np import h5py from skimage import io # 请根据你的数据集实际分类数量修改这个值 NUM_CLASSES = 43 def preprocess_img(img): # 示例预处理:调整为32x32尺寸,归一化到0-1范围 from skimage.transform import resize img = resize(img, (32, 32)) return img def get_class(img_path): parent_dir = os.path.dirname(img_path) class_str = os.path.basename(parent_dir) try: return int(class_str) except ValueError: print(f"无效分类名:{class_str},路径:{img_path}") return None try: with h5py.File('X.h5', 'r') as hf: X, Y = hf['imgs'][:], hf['labels'][:] print("✅ 成功从X.h5加载数据") except (IOError, OSError, KeyError) as e: print(f"⚠️ 加载X.h5失败:{e},开始处理原始图片...") root_dir = 'Data/Final_Training/Images/' imgs = [] labels = [] # 用os.path.join拼接路径,避免分隔符问题 all_img_paths = glob.glob(os.path.join(root_dir, '*', '*.ppm')) print(f"🔍 找到{len(all_img_paths)}张图片") np.random.shuffle(all_img_paths) for idx, img_path in enumerate(all_img_paths): # 每处理1000张打印进度 if idx % 1000 == 0: print(f"⏳ 已处理{idx}/{len(all_img_paths)}张图片") try: img = io.imread(img_path) img = preprocess_img(img) # 确保所有图片预处理后形状一致(比如32x32x3) if img.shape != (32, 32, 3): print(f"❌ 图片{img_path}形状异常:{img.shape},跳过") continue label = get_class(img_path) # 过滤无效标签 if label is None or label < 0 or label >= NUM_CLASSES: print(f"❌ 标签无效:{label},路径:{img_path},跳过") continue imgs.append(img) labels.append(label) except (IOError, OSError) as e: print(f"❌ 处理图片失败:{img_path},错误:{e}") pass print(f"🎉 处理完成,共收集{len(imgs)}张有效图片") # 转换为numpy数组 X = np.array(imgs, dtype='float32') # 生成one-hot编码标签 Y = np.eye(NUM_CLASSES, dtype='uint8')[labels] print(f"📊 数据形状:X={X.shape}, Y={Y.shape}") # 写入h5文件 with h5py.File('X.h5', 'w') as hf: hf.create_dataset('imgs', data=X) hf.create_dataset('labels', data=Y) print("✅ 数据已成功写入X.h5")
3. 额外检查点
- 确认你的数据集路径结构:
Data/Final_Training/Images/下的子文件夹必须是整数命名的分类文件夹(比如0、1、2...),每个文件夹下存放对应类别的ppm图片。 - 确认
NUM_CLASSES的值和实际分类数量一致,否则one-hot编码会失败。 - 检查
preprocess_img函数:确保它能将所有图片处理成相同的形状(比如统一的宽高和通道数),否则np.array(imgs)会生成不规则数组,无法写入h5文件。
内容的提问来源于stack exchange,提问作者randomUser
相关产品推荐
相关产品推荐

