Orienter / dataset /split_coco.py
stereoid's picture
Add files using upload-large-folder tool
3f3265f verified
Raw
History Blame Contribute Delete
6.76 kB
import os
import json
import shutil
import argparse
import random
import pandas as pd
FOLD_CNT = 10
def generate_fold(args):
df = pd.DataFrame(columns=['img_id', 'fold'])
json_file_path = args.ann_file
assert os.path.exists(json_file_path), f'json file not found: {json_file_path}'
with open(json_file_path, 'r') as f:
json_data = json.load(f)
# reproducable random shuffle
random.seed(1)
random.shuffle(json_data['images'])
fold_size = len(json_data['images']) // FOLD_CNT
for image in json_data['images']:
df.loc[len(df), df.columns] = [image['id'], min(len(df) // fold_size, FOLD_CNT - 1)]
df.to_csv(args.fold_file, index=False)
def generate_fold_app(args):
df = pd.DataFrame(columns=['img_id', 'fold'])
json_file_path = args.ann_file
assert os.path.exists(json_file_path), f'json file not found: {json_file_path}'
with open(json_file_path, 'r') as f:
json_data = json.load(f)
apps = set()
for image in json_data['images']:
appid = str(image['id'])[:-3]
apps.add(appid)
apps = list(apps)
bel_app = {}
# reproducable random shuffle
apps = sorted(apps)
random.seed(1)
random.shuffle(apps)
fold_size = len(apps) // FOLD_CNT
for app in apps:
bel_app[app] = min(len(bel_app) // fold_size, FOLD_CNT - 1)
for image in json_data['images']:
appid = str(image['id'])[:-3]
df.loc[len(df), df.columns] = [image['id'], bel_app[appid]]
df = df.sort_values(by='fold')
df.to_csv(args.fold_file, index=False)
def split(args):
json_file_path = args.ann_file
image_path = args.img_dir if args.img_dir and os.path.exists(args.img_dir) else None
fold_file = args.fold_file
output_path = args.output_path
assert os.path.exists(json_file_path), f'json file not found: {json_file_path}'
# assert os.path.exists(image_path), f'image path not found: {image_path}'
assert os.path.exists(fold_file), f'fold file not found: {fold_file}'
with open(json_file_path, 'r') as f:
json_data = json.load(f)
df = pd.read_csv(fold_file)
train_dataset = {'images': list(), 'categories': json_data['categories'], 'annotations': list()}
val_dataset = {'images': list(), 'categories': json_data['categories'], 'annotations': list()}
test_dataset = {'images': list(), 'categories': json_data['categories'], 'annotations': list()}
train_folds = [int(fold) for fold in args.train_folds.split(',')] if args.train_folds else []
val_folds = [int(fold) for fold in args.val_folds.split(',')] if args.val_folds else []
test_folds = [int(fold) for fold in args.test_folds.split(',')] if args.test_folds else []
print(f'train folds: {train_folds}')
print(f'val folds: {val_folds}')
print(f'test folds: {test_folds}')
train_imgid = set()
val_imgid = set()
test_imgid = set()
for _, row in df.iterrows():
if row['fold'] in train_folds:
train_imgid.add(row['img_id'])
elif row['fold'] in val_folds:
val_imgid.add(row['img_id'])
elif row['fold'] in test_folds:
test_imgid.add(row['img_id'])
else:
raise ValueError(f'fold not found: {row["fold"]}')
for image in json_data['images']:
if image['id'] in train_imgid:
train_dataset['images'].append(image)
elif image['id'] in val_imgid:
val_dataset['images'].append(image)
elif image['id'] in test_imgid:
test_dataset['images'].append(image)
else:
raise ValueError(f'image id not found: {image["id"]}')
for annotation in json_data['annotations']:
if annotation['image_id'] in train_imgid:
train_dataset['annotations'].append(annotation)
elif annotation['image_id'] in val_imgid:
val_dataset['annotations'].append(annotation)
elif annotation['image_id'] in test_imgid:
test_dataset['annotations'].append(annotation)
else:
raise ValueError(f'annotation image_id not found: {annotation["image_id"]}')
print(f'train dataset: {len(train_dataset["images"])} images, {len(train_dataset["annotations"])} annotations')
print(f'val dataset: {len(val_dataset["images"])} images, {len(val_dataset["annotations"])} annotations')
print(f'test dataset: {len(test_dataset["images"])} images, {len(test_dataset["annotations"])} annotations')
print(os.path.abspath(output_path))
train_image_path = os.path.join(output_path, 'images', 'instances_train2017')
val_image_path = os.path.join(output_path, 'images', 'instances_val2017')
test_image_path = os.path.join(output_path, 'images', 'instances_test2017')
os.makedirs(output_path, exist_ok=True)
os.makedirs(train_image_path, exist_ok=True)
os.makedirs(val_image_path, exist_ok=True)
os.makedirs(test_image_path, exist_ok=True)
os.makedirs(os.path.join(output_path, 'annotations'), exist_ok=True)
with open(os.path.join(output_path, 'annotations', 'instances_train2017.json'), 'w') as f:
json.dump(train_dataset, f, indent=4)
with open(os.path.join(output_path, 'annotations', 'instances_val2017.json'), 'w') as f:
json.dump(val_dataset, f, indent=4)
with open(os.path.join(output_path, 'annotations', 'instances_test2017.json'), 'w') as f:
json.dump(test_dataset, f, indent=4)
if image_path:
for image in train_dataset['images']:
shutil.copy(os.path.join(image_path, image['file_name']), train_image_path)
for image in val_dataset['images']:
shutil.copy(os.path.join(image_path, image['file_name']), val_image_path)
for image in test_dataset['images']:
shutil.copy(os.path.join(image_path, image['file_name']), test_image_path)
def main(args):
if args.gen:
generate_fold_app(args)
split(args)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--ann_file', type=str, required=True)
parser.add_argument('--img_dir', type=str, required=True)
parser.add_argument('--output_path', type=str, default='./coco_split')
parser.add_argument('--train_folds', type=str, default=None)
parser.add_argument('--val_folds', type=str, default=None)
parser.add_argument('--test_folds', type=str, default=None)
parser.add_argument('--gen', action='store_true')
parser.add_argument('--fold_file', type=str, required=True)
args = parser.parse_args()
main(args)