Как разделить и скопировать файлы из нескольких папок в папке train, test и validation - PullRequest
0 голосов
/ 26 января 2019

У меня есть набор данных, который состоит из 130 папок, содержащих 32 фотографии в каждой.

Из каждой папки я хочу произвольно скопировать эти фотографии (26 для обучения, 3 для тестирования и 3 для проверки) в соответствующую подпапку (001, 002, 003 ...) в папке обучения, проверки и проверки. Так что у меня будет что-то вроде этого:

  • Поезд

    • 001 (в папке 26 фото)
    • 002
    • 003
    • ....
  • Набор для проверки

    • 001 (в папке 3 фотографии)
    • 002
    • 003
    • ....
  • Поезд

    • 001 (в папке 3 фотографии)
    • 002
    • 003
    • ....

Это код:

import random
import shutil

n_photo_train = 26
n_photo_validation = 3
n_photo_test = 3

for idx in range(130):

    source = '/Users/john/photodb_original/{d:03d}'.format(d=(idx + 1))
    dest_train = '/Users/john/photodb_sets/Train/{d:03d}'.format(d=(idx + 1))
    dest_validation = '/Users/john/photodb_sets/Validation/{d:03d}'.format(d=(idx + 1))
    dest_test = '/Users/john/photodb_sets/Test/{d:03d}'.format(d=(idx + 1))

    files = random.choice(os.listdir(source))
    photo_train = files[:n_photo_train]
    photo_test = files[26:29]
    photo_val = files[29:]

    shutil.copyfile(os.path.join(source, photo_train), dest_train)
    shutil.copyfile(os.path.join(source, photo_val), dest_validation)
    shutil.copyfile(os.path.join(source, photo_test), dest_test)

Я получаю эту ошибку: IsADirectoryError: [Errno 21] Is a directory: '/Users/john/photodb_original/001/'.

Я неправильно использовал shutil.copyfile? Иначе есть ли способ написать код более компактным и понятным способом?

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Я думаю, вам нужно создать каталоги для копирования файлов внутри них или, если у вас возникла исключительная ситуация, связанная с отсутствием каталога, попробуйте сначала создать его, а затем снова попытаться скопировать файл. В любом случае, вот пример кода, который, я думаю, делает то, что вы ищете.

import os
from random import shuffle
from shutil import copyfile, rmtree

org = os.path.realpath('org')
trn = os.path.realpath('trn')
tst = os.path.realpath('tst')
val = os.path.realpath('val')
# How split will be performed 26 3 3
rnd = [trn]*26+[tst]*3+[val]*3

rmtree(trn)
rmtree(tst)
rmtree(val)
rmtree(org)

# CREATE DUMMY DATA
for i in range(1, 131):
    d = os.path.join(org, "{:03d}".format(i))
    os.makedirs(d, exist_ok=True)
    for f in range(1, 33):
        f = os.path.join(d, "{:02d}".format(f))
        open(f, 'a').close()

# ACTUAL STUFF
for d in os.listdir(org):
    os.makedirs(os.path.join(trn, d))
    os.makedirs(os.path.join(tst, d))
    os.makedirs(os.path.join(val, d))
    files = os.listdir(os.path.join(org,d))
    shuffle(rnd)
    for f, trg in zip(os.listdir(os.path.join(org,d)),rnd):
        scr = os.path.join(org,d,f)
        dst = os.path.join(trg,d,f)
        copyfile(scr,dst)
0 голосов
/ 26 января 2019

random.choice(os.listdir(source)) вернет только отдельный элемент - при попытке индексировать эту строку вы получите пустую строку, а os.path.join вернет путь к каталогу - что вызывает ваше исключение.

Из вашего кода похоже, что вы намеревались использовать random.shuffle. Обратите внимание, что если вы используете shuffle, он изменяет список, поэтому ваш код должен быть разбит на две команды:

files = os.listdir(source)
random.shuffle(files)
...