web-dev-qa-db-ja.com

Keras flowFromDirectoryはファイル名が生成されるときに取得します

_flow_from_directory_を使用してロードされたファイル名を取得することは可能ですか?私が持っています :

_datagen = ImageDataGenerator(
    rotation_range=3,
#     featurewise_std_normalization=True,
    fill_mode='nearest',
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True
)

train_generator = datagen.flow_from_directory(
        path+'/train',
        target_size=(224, 224),
        batch_size=batch_size,)
_

次のようなマルチ出力モデル用のカスタムジェネレーターがあります。

_a = np.arange(8).reshape(2, 4)
# print(a)

print(train_generator.filenames)

def generate():
    while 1:
        x,y = train_generator.next()
        yield [x] ,[a,y]
_

現時点ではaの乱数を生成していますが、実際のトレーニングのために、画像のバウンディングボックス座標を含むjsonファイルをロードしたいというノード。そのために、train_generator.next()メソッドを使用して生成されたファイル名を取得する必要があります。それができたら、ファイルをロードし、jsonを解析して、aの代わりに渡すことができます。 x変数の順序と、取得するファイル名のリストが同じであることも必要です。

18
harveyslash

はい、少なくともバージョン2.0.4では可能です(以前のバージョンについては知りません)。

ImageDataGenerator().flow_from_directory(...)のインスタンスには、filenamesを持つ属性があります。これは、ジェネレーターが生成する順序でのすべてのファイルのリストであり、属性batch_index。したがって、次のようにできます。

datagen = ImageDataGenerator()
gen = datagen.flow_from_directory(...)

そして、ジェネレータでのすべての繰り返しで、次のような対応するファイル名を取得できます。

for i in gen:
    idx = (gen.batch_index - 1) * gen.batch_size
    print(gen.filenames[idx : idx + gen.batch_size])

これにより、現在のバッチ内の画像のファイル名がわかります。

22
Pepe

DirectoryIterator を継承することで、_image, file_path_タプルを返す非常に最小限のサブクラスを作成できます。

_import numpy as np
from keras.preprocessing.image import ImageDataGenerator, DirectoryIterator

class ImageWithNames(DirectoryIterator):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.filenames_np = np.array(self.filepaths)
        self.class_mode = None # so that we only get the images back

    def _get_batches_of_transformed_samples(self, index_array):
        return (super()._get_batches_of_transformed_samples(index_array),
                self.filenames_np[index_array])
_

初期化では、_self.filepaths_のnumpyバージョンである属性を追加したため、その配列に簡単にインデックスを付けて、各バッチ生成のパスを取得できます。

基本クラスに対する他の唯一の変更は、イメージバッチsuper()._get_batches_of_transformed_samples(index_array)およびファイルパス_self.filenames_np[index_array]_であるタプルを返すことです。

これで、次のようにジェネレーターを作成できます。

_imagegen = ImageDataGenerator()
datagen = ImageWithNames('/data/path', imagegen, target_size=(224,224))
_

そして、確認してください

_next(datagen)
_
3
Bob Baxley

shuffle=Trueでも同様に機能する例を次に示します。また、最後のバッチも適切に処理します。 1つのパスを作成するには:

datagen = ImageDataGenerator().flow_from_directory(...)    
batches_per_Epoch = datagen.samples // datagen.batch_size + (datagen.samples % datagen.batch_size > 0)
for i in range(batches_per_Epoch):
    batch = next(datagen)
    current_index = ((datagen.batch_index-1) * datagen.batch_size)
    if current_index < 0:
        if datagen.samples % datagen.batch_size > 0:
            current_index = max(0,datagen.samples - datagen.samples % datagen.batch_size)
        else:
            current_index = max(0,datagen.samples - datagen.batch_size)
    index_array = datagen.index_array[current_index:current_index + datagen.batch_size].tolist()
    img_paths = [datagen.filepaths[idx] for idx in index_array]
    #batch[0] - x, batch[1] - y, img_paths - absolute path
2
apatsekin

少なくともバージョン2.2.4では、次のようにできます。

datagen = ImageDataGenerator()
gen = datagen.flow_from_directory(...)
for file in gen.filenames:
    print(file)

またはファイルパスを取得する

for filepath in gen.filepaths:
    print(filepath)
0
Xinstein