Python 读取没有刚性文件夹结构的图像

Python 读取没有刚性文件夹结构的图像,python,python-3.x,tensorflow,tensorflow2.0,Python,Python 3.x,Tensorflow,Tensorflow2.0,我使用的是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

我使用的是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')
但是它要求我们严格按照分类的类别来组织文件夹,比如
cat
dog
data/train/cat
data/train/dog

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

X=['1.jpg','2.jpg',...]
y=[0,1,...]
其中
0
表示
dog
1
表示
cat
表示
y
,我希望实现与上面代码相同的效果(例如,图像8月,如水平翻转等+指定批次大小),我应该怎么做

我尝试过的方法

我使用以下代码

 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
),如何解决此问题?

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

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

您可以在这里查看:

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

或者您也可以按照上面描述的方式,使用
tf.data.Dataset.from\u tensor\u slices()

此外,还可以使用另一个映射函数进行扩充;您可以在此研究可用的图像预处理技术:

根据我自己的作品(改编自不久前的教程),我在此附上一个示例:

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错误,那么您应该减小批量大小;本质上这就是发生的事情,没有足够的视频内存。你必须使用映射函数,从_tensor_slices().map().batch()开始。OOM发生在我附带的
预处理
函数中。原因是
X
中存储了太多的张量。我应该如何避免呢?错误来自于这里:对于image_path.glob('*/'):if path.is_file():if path.name.lower().endswith(“.png',“.jpg',”.jpeg',“.tiff',“.bmp',“.gif')):X.append(预处理(image.open(path)。resize((224224),resample=image.BICUBIC)))y.append(class_names.index(path.parent.name.lower())