LoginSignup
3
3

More than 3 years have passed since last update.

学習に利用する画像のデータセットを作成する

Last updated at Posted at 2019-12-15

はじめに

  • 今回の、学習画像、テスト画像、水増し画像の合計サイズは、1.4GB 程度です。
  • これらの画像を、学習プログラム実施時に、読み込むとそれなりの時間が必要になります。
  • また、別の環境で学習プログラムを実施する時も、転送時間が発生します。
  • その他、画像サイズをリサイズしたり、カラーからグレーに変換する処理にも時間が必要になります。
  • あらかじめ、リサイズ、グレー変換したデータセットを作成する事で、50MB 程度にすることが出来ました。
  • ソース一式は ここ です。

ライブラリ

  • 前回と同様、Numpy Pillow を使っています。

設定

  • 以下の設定を追加しています。
  • DATASETS_PATH に、今回作成するデータセットが保存されます。
  • IMG_ROWS IMG_COLS は、画像サイズのリサイズです。今回は、28 x 28 のサイズへリサイズします。
  • 画像サイズは、後工程の学習モデルでも参照されます。
config.py
DATASETS_PATH = os.path.join(DATA_PATH, 'datasets')

IMG_ROWS, IMG_COLS = 28, 28

ファイル一覧の作成

  • 学習画像、テスト画像、水増し画像のファイル一覧を作成します。
  • query には、CLASSES が順次与えられます。
  • augment 引数は、水増し画像の利用可否のフラグです。
  • 前回、水増し画像は、query 毎に 6000 作成しました。足りない場合は、エラーにしています。
def make_filesets(augment):
    """ファイルセットの作成."""

    filesets = {'train': dict(), 'test': dict(), 'augment': dict()}

    for query in CLASSES:

        train_path = os.path.join(TRAIN_PATH, query)
        test_path = os.path.join(TEST_PATH, query)
        augment_path = os.path.join(AUGMENT_PATH, query)

        if not os.path.isdir(train_path):
            print('no train path: {}'.format(train_path))
            return None
        if not os.path.isdir(test_path):
            print('no test path: {}'.format(test_path))
            return None
        if not os.path.isdir(augment_path):
            print('no augment path: {}'.format(augment_path))
            return None

        train_files = glob.glob(os.path.join(train_path, '*.jpeg'))
        train_files.sort()
        filesets['train'][query] = train_files

        test_files = glob.glob(os.path.join(test_path, '*.jpeg'))
        test_files.sort()
        filesets['test'][query] = test_files

        augment_files = glob.glob(os.path.join(augment_path, '*.jpeg'))
        random.shuffle(augment_files)
        filesets['augment'][query] = augment_files

        if augment and len(augment_files) < AUGMENT_NUM:
            print('less augment num: {}, path: {}'.format(len(augment_files), augment_path))
            return None

    return filesets

画像の読み込みの関数

  • ファイルのフルパスを元に画像を処理します。
  • 設定ファイルに従い、リサイズされます。
  • もともと、OpenCV Haar Cascades では、リサイズを行わずに保存していました。後工程でリサイズする方が、様々なサイズで試すのに便利ですね。
  • LANCZOS は、時間はかかるが、品質良くリサイズしてくれます。デフォルトは、NEAREST ですね。品質より、速さ優先です。
  • その後、グレースケールに変換し、さらにuint8 に変換します。
def read_image(filename):
    """画像の読み込み、リサイズ、グレー変換."""

    image = Image.open(filename)
    image = image.resize((IMG_ROWS, IMG_COLS), Image.LANCZOS)
    image = image.convert('L')
    image = np.array(image, dtype=np.uint8)

    return image

データセットの作成

  • 学習画像、学習ラベル、テスト画像、テストラベルの配列を準備します。
def make_datasets(augment, filesets):
    """データセットの作成."""

    train_images = []
    train_labels = []
    test_images = []
    test_labels = []
  • query には、CLASSES が順次与えられます。
  • num には、ラベル が順次与えられます。
  • 例えば、CLASSES の 最初は、安倍乙 ラベルは 0 と言う感じです。
  • augment で水増し画像を利用するか判断します。利用する場合は、AUGMENT_NUM に記載の数のみtrain_files に設定します。
  • 各画像の読み込みには、tqdm も合わせて利用しています。処理経過が表示され、分かりやすいですね。
  • read_image に画像のファイルパスを与えて、リサイズ、グレースケール化した画像を読み込みます。
  • 同時にラベルも付与します。
    for num, query in enumerate(CLASSES):
        print('create dataset: {}'.format(query))

        if augment:
            train_files = filesets['augment'][query][:AUGMENT_NUM]
        else:
            train_files = filesets['train'][query]
        test_files = filesets['test'][query]

        for train_file in tqdm.tqdm(train_files, desc='create train', leave=False):
            train_images.append(read_image(train_file))
            train_labels.append(num)
        for test_file in tqdm.tqdm(test_files, desc='create test', leave=False):
            test_images.append(read_image(test_file))
            test_labels.append(num)
  • 学習画像、学習ラベル、テスト画像、テストラベルをデータセットとしてまとめます。
  • DATASET_PATH CLASSES IMG_ROWS IMG_COLS 水増し画像の利用有無を元にデータセットのファイル名を決めます。
    datasets = ((np.array(train_images), (np.array(train_labels))), (np.array(test_images), (np.array(test_labels))))

    datasets_path = os.path.join(DATASETS_PATH, ','.join(CLASSES))
    os.makedirs(datasets_path, exist_ok=True)
    train_num = AUGMENT_NUM if augment else 0
    datasets_file = os.path.join(datasets_path, '{}x{}-{}.pickle'.format(IMG_ROWS, IMG_COLS, train_num))
    with open(datasets_file, 'wb') as fout:
        pickle.dump(datasets, fout)
    print('save datasets: {}'.format(datasets_file))

image.png

  • 水増し画像の利用有無は、下記のオプションで切り替えています。
$ python save_datasets.py

$ python save_datasets.py --augment
  • pickle 化したデータセットは、下記の様になりました。
  • オリジナルの場合は、train test の合計 約 148MB から 3.2MB の pickleファイル
  • 水増し画像の場合は、augment test の合計 約 1433MB から 46MB の pickleファイル
$ du -d1 -h .
115M    ./train
 33M    ./test
 51M    ./datasets
1.4G    ./augment


$ ls
3.2M 12 15 23:22 28x28-0.pickle
46M 12 15 22:24 28x28-6000.pickle

おわりに

  • 学習プログラムから利用しやすい様に、画像データをリサイズ、グレースケールしたデータセットを作成しました。
  • 複数のサイズ、水増し画像の数の変化などで、色々データセットを作り、ファイル名で切り替えながら利用が出来ます。
  • 次回は、データセットを学習プログラムから読み込む部分を作成する予定です。
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3