Разделить набор данных изображения на наборы данных для тестирования поездов

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

-main_db

--- КЛАСС_1

----- img_1

----- img_2

----- img_3

----- img_4

--- КЛАСС_2

----- img_1

----- img_2

----- img_3

----- img_4

--- КЛАСС_3

----- img_1

----- img_2

----- img_3

----- img_4

Мне нужно разделить этот набор данных на 2 части: данные поезда (70%) и данные тестирования (30%). Ниже приведена иерархия, которую я хочу достичь.

-main_db

--- training_data

----- КЛАСС_1

------- img_1

------- img_2

------- img_3

------- img_4

--- КЛАСС_2

------- img_1

------- img_2

------- img_3

------- img_4

--- testing_data

----- КЛАСС_1

------- img_5

------- img_6

------- img_7

------- img_8

--- КЛАСС_2

------- img_5

------- img_6

------- img_7

------- img_8

Любая помощь приветствуется. Спасибо

Я пробовал этот модуль. Но у меня это не работает. Этот модуль вообще не импортируется.

https://github.com/jfilter/split-folders

Это именно то, что я хочу.


person Ishan Dixit    schedule 07.08.2019    source источник
comment
Кажется, вы сами нашли решение, но инструмент не работает. Поскольку это очень конкретный вопрос и вряд ли поможет широкой аудитории, попробуйте задать вопрос с split-folders, если у вас возникнут проблемы. Они с гораздо большей вероятностью помогут вам, чем люди здесь!   -  person nemo    schedule 07.08.2019
comment
Откуда _1 _ / _ 2 _ / _ 3 _ / _ 4_?   -  person Ari Cooper-Davis    schedule 07.08.2019
comment
@ АриКупер-Дэвис того же класса, что я считаю!   -  person Mari    schedule 07.08.2019
comment
@nemo Вы абсолютно правы и я уже открывал выпуск по их репо. !   -  person Ishan Dixit    schedule 07.08.2019
comment
Если гипотетически предположить, что у меня есть 20 изображений во всех подпапках, тогда папка обучающего набора должна содержать 16 изображений, а набор для тестирования содержит 4 изображения. Этот сплит учитывает соотношение долей 80% -20%. @ АриКупер-Дэвис   -  person Ishan Dixit    schedule 07.08.2019
comment
Модуль split-folders решает эту проблему (я автор). Не уверен, почему это не сработало для вас.   -  person Johannes Filter    schedule 05.08.2020


Ответы (6)


Это должно сработать. Он рассчитает, сколько изображений находится в каждой папке, а затем разделит их соответствующим образом, сохраняя тестовые данные в другой папке с той же структурой. Сохраните код в main.py файле и выполните команду:

python3 main.py ----data_path=/path1 --test_data_path_to_save=/path2 --train_ratio=0.7

import shutil
import os
import numpy as np
import argparse

def get_files_from_folder(path):

    files = os.listdir(path)
    return np.asarray(files)

def main(path_to_data, path_to_test_data, train_ratio):
    # get dirs
    _, dirs, _ = next(os.walk(path_to_data))

    # calculates how many train data per class
    data_counter_per_class = np.zeros((len(dirs)))
    for i in range(len(dirs)):
        path = os.path.join(path_to_data, dirs[i])
        files = get_files_from_folder(path)
        data_counter_per_class[i] = len(files)
    test_counter = np.round(data_counter_per_class * (1 - train_ratio))

    # transfers files
    for i in range(len(dirs)):
        path_to_original = os.path.join(path_to_data, dirs[i])
        path_to_save = os.path.join(path_to_test_data, dirs[i])

        #creates dir
        if not os.path.exists(path_to_save):
            os.makedirs(path_to_save)
        files = get_files_from_folder(path_to_original)
        # moves data
        for j in range(int(test_counter[i])):
            dst = os.path.join(path_to_save, files[j])
            src = os.path.join(path_to_original, files[j])
            shutil.move(src, dst)


def parse_args():
  parser = argparse.ArgumentParser(description="Dataset divider")
  parser.add_argument("--data_path", required=True,
    help="Path to data")
  parser.add_argument("--test_data_path_to_save", required=True,
    help="Path to test data where to save")
  parser.add_argument("--train_ratio", required=True,
    help="Train ratio - 0.7 means splitting data in 70 % train and 30 % test")
  return parser.parse_args()

if __name__ == "__main__":
  args = parse_args()
  main(args.data_path, args.test_data_path_to_save, float(args.train_ratio))
person nomow    schedule 07.08.2019
comment
Попробую эту штуку и дам знать! Спасибо за ответ ! - person Ishan Dixit; 07.08.2019

** Перейдите по этой ссылке https://www.kaggle.com/questions-and-answers/102677 Благодарность за комментарий saravanansaminathan на Kaggle. За ту же проблему с моими наборами данных со следующей структурой папок. / TTSplit / 0 /001_01.jpg ....... / 1 ​​/001_04.jpg ....... Я последовал, взяв приведенную выше ссылку в качестве ссылки. **

import os
import numpy as np
import shutil
import random
root_dir = '/home/dipak/Desktop/TTSplit/'
classes_dir = ['0', '1']

test_ratio = 0.20

for cls in classes_dir:
    os.makedirs(root_dir +'train/' + cls)
    os.makedirs(root_dir +'test/' + cls)

src = root_dir + cls

allFileNames = os.listdir(src)
np.random.shuffle(allFileNames)
train_FileNames, test_FileNames = np.split(np.array(allFileNames),
                                                          [int(len(allFileNames)* (1 - test_ratio))])


train_FileNames = [src+'/'+ name for name in train_FileNames.tolist()]
test_FileNames = [src+'/' + name for name in test_FileNames.tolist()]

print("*****************************")
print('Total images: ', len(allFileNames))
print('Training: ', len(train_FileNames))
print('Testing: ', len(test_FileNames))
print("*****************************")


lab = ['0', '1']

for name in train_FileNames:
    for i in lab:
        shutil.copy(name, root_dir +'train/' + i)

for name in test_FileNames:
    for i in lab:
        shutil.copy(name, root_dir +'test/' + i)
print("Copying Done!")
person Dipendra Pant    schedule 13.11.2020

Если вы не слишком увлечены кодированием, вы можете использовать пакет python, называемый разделенными папками. Он чрезвычайно прост в использовании, и его можно найти здесь. Вот как его можно использовать.

pip install split_folders
import split-folders
input_folder = "input_path"
output = "output_path" #where you want the split datasets saved. one will be created if none is set

split_folders.ratio('input_folder', output="output", seed=42, ratio=(.8, .1, .1)) # ratio of split are in order of train/val/test. You can change to whatever you want. For train/val sets only, you could do .75, .25 for example.

Однако я настоятельно рекомендую кодировать ответы, представленные выше, потому что они помогают вам учиться.

person Misan    schedule 27.07.2020
comment
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из отзыва - person Jason Aller; 27.07.2020
comment
Это пакет, а не веб-сайт. Он будет доступен через pypi еще долгое время. - person Johannes Filter; 05.08.2020

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

import splitfolders  # or import split_folders
splitfolders.ratio("input_folder", output="output", seed=1337, ratio=(.8, .1, .1), 
group_prefix=None) # default values

# Split with a ratio.
#To only split into training and validation set, set a tuple to `ratio`, i.e,`(.8,    
# .2)`.
splitfolders.ratio("input_folder", output="output", seed=1337, ratio=(.8, .1, .1), 
group_prefix=None) # default values

# Split val/test with a fixed number of items e.g. 100 for each set.
# To only split into training and validation set, use a single number to `fixed`, 
i.e., 
# `10`.
splitfolders.fixed("input_folder", output="output", seed=1337, fixed=(100, 100), 
oversample=False, group_prefix=None) # default values
person burhan rashid    schedule 31.10.2020

data = os.listdir(image_directory)

from sklearn.model_selection import train_test_split
train, valid = train_test_split(data, test_size=0.2, random_state=1)

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

person Ikram.Inf    schedule 05.03.2021

Как насчет этого?

from pathlib import Path
from sklearn.model_selection import  StratifiedShuffleSplit
import shutil

def image_train_test_split(path, fmt, train_size):
  train_folder = Path('train')
  test_folder = Path('test')

  train_folder.mkdir(exist_ok=True)
  test_folder.mkdir(exist_ok=True)

  data_path = Path(path)
  data = []
  for d in data_path.glob('*'):
    for f in d.glob(f'*.{fmt}'):
      data.append([f, d.stem])
  data = np.array(data)

  ss = StratifiedShuffleSplit(1, train_size=0.8)
  train_ix, test_ix = next(ss.split(data[:,0], data[:,1]))

  train_set, test_set = data[train_ix], data[test_ix]

  for p, c in train_set:
    
    (train_folder / c).mkdir(exist_ok=True)
    shutil.move(p, train_folder.joinpath(*p.parts[-2:]))

  for p, c in test_set:
    
    (test_folder / c).mkdir(exist_ok=True)
    shutil.move(p, test_folder.joinpath(*p.parts[-2:]))
person 3nomis    schedule 28.06.2021