如何在Keras的image_dataset_from_directory中忽略损坏图片而不删除
加载图片时忽略损坏文件的解决方案
使用Keras的image_dataset_from_directory时,确实没有直接参数跳过损坏图片,但可以通过两种方式实现保留文件、加载时过滤的需求:
方法1:预筛选有效图片后构建数据集
先遍历目录检查所有图片的有效性,收集有效路径后再创建数据集,避免加载时触发异常:
步骤1:编写图片有效性检查函数
import os from PIL import Image def is_image_valid(file_path): try: with Image.open(file_path) as img: img.verify() # 验证图片结构完整性 img.load() # 额外检查像素数据,避免头文件正常但内容损坏的情况 return True except (IOError, SyntaxError, ValueError): return False
步骤2:收集有效图片路径与标签
data_dir = "你的图片根目录路径" class_names = sorted([d for d in os.listdir(data_dir) if os.path.isdir(os.path.join(data_dir, d))]) class_indices = {name: idx for idx, name in enumerate(class_names)} valid_paths = [] valid_labels = [] for cls_name in class_names: cls_dir = os.path.join(data_dir, cls_name) for img_file in os.listdir(cls_dir): img_path = os.path.join(cls_dir, img_file) if is_image_valid(img_path): valid_paths.append(img_path) valid_labels.append(class_indices[cls_name])
步骤3:构建并预处理数据集
import tensorflow as tf from tensorflow.keras.layers import Rescaling def load_image(path, label, img_size=(256, 256)): img = tf.io.read_file(path) img = tf.image.decode_image(img, channels=3, expand_animations=False) # 忽略动图 img = tf.image.resize(img, img_size) return img, label # 创建数据集 dataset = tf.data.Dataset.from_tensor_slices((valid_paths, valid_labels)) dataset = dataset.map(load_image, num_parallel_calls=tf.data.AUTOTUNE) # 常规数据集操作:打乱、分批、预取 dataset = dataset.shuffle(1000).batch(32).prefetch(tf.data.AUTOTUNE) # 添加归一化层(可选) normalizer = Rescaling(1./255) dataset = dataset.map(lambda x, y: (normalizer(x), y))
方法2:基于image_dataset_from_directory过滤无效样本
如果已经依赖image_dataset_from_directory的默认配置(如自动划分验证集、类名自动识别等),可以利用return_file_paths参数获取文件路径,再过滤损坏样本:
import tensorflow as tf data_dir = "你的图片根目录路径" img_size = (256, 256) batch_size = 32 # 获取包含文件路径的原始数据集(先不分批) raw_dataset = tf.keras.utils.image_dataset_from_directory( data_dir, image_size=img_size, batch_size=None, return_file_paths=True # 返回 (图片, 标签, 文件路径) 元组 ) # 定义过滤函数:检查图片是否可正常解码 def filter_corrupted(image, label, file_path): try: # 重新解码验证图片有效性 img_bytes = tf.io.read_file(file_path) tf.image.decode_image(img_bytes, channels=3, expand_animations=False) return tf.constant(True) except tf.errors.InvalidArgumentError: return tf.constant(False) # 过滤无效样本,并移除路径信息 filtered_dataset = raw_dataset.filter(filter_corrupted) filtered_dataset = filtered_dataset.map(lambda img, label, path: (img, label)) # 分批与预取 filtered_dataset = filtered_dataset.batch(batch_size).prefetch(tf.data.AUTOTUNE)
注意事项
- 方法1适合数据集规模较小的场景,提前过滤能减少后续加载的异常风险;
- 方法2更适配
image_dataset_from_directory的原生配置,但需要注意先设置batch_size=None,过滤后再分批; - 图片有效性检查可以结合PIL和TensorFlow的解码逻辑,确保覆盖更多损坏场景(如文件头正常但数据损坏的图片)。
内容的提问来源于stack exchange,提问作者Tuan Do
相关产品推荐
相关产品推荐

