从 ImageDataGenerator() 中一张一张地提取图像及其标签。flow_from_directory

extracting images and their label one by one from ImageDataGenerator().flow_from_directory

所以我导入了我的数据集 (38 类) 以使用 ImageDataGenerator() 进行验证。flow_from_directory

valid = ImageDataGenerator().flow_from_directory(directory="dataset/valid", target_size=(224,224))

我想一张一张地挑选每张图片及其标签。例如我想选择第一张图片和它的标签

我试过了

for img, lbl in valid:
    print(lbl)
    break

我得到了图像,但对于标签,我只得到一个形状为 (32,38) 的数组,其中包含 0 和 1s

[[0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 ...
 [0. 0. 0. ... 1. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]
 [0. 0. 0. ... 0. 0. 0.]]

有没有办法得到这张图片的标签?

documentation 可能会帮助您解决这个问题。更具体地说,来自 tf.keras.ImageDataGenerator.flow_from_directory:

的默认参数
flow_from_directory(
    directory, target_size=(256, 256), color_mode='rgb', classes=None,
    class_mode='categorical', batch_size=32, shuffle=True, seed=None,
    save_to_dir=None, save_prefix='', save_format='png',
    follow_links=False, subset=None, interpolation='nearest'
)

class 模式是分类的,因此您的标签将作为单热编码矩阵出现。默认批处理大小为 32,因此当您迭代时,每次都会获取 32 个 one-hot 编码行。这就是你得到的。

要访问标签,您可以索引数据集所有标签的列表:

valid.labels[0]

生成器的输出格式为 (batch_size, images, labels)。由于您没有指定 batch_size,它默认为 32。您也没有指定 class_mode,因此默认为分类。这意味着您的标签将被一次性编码。每个标签都是一个长度为 38 的向量。因此您的标签将采用 (batch_size, 38) 的形式。 现在您可能想要显示 class 的实际名称 与其绝对值相比。您可以使用 class_dict=valid.class_indices 实现此目的。 此 returns 形式为 {class_name: integer_value} 的字典,其中整数值是与 class 名称关联的整数值。其他一些有用的属性 生成器的是 labels= valid.labels 这是所有标签的列表和 file_names= valid.filenames 这是所有 file_names 的列表。现在如果你想 使用下面的代码打印出所有标签信息

source_dir=r'dataset/valid' # set this to the path of the directory with the images
batch_size=32  # specify the desired batch size
valid=ImageDataGenerator().flow_from_directory(source_dir, class_mode='categorical',batch_size=batch_size, target_size=(224,224) )
val_labels=valid.labels
file_names=valid.filenames
gen_length=len(val_labels)
print ('There are a total of ', gen_length, 'files in the specified directory')
class_dict=valid.class_indices
new_dict={}
for key,value in class_dict.items(): # reverse the dictionary show it is in the form {integer label, class_name}
    new_dict[value]=key  
for i in range (gen_length):
    file_count=  (i+1)* batch_size
    if file_count>=gen_length:    
        j_end=gen_length- i* batch_size # cut off printing because we have used all the labels
    else:
        j_end=batch_size
    files, labels = next(valid) # fetches next batch of 32 files and labels
    print (' For batch ',i, ' labels are:')
    print ('{0:^20s} {1:^14s}'.format('CLASS', 'CLASS NUMBER'))
    for j in range (j_end):
        label=np.argmax(labels[j])
        class_name= new_dict[label]
        print('{0:^20s} {1:^14s}'.format(class_name, str(label)))
    if file_count>=gen_length:
        break