【问题标题】:Reading images without rigid folder structure读取没有固定文件夹结构的图像
【发布时间】:2020-07-29 13:08:39
【问题描述】:

我正在使用 Tensorflow 2(尤其是 Tensorflow 2.2)

下面的函数允许我们从文件夹中读取图像

train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
        'data/train',
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')

但它要求我们根据catdog 分类为 data/train/catdata/train/dog

现在说,我们在文件夹 data/train/(比如 data/train/1.jpg 等)中有所有训练图像,我在下面有 train_set X 和标签 y

X=['1.jpg','2.jpg',...]
y=[0,1,...]

其中0 表示dog1 表示cat 表示y,我想达到与上面的代码相同的效果(例如,图像八月像水平翻转等+ 与batchsize指定),我该怎么做?

我尝试过的一种方法

我使用下面的代码

 def preprocess(image):

    img_shape=np.array(image).shape        
    image = tf.cast(np.array(image), tf.float32)
    image = (image / 127.5) - 1
    return image

 image_path=pathlib.Path.joinpath("train", "data")
 class_names=[x.name.lower() for x in image_path.glob('*') if x.is_dir()]
    X=[]
    y=[]


    for path in image_path.glob('**/*'):
        if path.is_file():
            if path.name.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif')):
                X.append(preprocess(Image.open(path).resize((224,224),resample=Image.BICUBIC)))
                y.append(class_names.index(path.parent.name.lower()))

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1 - train_ratio, stratify=y)
    X_val, X_test, y_val, y_test = train_test_split(X_test, y_test,
                                                    test_size=test_ratio / (test_ratio + validation_ratio),
                                                    stratify=y_test)


    train_data = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(batch_size)
    validation_data = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(batch_size)
    test_data = tf.data.Dataset.from_tensor_slices((X_test, y_test)).batch(batch_size)  

我出现内存不足错误(因为我将所有图像都存储在 X 中),我应该如何解决这个问题?

【问题讨论】:

    标签: python python-3.x tensorflow tensorflow2.0


    【解决方案1】:

    为此,我强烈建议您使用tf.data.Dataset(),以便读取和提取您的数据。

    事实上,它甚至是官方推荐的 TensorFlow 中的 ETL 过程(提取、转换、加载)的准备方式。

    你可以看这里:https://www.tensorflow.org/api_docs/python/tf/data/Dataset

    例如,在您的特定情况下(当您阅读文档时,它会更有意义),您可以使用 .map() 函数,在该函数中根据描述中的字符串检索/生成标签 0 或 1你的形象。

    或者你也可以按照上面描述的方式实现它,使用tf.data.Dataset.from_tensor_slices()

    此外,您可以使用另一个映射函数进行扩充;你可以在这里研究可用的图像预处理技术:https://www.tensorflow.org/api_docs/python/tf/image

    根据我自己的工作(前段时间改编的教程),我在这里附上一个例子:

    def load_filenames(csv_data, datapath):
        filenames = [os.path.join(datapath, filename) for filename in csv_data['id'].tolist()]
        return filenames
    
    
    def load_labels(csv_data):
        return csv_data['has_cactus'].tolist()
    
    
    def parse_fn(filename, label):
        filename = filename.numpy().decode('utf-8')
        print(filename)
        return filename, label
    
    
    def process_function(filename, label):
        img = tf.io.read_file(filename)
        img = tf.image.decode_jpeg(img)
        img = (tf.cast(img, tf.float32) / 127.5) - 1
        img = tf.image.resize(img, (96, 96))
        return img, label
        train_csv = pd.read_csv(filepath_or_buffer='data/aerial-cactus-identification/train.csv')
        filenames = load_filenames(csv_data=train_csv, datapath='data/aerial-cactus-identification/train')
        labels = load_labels(csv_data=train_csv)
    
        train_filenames, val_filenames, train_labels, val_labels = train_test_split(filenames,
                                                                                    labels,
                                                                                    train_size=0.9,
                                                                                    random_state=42)
        num_train = len(train_filenames)
        num_val = len(val_filenames)
        train_data = tf.data.Dataset.from_tensor_slices(
            (tf.constant(train_filenames), tf.constant(train_labels))
        )
    
        val_data = tf.data.Dataset.from_tensor_slices(
            (tf.constant(val_filenames), tf.constant(val_labels))
        )
    
    
        train_data = (train_data.map(process_function)
                      .shuffle(buffer_size=num_train)
                      .batch(BATCH_SIZE)
                      .prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
                      )
    
        val_data = (val_data.map(process_function)
                    .shuffle(buffer_size=num_val)
                    .batch(BATCH_SIZE)
                    .prefetch(buffer_size=tf.data.experimental.AUTOTUNE)
                    )
    

    【讨论】:

    • 嗨,我已经编辑了问题以附加我尝试过的方法,这接近你的建议,但我遇到了我在问题中强调的问题,我应该如何处理?
    • 如果出现OOM错误,则应减小batch_size;本质上就是这样,没有足够的视频内存。
    • 你必须使用映射函数,from_tensor_slices().map().batch()
    • OOM 发生在我附加的preprocess 函数中。原因是X 中的张量存储过多。我应该如何避免这种情况?
    • 错误来自这里:for path in image_path.glob('*/'): if path.is_file(): if path.name.lower()。结束(('.png','.jpg','.jpeg','.tiff','.bmp','.gif')):X.append(预处理(Image.open(路径).resize( (224,224),resample=Image.BICUBIC))) y.append(class_names.index(path.parent.name.lower()))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多