This gists collect scripts converting datasets to yolo format including kitti2yolo.py and wider2yolo.py
yolo format class_id cx/widht cy/height w/width h/height
import json | |
from pathlib import Path | |
import glob | |
import os | |
import shutil | |
from tqdm import tqdm | |
import numpy as np | |
def coco91_to_coco80_class(): # converts 80-index (val2014) to 91-index (paper) | |
# https://tech.amikelive.com/node-718/what-object-categories-labels-are-in-coco-dataset/ | |
# a = np.loadtxt('data/coco.names', dtype='str', delimiter='\n') | |
# b = np.loadtxt('data/coco_paper.names', dtype='str', delimiter='\n') | |
# x1 = [list(a[i] == b).index(True) + 1 for i in range(80)] # darknet to coco | |
# x2 = [list(b[i] == a).index(True) if any(b[i] == a) else None for i in range(91)] # coco to darknet | |
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, None, 24, 25, None, | |
None, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, None, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, | |
51, 52, 53, 54, 55, 56, 57, 58, 59, None, 60, None, None, 61, None, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, | |
None, 73, 74, 75, 76, 77, 78, 79, None] | |
return x | |
def make_folders(path): | |
# Create folders | |
if os.path.exists(path): | |
shutil.rmtree(path) # delete output folder | |
os.makedirs(path) # make new output folder | |
os.makedirs(path + os.sep + 'labels') # make new labels folder | |
os.makedirs(path + os.sep + 'images') # make new labels folder | |
return path | |
def convert_coco_json(json_dir, out_root): | |
assert out_root is not None | |
make_folders(path=out_root) # output directory | |
jsons = glob.glob(json_dir + 'instances_*.json') | |
coco80 = coco91_to_coco80_class() | |
# Import json | |
for json_file in sorted(jsons): | |
json_file = Path(json_file) | |
out_dir_name = Path(json_file).stem.replace('instances_', '') | |
fn = f'{out_root}/labels/{out_dir_name}/' | |
os.mkdir(fn) | |
with open(json_file) as f: | |
data = json.load(f) | |
# Create image dict | |
images = {'%g' % x['id']: x for x in data['images']} | |
# Write labels file | |
for x in tqdm(data['annotations'], desc='Annotations %s' % json_file.name): | |
if x['iscrowd']: | |
continue | |
img = images['%g' % x['image_id']] | |
h, w, f = img['height'], img['width'], img['file_name'] | |
# The Labelbox bounding box format is [top left x, top left y, width, height] | |
box = np.array(x['bbox'], dtype=np.float64) | |
box[:2] += box[2:] / 2 # xy top-left corner to center | |
box[[0, 2]] /= w # normalize x | |
box[[1, 3]] /= h # normalize y | |
if (box[2] > 0.) and (box[3] > 0.): # if w > 0 and h > 0 | |
with open(fn + Path(f).stem + '.txt', 'a') as file: | |
file.write('%g %.6f %.6f %.6f %.6f\n' % (coco80[x['category_id'] - 1], *box)) | |
if __name__ == '__main__': | |
JSON_DIR = '/media/HD1/datasets/coco2017/annotations/' | |
OUT_DIR = './coco2017/' | |
convert_coco_json(JSON_DIR, OUT_DIR) |
This gists collect scripts converting datasets to yolo format including kitti2yolo.py and wider2yolo.py
yolo format class_id cx/widht cy/height w/width h/height
""" | |
convert_txt0 use the original images | |
convert_txt1 crop the original images | |
""" | |
from pathlib import Path | |
from PIL import Image | |
import numpy as np | |
import pandas as pd | |
import shutil | |
import random | |
LABEL_CFG = { | |
'person': [ | |
'Pedestrian', | |
'Person_sitting' | |
], | |
'cyclist': [ | |
'Cyclist' | |
], | |
'car': [ | |
'Car', | |
'Van', | |
], | |
} | |
KITTI_ROOT = Path('/data/luojiapeng/datasets/kitti/') | |
KITTI_TXT = KITTI_ROOT / 'training/ImageSets/trainval.txt' | |
OUT_ROOT = Path('./kitti') | |
class Convert_Original_Label: | |
_NAMES = list(LABEL_CFG.keys()) | |
_DICT = {v:k for k,v_lst in LABEL_CFG.items() for v in v_lst } | |
@classmethod | |
def __call__(cls, name): | |
if name not in cls._DICT: | |
return None | |
else: | |
return cls._NAMES.index(cls._DICT[name]) | |
label_converter = Convert_Original_Label() | |
def convert_txt0(src_txt, src_img, dst_txt, dst_img): | |
# directly convert coordinate and copy image | |
data = pd.read_csv(str(src_txt), ' ', header=None, index_col=None) | |
classes = data.loc[:, 0].values.tolist() | |
boxes = data.loc[:, 4:7].values.tolist() | |
img = Image.open(str(src_img)) | |
im_w, im_h = img.size | |
fp = open(dst_txt, 'w') | |
for c, box in zip(classes, boxes): | |
new_c = label_converter(c) | |
if new_c is None: | |
continue | |
x0, y0, x1, y1 = box | |
x0, x1 = x0 / im_w, x1 / im_w | |
y0, y1 = y0 / im_h, y1 / im_h | |
cx = (x0 + x1) / 2 | |
cy = (y0 + y1) / 2 | |
box_w = x1 - x0 | |
box_h = y1 - y0 | |
fp.write('%d %.6f %.6f %.6f %.6f\n' % (new_c, cx, cy, box_w, box_h)) | |
fp.close() | |
# cp img_file | |
shutil.copyfile(str(src_img), str(dst_img)) | |
return [dst_txt], [dst_img] | |
def convert_txt1(src_txt, src_img, dst_txt, dst_img): | |
# convert coordinate and copy image with crop | |
data = pd.read_csv(str(src_txt), ' ', header=None, index_col=None) | |
classes = data.loc[:, 0].values.tolist() | |
boxes = data.loc[:, 4:7].values | |
img = Image.open(str(src_img)) | |
im_w, im_h = img.size | |
crop_x0, crop_y0, crop_x1, crop_y1 = 0, 0, im_h, im_h | |
count = 0 | |
out_txt_lst = [] | |
out_img_lst = [] | |
while True: | |
if crop_x1 >= im_w: | |
break | |
crop_box = (crop_x0, crop_y0, crop_x1, crop_y1) | |
c_img, c_boxes = crop_image_box(img, boxes, crop_box) | |
dst_txt_i = dst_txt.with_name(f'{dst_txt.stem}_{count}.txt') | |
dst_img_i = dst_img.with_name(f'{dst_img.stem}_{count}.png') | |
c_img.save(str(dst_img_i)) | |
count += 1 | |
fp = open(dst_txt_i, 'w') | |
for c, box in zip(classes, c_boxes): | |
new_c = label_converter(c) | |
if not new_c: | |
continue | |
x0, y0, x1, y1 = box | |
x0, x1 = x0 / im_h, x1 / im_h | |
y0, y1 = y0 / im_h, y1 / im_h | |
cx = (x0 + x1) / 2 | |
cy = (y0 + y1) / 2 | |
box_w = x1 - x0 | |
box_h = y1 - y0 | |
fp.write('%d %.6f %.6f %.6f %.6f\n' % (new_c, cx, cy, box_w, box_h)) | |
out_txt_lst.append(dst_txt_i) | |
out_img_lst.append(dst_img_i) | |
crop_x0 += im_h // 2 | |
crop_x1 += im_h // 2 | |
fp.close() | |
return out_txt_lst, out_img_lst | |
def crop_image_box(image, boxes, crop_box): | |
img = image.crop(crop_box) | |
x0, y0, x1, y1 = np.split(boxes, 4, axis=1) | |
x0 = np.clip(x0 - crop_box[0], 0, img.size[0]) | |
y0 = np.clip(y0 - crop_box[1], 0, img.size[1]) | |
x1 = np.clip(x1 - crop_box[0], 0, img.size[0]) | |
y1 = np.clip(y1 - crop_box[1], 0, img.size[1]) | |
boxes = np.stack([x0, y0, x1, y1], axis=1) | |
return img, boxes | |
def func(id_lst, mode): | |
OUT_ROOT.mkdir(parents=True, exist_ok=True) | |
fp = open(OUT_ROOT / f'{mode}.txt', 'w') | |
for file_id in id_lst: | |
print(file_id) | |
txt_file = KITTI_ROOT / f'training/label_2/{file_id}.txt' | |
img_file = KITTI_ROOT / f'training/image_2/{file_id}.png' | |
out_txt_file = OUT_ROOT / f'labels/{mode}/{file_id}.txt' | |
out_img_file = OUT_ROOT / f'images/{mode}/{file_id}.png' | |
out_txt_file.parent.mkdir(parents=True, exist_ok=True) | |
out_img_file.parent.mkdir(parents=True, exist_ok=True) | |
out_txts, out_imgs = convert_txt0(txt_file, img_file, out_txt_file, out_img_file) | |
for x in out_imgs: | |
fp.write(str(x.absolute())+'\n') | |
fp.close() | |
if __name__ == '__main__': | |
file_id_lst = np.loadtxt(KITTI_TXT, dtype=str).tolist() | |
random.shuffle(file_id_lst) | |
train_num = int(len(file_id_lst) * 0.8) | |
train_id_lst = sorted(file_id_lst[:train_num]) | |
val_id_lst = sorted(file_id_lst[train_num:]) | |
func(train_id_lst, 'train') | |
func(val_id_lst, 'val') |
from pathlib import Path | |
import numpy as np | |
from PIL import Image | |
import shutil | |
WIDER_ROOT = Path('/media/HD1/Datasets/widerface') | |
MODE = 'val' | |
def read_txt(file_path): | |
data = {} | |
for line in open(file_path).readlines(): | |
line = line.rstrip() | |
if not line: | |
continue | |
if line.endswith('.jpg'): | |
file_id = line[:-4] | |
data[file_id] = [] | |
continue | |
line = line.split() | |
if len(line) == 10: | |
x0, y0, w, h = [int(x) for x in line[:4]] | |
x1 = x0 + w | |
y1 = y0 + h | |
data[file_id].append([x0, y0, x1, y1]) | |
return data | |
if __name__ == '__main__': | |
src_img_dir = WIDER_ROOT / f'WIDER_{MODE}/images' | |
txt_file = WIDER_ROOT / f'wider_face_split/wider_face_{MODE}_bbx_gt.txt' | |
dst_img_dir = Path(f'./wider/images/{MODE}') | |
dst_txt_dir = Path(f'./wider/labels/{MODE}') | |
img_list_file = Path(f'./wider/{MODE}.txt') | |
dst_img_dir.mkdir(parents=True, exist_ok=False) | |
dst_txt_dir.mkdir(parents=True, exist_ok=False) | |
labels = read_txt(txt_file) | |
img_list_fp = open(img_list_file, 'w') | |
for file_id, boxes in labels.items(): | |
if len(boxes) == 0: | |
continue | |
src_img = src_img_dir / (file_id + '.jpg') | |
dst_id = file_id.split('/')[1] | |
dst_img = dst_img_dir / (dst_id + '.jpg') | |
dst_txt = dst_txt_dir / (dst_id + '.txt') | |
dst_img.parent.mkdir(exist_ok=True) | |
dst_txt.parent.mkdir(exist_ok=True) | |
img = Image.open(str(src_img)) | |
im_w, im_h = img.size | |
fp = open(dst_txt, 'w') | |
dst_txt.parent.mkdir(exist_ok=True) | |
for box in boxes: | |
x0, y0, x1, y1 = box | |
cx = (x0 + x1) / 2 | |
cy = (y0 + y1) / 2 | |
w = x1 - x0 | |
h = y1 - y0 | |
cx /= im_w | |
cy /= im_h | |
w /= im_w | |
h /= im_h | |
fp.write('0 %.6f %.6f %.6f %.6f\n' % (cx, cy, w, h)) | |
fp.close() | |
shutil.copyfile(str(src_img), str(dst_img)) | |
img_list_fp.write(str(dst_img.absolute())+'\n') | |
img_list_fp.close() | |