使用image_dataset_from_directory遇未知图片格式错误,已清理仍未解决
TensorFlow图像分类数据集格式错误排查问题
问题场景
图像分类任务中,数据集包含6个类别子文件夹,内有TensorFlow支持的jpg、png、jpeg格式图片。使用image_dataset_from_directory构建数据集后,运行以下代码遍历验证集val_ds时:
for x, y in val_ds: print(x.shape, y.shape)
出现错误:Unknown image file format. One of JPEG, PNG, GIF, BMP required.
已尝试的清理操作
先后使用两个脚本清理损坏图片,但问题依旧:
脚本1:基于imghdr的格式校验
通过imghdr检测图片实际格式,将无效或TensorFlow不支持的图片移动到指定文件夹,每个子文件夹至少移除500张图片:
from pathlib import Path import imghdr import shutil import os destination_folder_path = '../bekar/flood_bekar' data_dir = "./flood" image_extensions = [".png", ".jpg", 'bmp', 'jpeg'] # 支持的扩展名 img_type_accepted_by_tf = ["bmp", "gif", "jpeg", "png"] for filepath in Path(data_dir).rglob("*"): if filepath.suffix.lower() in image_extensions: img_type = imghdr.what(filepath) destination_file_path = os.path.join(destination_folder_path, os.path.basename(filepath)) if img_type is None: print(f"{filepath} is not an image") shutil.move(filepath, destination_file_path) elif img_type not in img_type_accepted_by_tf: print(f"{filepath} is a {img_type}, not accepted by TensorFlow") shutil.move(filepath, destination_file_path)
脚本2:结合cv2与imghdr的校验
用cv2尝试读取图片并获取形状,同时校验格式,最终未检测到异常文件:
import os import cv2 import imghdr def check_images( s_dir, ext_list): bad_images=[] bad_ext=[] s_list= os.listdir(s_dir) for klass in s_list: klass_path=os.path.join (s_dir, klass) print ('processing class directory ', klass) if os.path.isdir(klass_path): file_list = os.listdir(klass_path) for f in file_list: f_path = os.path.join (klass_path,f) tip = imghdr.what(f_path) if ext_list.count(tip) == 0: bad_images.append(f_path) if os.path.isfile(f_path): try: img = cv2.imread(f_path) shape = img.shape except Exception: print('file ', f_path, ' is not a valid image file') bad_images.append(f_path) else: print('*** fatal error, you a sub directory ', f, ' in class directory ', klass) else: print ('*** WARNING*** you have files in ', s_dir, ' it should only contain sub directories') return bad_images, bad_ext source_dir = './' good_exts=['jpg', 'png', 'jpeg', 'gif', 'bmp' ] bad_file_list, bad_ext_list=check_images(source_dir, good_exts) if len(bad_file_list) != 0: print('improper image files are listed below') for i in range (len(bad_file_list)): print (bad_file_list[i]) else: print('no improper image files were found')
解决办法
1. 精准定位出错文件
直接用TensorFlow的文件读取与解码逻辑验证每个验证集文件,捕获异常并打印路径:
import tensorflow as tf # 获取验证集所有文件路径 val_file_paths = val_ds.file_paths for path in val_file_paths: try: # 读取文件 img_raw = tf.io.read_file(path) # 解码图片(不指定格式,让TensorFlow自动检测) tf.image.decode_image(img_raw, channels=3, expand_animations=False) except Exception as e: print(f"错误文件路径:{path}") print(f"错误信息:{str(e)}")
找到出错文件后,手动移除或替换即可。
2. 补充数据集校验逻辑
- 检查文件大小:移除空文件或极小文件(比如文件大小<1KB),这类文件大概率损坏:
import os for path in val_file_paths: if os.path.getsize(path) < 1024: # 小于1KB print(f"移除小文件:{path}") os.remove(path) - 匹配扩展名与实际格式:对于扩展名和
imghdr检测结果不一致的文件,修正扩展名或直接移除。
3. 优化数据集构建参数
在调用image_dataset_from_directory时,添加以下参数避免潜在问题:
val_ds = tf.keras.utils.image_dataset_from_directory( data_dir, validation_split=0.2, subset="validation", seed=123, # 固定种子确保划分稳定 image_size=(224, 224), # 明确指定图片尺寸 batch_size=32, shuffle=False # 关闭打乱,方便按顺序定位出错文件 )
内容的提问来源于stack exchange,提问作者Beckerman
相关产品推荐
相关产品推荐

