Копирование файлов с помощью shutil.copy()

Такая задача: есть датасет, состоящий из папок, в каждой из которых есть некоторое число картинок. Нужно найти максимальное число картинок, а затем во всех остальных папках копировать уже лежащие в папке изображения, до тех пор, пока их не станет не меньше, чем максимум. Т.е. я просто балансирую классы, копируя уже существующие изображения.

Проблема в том, что функция shutil.copy() копирует файл с таким же именем, из-за чего ей нельзя воспользоваться при копировании файла в ту же директорию.

Как тогда решить эту задачу?

Вот мой код:

import shutil
import os
from random import randint


dir_path = 'C:/Users/**/cnn/data/train/dataset/'
max_files = 0
directory = os.listdir(path=os.path.join(dir_path))

for folder in directory:
    files_num = len(os.listdir(path=os.path.join(dir_path+folder)))

    if files_num > max_files:
        max_files = files_num

print('--------\n\nmax is', max_files)

for folder in directory: 
    files_num = len(os.listdir(path=os.path.join(dir_path + folder)))
    files = os.listdir(path=os.path.join(dir_path+folder))

    for file in files:
        if files_num >= max_files:
            break
        else:
            shutil.copy(os.path.join(dir_path + folder + '/' + file),
                        os.path.join(dir_path + folder))

            files_num = len(os.listdir(path=os.path.join(dir_path + folder))) 

Ответы (2 шт):

Автор решения: MaxU

Баланисировать выборку, клонируя изображения, очень сомнительная затея.

Сеть не будет дополнительно обучаться на тех же самых картинках. Это просто замедлит обучение и врядли увеличит точность предсказаний.

Вместо этого воспользуйтесь apply_tfms, как это показано в данной статье для того, чтобы создать дополнительные изображения.

→ Ссылка
Автор решения: DKay

Как указал @MaxU балансировать классы копированием -- плохая идея, но если кому-то понадобится, то решение @splash58 с небольшой доработкой сработало. Привожу код:

import shutil
import os
from random import randint
from tqdm import tqdm

dir_path = 'C:/Users/***/cnn/data/train/dataset/'
max_files = 0
directory = os.listdir(path=os.path.join(dir_path))


for folder in directory:

    files_num = len(os.listdir(path=os.path.join(dir_path+folder)))
    print('{0} contains {1} files'.format(folder, files_num))

    if files_num > max_files:
        max_files = files_num

print('--------\n\nmax is', max_files)


for folder in tqdm(directory):

    files_num = len(os.listdir(path=os.path.join(dir_path + folder)))
    files = os.listdir(path=os.path.join(dir_path+folder))

    while files_num < max_files:

        for file in files:
            if files_num >= max_files:
                break
            else:
                shutil.copy(os.path.join(dir_path + folder + '/' + file),
                        os.path.join(dir_path + folder+ '/' + file[:-4] + str(randint(0,10)))+'.jpg')

                files_num = len(os.listdir(path=os.path.join(dir_path + folder)))   

→ Ссылка