|
| 1 | +# Copyright (c) OpenMMLab. All rights reserved. |
| 2 | +import json |
| 3 | +import math |
| 4 | +import os |
| 5 | +import os.path as osp |
| 6 | + |
| 7 | +import cv2 |
| 8 | +import numpy as np |
| 9 | + |
| 10 | + |
| 11 | +def default_dump(obj): |
| 12 | + """Convert numpy classes to JSON serializable objects.""" |
| 13 | + if isinstance(obj, (np.integer, np.floating, np.bool_)): |
| 14 | + return obj.item() |
| 15 | + elif isinstance(obj, np.ndarray): |
| 16 | + return obj.tolist() |
| 17 | + else: |
| 18 | + return obj |
| 19 | + |
| 20 | + |
| 21 | +def convert_wflw_to_coco(ann_file, out_file): |
| 22 | + annotations = [] |
| 23 | + images = [] |
| 24 | + files = [] |
| 25 | + cnt = 0 |
| 26 | + image_cnt = 0 |
| 27 | + |
| 28 | + data_infos = open(ann_file).readlines() |
| 29 | + data_infos = [x.strip().split() for x in data_infos] |
| 30 | + for data in data_infos: |
| 31 | + file_name = data[-1] |
| 32 | + img_path = osp.join('data/wflw/WFLW_images', file_name) |
| 33 | + img = cv2.imread(img_path) |
| 34 | + |
| 35 | + keypoints = [] |
| 36 | + |
| 37 | + coordinates = [data[i:i + 2] for i in range(0, 196, 2)] |
| 38 | + |
| 39 | + for coordinate in coordinates: |
| 40 | + x, y = coordinate[0], coordinate[1] |
| 41 | + x, y = float(x), float(y) |
| 42 | + keypoints.append([x, y, 1]) |
| 43 | + keypoints = np.array(keypoints) |
| 44 | + |
| 45 | + x1, y1, _ = np.amin(keypoints, axis=0) |
| 46 | + x2, y2, _ = np.amax(keypoints, axis=0) |
| 47 | + w, h = x2 - x1, y2 - y1 |
| 48 | + scale = math.ceil(max(w, h)) / 200 |
| 49 | + w_new = w / scale |
| 50 | + h_new = h / scale |
| 51 | + center = [(x1 + x2) / 2, (y1 + y2) / 2] |
| 52 | + x1_new = center[0] - w_new / 2 |
| 53 | + y1_new = center[1] - h_new / 2 |
| 54 | + bbox = [x1_new, y1_new, w_new, h_new] |
| 55 | + |
| 56 | + image = {} |
| 57 | + # check if the image already exists |
| 58 | + if file_name in files: |
| 59 | + image = images[files.index(file_name)] |
| 60 | + else: |
| 61 | + image['id'] = image_cnt |
| 62 | + image['file_name'] = f'{file_name}' |
| 63 | + image['height'] = img.shape[0] |
| 64 | + image['width'] = img.shape[1] |
| 65 | + image_cnt = image_cnt + 1 |
| 66 | + files.append(file_name) |
| 67 | + images.append(image) |
| 68 | + |
| 69 | + ann = {} |
| 70 | + ann['keypoints'] = keypoints.reshape(-1).tolist() |
| 71 | + ann['image_id'] = image['id'] |
| 72 | + ann['id'] = cnt |
| 73 | + ann['num_keypoints'] = len(keypoints) |
| 74 | + ann['bbox'] = bbox |
| 75 | + ann['is_crowd'] = 0 |
| 76 | + ann['area'] = w * h |
| 77 | + ann['category_id'] = 1 |
| 78 | + ann['center'] = center |
| 79 | + ann['scale'] = scale |
| 80 | + annotations.append(ann) |
| 81 | + cnt = cnt + 1 |
| 82 | + |
| 83 | + cocotype = {} |
| 84 | + cocotype['images'] = images |
| 85 | + cocotype['annotations'] = annotations |
| 86 | + cocotype['categories'] = [{ |
| 87 | + 'supercategory': 'person', |
| 88 | + 'id': 1, |
| 89 | + 'name': 'face', |
| 90 | + 'keypoints': [], |
| 91 | + 'skeleton': [] |
| 92 | + }] |
| 93 | + |
| 94 | + json.dump( |
| 95 | + cocotype, |
| 96 | + open(out_file, 'w'), |
| 97 | + ensure_ascii=False, |
| 98 | + default=default_dump) |
| 99 | + print(f'done {out_file}') |
| 100 | + |
| 101 | + |
| 102 | +if __name__ == '__main__': |
| 103 | + if not osp.exists('data/wflw/annotations'): |
| 104 | + os.makedirs('data/wflw/annotations') |
| 105 | + root_folder = 'data/wflw' |
| 106 | + ann_folder = f'{root_folder}/WFLW_annotations' |
| 107 | + for root, dirs, files in os.walk(ann_folder): |
| 108 | + for file in files: |
| 109 | + if not file.endswith('txt'): |
| 110 | + continue |
| 111 | + print(f'Processing {file}') |
| 112 | + sub_class = file.split('_')[-1].replace('.txt', '') |
| 113 | + if sub_class != 'train' and sub_class != 'test': |
| 114 | + out_file = f'face_landmarks_wflw_test_{sub_class}.json' |
| 115 | + else: |
| 116 | + out_file = f'face_landmarks_wflw_{sub_class}.json' |
| 117 | + convert_wflw_to_coco(f'{root}/{file}', |
| 118 | + f'{root_folder}/annotations/{out_file}') |
0 commit comments