Python 读取没有刚性文件夹结构的图像
我使用的是Tensorflow 2(特别是Tensorflow 2.2) 下面的功能允许我们从文件夹中读取图像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
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\uX
和标签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())