diff --git a/configs/pose/hand/litehrnet_30_coco_wholebody_hand_256x256.py b/configs/pose/hand/litehrnet_30_coco_wholebody_hand_256x256.py new file mode 100644 index 00000000..0c47db73 --- /dev/null +++ b/configs/pose/hand/litehrnet_30_coco_wholebody_hand_256x256.py @@ -0,0 +1,176 @@ +# oss_io_config = dict( +# ak_id='your oss ak id', +# ak_secret='your oss ak secret', +# hosts='oss-cn-zhangjiakou.aliyuncs.com', # your oss hosts +# buckets=['your_bucket']) # your oss buckets + +oss_sync_config = dict(other_file_list=['**/events.out.tfevents*', '**/*log*']) + +log_level = 'INFO' +load_from = None +resume_from = None +dist_params = dict(backend='nccl') +workflow = [('train', 1)] +checkpoint_config = dict(interval=10) + +optimizer = dict(type='Adam', lr=5e-4) +optimizer_config = dict(grad_clip=None) +# learning policy +lr_config = dict( + policy='step', + warmup='linear', + warmup_iters=500, + warmup_ratio=0.001, + step=[170, 200]) +total_epochs = 210 +log_config = dict( + interval=50, + hooks=[dict(type='TextLoggerHook'), + dict(type='TensorboardLoggerHook')]) +channel_cfg = dict( + num_output_channels=21, + dataset_joints=21, + dataset_channel=[ + [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20 + ], + ], + inference_channel=[ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20 + ]) + +# model settings +model = dict( + type='TopDown', + pretrained=False, + backbone=dict( + type='LiteHRNet', + in_channels=3, + extra=dict( + stem=dict(stem_channels=32, out_channels=32, expand_ratio=1), + num_stages=3, + stages_spec=dict( + num_modules=(3, 8, 3), + num_branches=(2, 3, 4), + num_blocks=(2, 2, 2), + module_type=('LITE', 'LITE', 'LITE'), + with_fuse=(True, True, True), + reduce_ratios=(8, 8, 8), + num_channels=( + (40, 80), + (40, 80, 160), + (40, 80, 160, 320), + )), + with_head=True, + )), + keypoint_head=dict( + type='TopdownHeatmapSimpleHead', + in_channels=40, + out_channels=channel_cfg['num_output_channels'], + num_deconv_layers=0, + extra=dict(final_conv_kernel=1, ), + loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)), + train_cfg=dict(), + test_cfg=dict( + flip_test=True, + post_process='default', + shift_heatmap=True, + modulate_kernel=11)) + +data_root = 'data/coco' + +data_cfg = dict( + image_size=[256, 256], + heatmap_size=[64, 64], + num_output_channels=channel_cfg['num_output_channels'], + num_joints=channel_cfg['dataset_joints'], + dataset_channel=channel_cfg['dataset_channel'], + inference_channel=channel_cfg['inference_channel'], +) + +train_pipeline = [ + # dict(type='TopDownGetBboxCenterScale', padding=1.25), + dict(type='TopDownRandomFlip', flip_prob=0.5), + dict( + type='TopDownGetRandomScaleRotation', rot_factor=30, + scale_factor=0.25), + dict(type='TopDownAffine'), + dict(type='MMToTensor'), + dict( + type='NormalizeTensor', + mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), + dict(type='TopDownGenerateTarget', sigma=3), + dict( + type='PoseCollect', + keys=['img', 'target', 'target_weight'], + meta_keys=[ + 'image_file', 'image_id', 'joints_3d', 'joints_3d_visible', + 'center', 'scale', 'rotation', 'flip_pairs' + ]) +] + +val_pipeline = [ + dict(type='TopDownAffine'), + dict(type='MMToTensor'), + dict( + type='NormalizeTensor', + mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]), + dict( + type='PoseCollect', + keys=['img'], + meta_keys=[ + 'image_file', 'image_id', 'center', 'scale', 'rotation', + 'flip_pairs' + ]) +] + +test_pipeline = val_pipeline +data_source_cfg = dict(type='HandCocoPoseTopDownSource', data_cfg=data_cfg) + +data = dict( + imgs_per_gpu=32, # for train + workers_per_gpu=2, # for train + # imgs_per_gpu=1, # for test + # workers_per_gpu=1, # for test + val_dataloader=dict(samples_per_gpu=32), + test_dataloader=dict(samples_per_gpu=32), + train=dict( + type='HandCocoWholeBodyDataset', + data_source=dict( + ann_file=f'{data_root}/annotations/coco_wholebody_train_v1.0.json', + img_prefix=f'{data_root}/train2017/', + **data_source_cfg), + pipeline=train_pipeline), + val=dict( + type='HandCocoWholeBodyDataset', + data_source=dict( + ann_file=f'{data_root}/annotations/coco_wholebody_val_v1.0.json', + img_prefix=f'{data_root}/val2017/', + test_mode=True, + **data_source_cfg), + pipeline=val_pipeline), + test=dict( + type='HandCocoWholeBodyDataset', + data_source=dict( + ann_file=f'{data_root}/annotations/coco_wholebody_val_v1.0.json', + img_prefix=f'{data_root}/val2017/', + test_mode=True, + **data_source_cfg), + pipeline=val_pipeline), +) + +eval_config = dict(interval=10, metric='PCK', save_best='PCK') +evaluator_args = dict( + metric_names=['PCK', 'AUC', 'EPE', 'NME'], pck_thr=0.2, auc_nor=30) +eval_pipelines = [ + dict( + mode='test', + data=dict(**data['val'], imgs_per_gpu=1), + evaluators=[dict(type='KeyPointEvaluator', **evaluator_args)]) +] +export = dict(use_jit=False) +checkpoint_sync_export = True diff --git a/data/test/pose/hand/small_whole_body_hand_coco/annotations/small_whole_body_hand_coco.json b/data/test/pose/hand/small_whole_body_hand_coco/annotations/small_whole_body_hand_coco.json new file mode 100644 index 00000000..8b1aa35d --- /dev/null +++ b/data/test/pose/hand/small_whole_body_hand_coco/annotations/small_whole_body_hand_coco.json @@ -0,0 +1,2381 @@ +{ + "info": { + "description": "COCO-WholeBody", + "url": "https://github.com/jin-s13/COCO-WholeBody", + "version": "1.0", + "year": "2020", + "date_created": "2020/07/01" + }, + "licenses": [ + { + "url": "http://creativecommons.org/licenses/by-nc-sa/2.0/", + "id": 1, + "name": "Attribution-NonCommercial-ShareAlike License" + }, + { + "url": "http://creativecommons.org/licenses/by-nc/2.0/", + "id": 2, + "name": "Attribution-NonCommercial License" + }, + { + "url": "http://creativecommons.org/licenses/by-nc-nd/2.0/", + "id": 3, + "name": "Attribution-NonCommercial-NoDerivs License" + }, + { + "url": "http://creativecommons.org/licenses/by/2.0/", + "id": 4, + "name": "Attribution License" + }, + { + "url": "http://creativecommons.org/licenses/by-sa/2.0/", + "id": 5, + "name": "Attribution-ShareAlike License" + }, + { + "url": "http://creativecommons.org/licenses/by-nd/2.0/", + "id": 6, + "name": "Attribution-NoDerivs License" + }, + { + "url": "http://flickr.com/commons/usage/", + "id": 7, + "name": "No known copyright restrictions" + }, + { + "url": "http://www.usa.gov/copyright.shtml", + "id": 8, + "name": "United States Government Work" + } + ], + "images":[ + { + "license": 1, + "file_name": "000000425226.jpg", + "coco_url": "http://images.cocodataset.org/val2017/000000425226.jpg", + "height": 640, + "width": 480, + "date_captured": "2013-11-14 21:48:51", + "flickr_url": "http://farm5.staticflickr.com/4055/4546463824_bc40e0752b_z.jpg", + "id": 425226 + }, + { + "license": 3, + "file_name": "000000292456.jpg", + "coco_url": "http://images.cocodataset.org/val2017/000000292456.jpg", + "height": 375, + "width": 500, + "date_captured": "2013-11-15 13:30:32", + "flickr_url": "http://farm2.staticflickr.com/1284/846533447_96678f6640_z.jpg", + "id": 292456 + } + ], + "annotations":[ + { + "segmentation": [ + [ + 125.12, + 539.69, + 140.94, + 522.43, + 100.67, + 496.54, + 84.85, + 469.21, + 73.35, + 450.52, + 104.99, + 342.65, + 168.27, + 290.88, + 179.78, + 288, + 189.84, + 286.56, + 191.28, + 260.67, + 202.79, + 240.54, + 221.48, + 237.66, + 248.81, + 243.42, + 257.44, + 256.36, + 253.12, + 262.11, + 253.12, + 275.06, + 299.15, + 233.35, + 329.35, + 207.46, + 355.24, + 206.02, + 363.87, + 206.02, + 365.3, + 210.34, + 373.93, + 221.84, + 363.87, + 226.16, + 363.87, + 237.66, + 350.92, + 237.66, + 332.22, + 234.79, + 314.97, + 249.17, + 271.82, + 313.89, + 253.12, + 326.83, + 227.24, + 352.72, + 214.29, + 357.03, + 212.85, + 372.85, + 208.54, + 395.87, + 228.67, + 414.56, + 245.93, + 421.75, + 266.07, + 424.63, + 276.13, + 437.57, + 266.07, + 450.52, + 284.76, + 464.9, + 286.2, + 479.28, + 291.96, + 489.35, + 310.65, + 512.36, + 284.76, + 549.75, + 244.49, + 522.43, + 215.73, + 546.88, + 199.91, + 558.38, + 204.22, + 565.57, + 189.84, + 568.45, + 184.09, + 575.64, + 172.58, + 578.52, + 145.26, + 567.01, + 117.93, + 551.19, + 133.75, + 532.49 + ] + ], + "num_keypoints": 10, + "area": 47803.27955, + "iscrowd": 0, + "keypoints": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 142, + 309, + 1, + 177, + 320, + 2, + 191, + 398, + 2, + 237, + 317, + 2, + 233, + 426, + 2, + 306, + 233, + 2, + 92, + 452, + 2, + 123, + 468, + 2, + 0, + 0, + 0, + 251, + 469, + 2, + 0, + 0, + 0, + 162, + 551, + 2 + ], + "image_id": 425226, + "bbox": [ + 73.35, + 206.02, + 300.58, + 372.5 + ], + "category_id": 1, + "id": 183126, + "face_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "lefthand_box": [ + 235.32, + 420.86, + 36.03000000000003, + 31.66999999999996 + ], + "righthand_box": [ + 304.2, + 204.65, + 68.03000000000003, + 42.579999999999984 + ], + "lefthand_kpts": [ + 237.0, + 426.0, + 0.10405432432889938, + 245.0, + 428.0, + 0.20745894312858582, + 253.0, + 430.0, + 0.20745894312858582, + 261.0, + 433.0, + 0.5343613624572754, + 269.0, + 438.0, + 0.2143213450908661, + 265.0, + 429.0, + 0.12357126176357269, + 270.0, + 433.0, + 0.26612094044685364, + 269.0, + 439.0, + 0.09291676431894302, + 265.0, + 445.0, + 0.1144329234957695, + 264.0, + 427.0, + 0.04132022708654404, + 269.0, + 438.0, + 0.14125224947929382, + 265.0, + 445.0, + 0.12546022236347198, + 260.0, + 446.0, + 0.1301765739917755, + 261.0, + 431.0, + 0.03911404311656952, + 269.0, + 438.0, + 0.05325932428240776, + 263.0, + 445.0, + 0.0727347582578659, + 260.0, + 446.0, + 0.09616264700889587, + 262.0, + 426.0, + 0.02422112599015236, + 262.0, + 446.0, + 0.05307695269584656, + 259.0, + 447.0, + 0.10021205991506577, + 256.0, + 449.0, + 0.16766609251499176 + ], + "righthand_kpts": [ + 308.0, + 239.0, + 0.1408521831035614, + 321.0, + 226.5, + 0.02196568436920643, + 334.0, + 214.0, + 0.02196568436920643, + 354.0, + 211.0, + 0.10082424432039261, + 365.0, + 206.0, + 0.7382210493087769, + 346.0, + 209.0, + 0.36809757351875305, + 364.0, + 214.0, + 0.18089689314365387, + 355.0, + 209.0, + 0.1661667376756668, + 370.0, + 226.0, + 0.0630379319190979, + 342.0, + 214.0, + 0.20839764177799225, + 364.0, + 216.0, + 0.3880220949649811, + 368.0, + 226.0, + 0.26579514145851135, + 374.0, + 236.0, + 0.2594422996044159, + 338.0, + 218.0, + 0.4262842833995819, + 356.0, + 220.0, + 0.6470030546188354, + 364.0, + 227.0, + 0.3695657551288605, + 372.0, + 237.0, + 0.14602071046829224, + 335.0, + 227.0, + 0.425717294216156, + 347.0, + 229.0, + 0.479814738035202, + 356.0, + 232.0, + 0.3711409270763397, + 364.0, + 234.0, + 0.39777901768684387 + ], + "face_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "face_valid": false, + "lefthand_valid": true, + "righthand_valid": true, + "foot_valid": true, + "foot_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 203.91247, + 554.31637, + 2.0, + 186.27924, + 568.78466, + 2.0, + 134.28382, + 542.10875, + 2.0 + ] + }, + { + "segmentation": [ + [ + 237.64, + 275.62, + 235.11, + 282.36, + 240.17, + 291.63, + 248.6, + 300.9, + 251.12, + 284.04, + 251.12, + 275.62, + 254.49, + 258.76, + 267.98, + 246.12, + 267.98, + 239.38, + 268.82, + 230.96, + 262.08, + 224.21, + 259.55, + 211.57, + 260.39, + 199.78, + 260.39, + 188.82, + 260.39, + 104.55, + 312.64, + 94.44, + 294.1, + 84.33, + 290.73, + 80.96, + 295.79, + 68.31, + 294.94, + 53.99, + 291.57, + 48.09, + 280.62, + 45.56, + 268.82, + 48.09, + 258.71, + 51.46, + 259.55, + 62.42, + 256.18, + 70.84, + 256.18, + 80.11, + 252.81, + 89.38, + 265.45, + 95.28, + 251.97, + 104.55, + 240.17, + 125.62, + 234.27, + 136.57, + 224.16, + 142.47, + 214.04, + 146.69, + 199.72, + 150.9, + 192.98, + 153.43, + 187.08, + 153.43, + 184.55, + 159.33, + 191.29, + 170.28, + 198.88, + 171.97, + 210.67, + 170.28, + 224.16, + 164.38, + 232.58, + 159.33, + 239.33, + 156.8, + 247.75, + 148.37, + 250.28, + 143.31, + 255.34, + 156.8, + 255.34, + 163.54, + 255.34, + 172.81, + 256.18, + 180.39, + 256.18, + 186.29, + 257.87, + 196.4, + 254.49, + 204.83, + 250.28, + 211.57, + 248.6, + 217.47, + 248.6, + 224.21, + 247.75, + 236.01, + 247.75, + 246.97, + 246.07, + 269.72, + 244.38, + 282.36, + 238.48, + 275.62 + ] + ], + "num_keypoints": 13, + "area": 5425.7433, + "iscrowd": 0, + "keypoints": [ + 256, + 76, + 1, + 260, + 70, + 2, + 0, + 0, + 0, + 269, + 72, + 2, + 0, + 0, + 0, + 254, + 112, + 2, + 307, + 99, + 1, + 236, + 145, + 2, + 338, + 150, + 1, + 200, + 160, + 2, + 0, + 0, + 0, + 270, + 189, + 1, + 308, + 188, + 1, + 257, + 227, + 2, + 359, + 246, + 1, + 251, + 287, + 1, + 0, + 0, + 0 + ], + "image_id": 292456, + "bbox": [ + 184.55, + 45.56, + 128.09, + 255.34 + ], + "category_id": 1, + "id": 184382, + "face_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "lefthand_box": [ + 184.74, + 153.3, + 17.42999999999998, + 16.939999999999998 + ], + "righthand_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "lefthand_kpts": [ + 197.4, + 160.1, + 1, + 195.7, + 156.85, + 1, + 194.0, + 153.6, + 2, + 191.8, + 154.7, + 2, + 190.2, + 156.7, + 1, + 188.3, + 158.3, + 2, + 185.9, + 159.9, + 2, + 187.8, + 160.1, + 1, + 189.6, + 159.5, + 1, + 188.4, + 161.1, + 2, + 185.8, + 163.2, + 2, + 187.8, + 163.2, + 1, + 189.9, + 161.9, + 1, + 189.1, + 164.2, + 2, + 187.3, + 166.3, + 2, + 189.4, + 165.8, + 1, + 190.9, + 164.3, + 1, + 190.7, + 166.9, + 2, + 189.6, + 168.4, + 2, + 191.3, + 168.0, + 1, + 192.8, + 166.6, + 1 + ], + "righthand_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "face_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "face_valid": false, + "lefthand_valid": true, + "righthand_valid": false, + "foot_valid": true, + "foot_kpts": [ + 243.75893, + 280.33895, + 2.0, + 238.25574, + 283.57612, + 2.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + { + "segmentation": [ + [ + 335.68, + 70.36, + 323.93, + 70.36, + 323.93, + 70.36, + 323.93, + 77.07, + 323.93, + 83.78, + 323.09, + 87.97, + 322.26, + 95.53, + 323.93, + 103.91, + 325.61, + 108.11, + 326.45, + 115.66, + 327.29, + 125.73, + 328.13, + 132.44, + 329.81, + 137.47, + 329.81, + 150.06, + 334, + 155.93, + 335.68, + 159.28, + 338.19, + 160.96, + 345.74, + 157.61, + 348.26, + 153.41, + 351.62, + 144.18, + 351.62, + 129.92, + 349.94, + 124.89, + 345.74, + 106.43, + 344.91, + 103.08, + 345.74, + 101.4, + 354.13, + 82.94, + 352.46, + 75.39, + 347.42, + 71.2, + 347.42, + 71.2, + 335.68, + 68.68 + ] + ], + "num_keypoints": 10, + "area": 2050.998, + "iscrowd": 0, + "keypoints": [ + 346, + 92, + 2, + 347, + 87, + 2, + 340, + 86, + 2, + 0, + 0, + 0, + 327, + 88, + 2, + 316, + 109, + 1, + 337, + 109, + 2, + 0, + 0, + 0, + 358, + 151, + 1, + 0, + 0, + 0, + 380, + 179, + 1, + 309, + 177, + 1, + 331, + 179, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "image_id": 292456, + "bbox": [ + 322.26, + 68.68, + 31.87, + 92.28 + ], + "category_id": 1, + "id": 208754, + "face_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "lefthand_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "righthand_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "lefthand_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "righthand_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "face_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "face_valid": false, + "lefthand_valid": false, + "righthand_valid": false, + "foot_valid": false, + "foot_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + { + "segmentation": [ + [ + 145.65, + 41.37, + 160.08, + 33.24, + 172.68, + 31.93, + 176.35, + 38.23, + 175.57, + 46.62, + 173.73, + 50.82, + 174.78, + 55.02, + 172.68, + 59.74, + 170.32, + 66.57, + 167.17, + 70.76, + 165.07, + 73.91, + 166.91, + 77.59, + 165.07, + 83.36, + 167.43, + 90.97, + 167.96, + 103.83, + 167.96, + 115.63, + 167.43, + 122.46, + 186.06, + 138.2, + 188.69, + 147.12, + 190.26, + 152.63, + 184.22, + 157.36, + 177.93, + 156.31, + 167.69, + 145.02, + 169.01, + 169.69, + 159.03, + 173.95, + 152.74, + 176.84, + 150.64, + 197.57, + 152.47, + 212, + 161.66, + 216.2, + 163.23, + 224.34, + 162.45, + 228.01, + 162.97, + 250.31, + 165.33, + 258.71, + 172.68, + 267.11, + 170.58, + 270.26, + 159.03, + 270.26, + 149.59, + 267.63, + 144.86, + 265.8, + 144.08, + 256.61, + 138.04, + 248.21, + 134.63, + 247.43, + 132.27, + 242.44, + 135.42, + 233.52, + 140.14, + 220.4, + 139.09, + 205.18, + 135.94, + 173.95, + 129.91, + 167.04, + 131.48, + 150.25, + 133.06, + 132.41, + 134.37, + 124.27, + 132.79, + 115.87, + 132.79, + 88.52, + 137.52, + 81.96, + 143.29, + 74.61, + 146.44, + 68.84, + 149.59, + 61.23, + 148.54, + 55.98, + 146.44, + 50.73, + 143.03, + 45.75 + ] + ], + "num_keypoints": 14, + "area": 6855.73765, + "iscrowd": 0, + "keypoints": [ + 167, + 60, + 2, + 169, + 54, + 2, + 163, + 54, + 2, + 0, + 0, + 0, + 151, + 54, + 2, + 160, + 93, + 2, + 145, + 94, + 2, + 0, + 0, + 0, + 153, + 116, + 2, + 0, + 0, + 0, + 176, + 138, + 2, + 157, + 149, + 2, + 147, + 151, + 2, + 153, + 194, + 1, + 151, + 206, + 2, + 143, + 235, + 2, + 155, + 257, + 2 + ], + "image_id": 292456, + "bbox": [ + 129.91, + 31.93, + 60.35, + 238.33 + ], + "category_id": 1, + "id": 216341, + "face_box": [ + 155.3, + 51.49, + 17.569999999999993, + 20.440000000000005 + ], + "lefthand_box": [ + 0.0, + 0.0, + 0.0, + 0.0 + ], + "righthand_box": [ + 176.35, + 138.34, + 12.870000000000005, + 19.210000000000008 + ], + "lefthand_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "righthand_kpts": [ + 180.0, + 141.0, + 0.10326574742794037, + 183.5, + 144.0, + 0.07696976512670517, + 187.0, + 147.0, + 0.07696976512670517, + 188.0, + 149.0, + 0.04711573198437691, + 191.0, + 155.0, + 0.07077035307884216, + 186.0, + 149.0, + 0.29661688208580017, + 186.0, + 153.0, + 0.24504776298999786, + 187.0, + 154.0, + 0.27228468656539917, + 187.0, + 156.0, + 0.4332796335220337, + 183.0, + 149.0, + 0.3887251019477844, + 184.0, + 153.0, + 0.2849636673927307, + 184.0, + 155.0, + 0.25188443064689636, + 185.0, + 157.0, + 0.22013618052005768, + 181.0, + 149.0, + 0.26592785120010376, + 181.0, + 152.0, + 0.334407240152359, + 181.0, + 155.0, + 0.3411094844341278, + 182.0, + 156.0, + 0.21506451070308685, + 178.0, + 150.0, + 0.1895236074924469, + 179.0, + 152.0, + 0.22152823209762573, + 179.0, + 153.0, + 0.24057771265506744, + 179.0, + 155.0, + 0.3196240961551666 + ], + "face_kpts": [ + 153.685, + 53.5251, + 1.0, + 153.685, + 55.9995, + 1.0, + 153.804, + 58.4704, + 1.0, + 154.134, + 60.9212, + 1.0, + 154.957, + 63.2463, + 1.0, + 156.253, + 65.3459, + 1.0, + 157.915, + 67.1762, + 1.0, + 159.836, + 68.7344, + 1.0, + 161.981, + 69.9598, + 1.0, + 164.351, + 70.6189, + 1.0, + 166.61, + 69.8115, + 1.0, + 167.696, + 67.6045, + 1.0, + 168.698, + 65.3436, + 1.0, + 169.518, + 63.0107, + 1.0, + 170.223, + 60.6411, + 1.0, + 170.512, + 58.1862, + 1.0, + 170.86, + 55.7391, + 1.0, + 161.251, + 53.1078, + 1.0, + 162.566, + 52.687, + 1.0, + 163.888, + 52.5886, + 1.0, + 165.174, + 52.6945, + 1.0, + 166.412, + 52.9976, + 1.0, + 169.073, + 53.6941, + 1.0, + 169.62, + 53.6665, + 1.0, + 170.131, + 53.6955, + 1.0, + 170.627, + 53.7716, + 1.0, + 171.084, + 54.1277, + 1.0, + 167.945, + 55.3813, + 1.0, + 168.385, + 57.2486, + 1.0, + 168.792, + 59.0841, + 1.0, + 169.156, + 60.9188, + 1.0, + 165.611, + 61.6406, + 1.0, + 166.592, + 62.0987, + 1.0, + 167.667, + 62.4634, + 1.0, + 168.508, + 62.5478, + 1.0, + 169.288, + 62.1283, + 1.0, + 162.091, + 54.5984, + 1.0, + 163.22, + 53.9983, + 1.0, + 164.482, + 54.0386, + 1.0, + 165.15, + 55.0692, + 1.0, + 164.097, + 55.3072, + 1.0, + 163.04, + 55.1084, + 1.0, + 168.609, + 55.7261, + 1.0, + 169.207, + 55.083, + 1.0, + 170.057, + 55.1597, + 1.0, + 170.369, + 55.961, + 1.0, + 169.776, + 56.2287, + 1.0, + 169.141, + 56.1008, + 1.0, + 162.475, + 63.8369, + 1.0, + 164.48, + 63.848, + 1.0, + 166.47, + 64.0609, + 1.0, + 167.089, + 64.2488, + 1.0, + 167.527, + 64.4092, + 1.0, + 167.957, + 64.8118, + 1.0, + 168.079, + 65.2803, + 1.0, + 167.681, + 65.6566, + 1.0, + 167.16, + 65.9072, + 1.0, + 166.491, + 65.9737, + 1.0, + 165.017, + 65.529, + 1.0, + 163.655, + 64.8154, + 1.0, + 162.759, + 63.9383, + 1.0, + 164.797, + 64.4124, + 1.0, + 166.767, + 64.9156, + 1.0, + 167.323, + 65.1626, + 1.0, + 167.909, + 65.2694, + 1.0, + 167.288, + 65.157, + 1.0, + 166.65, + 64.9973, + 1.0, + 164.709, + 64.5693, + 1.0 + ], + "face_valid": true, + "lefthand_valid": false, + "righthand_valid": true, + "foot_valid": true, + "foot_kpts": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 137.68845, + 238.83224, + 2.0, + 169.43431, + 265.41017, + 2.0, + 164.26638, + 267.99414, + 2.0, + 149.87, + 259.50397, + 2.0 + ] + } + ], + "categories": [ + { + "supercategory": "person", + "id": 1, + "name": "person", + "keypoints": [ + "nose", + "left_eye", + "right_eye", + "left_ear", + "right_ear", + "left_shoulder", + "right_shoulder", + "left_elbow", + "right_elbow", + "left_wrist", + "right_wrist", + "left_hip", + "right_hip", + "left_knee", + "right_knee", + "left_ankle", + "right_ankle" + ], + "skeleton": [ + [ + 16, + 14 + ], + [ + 14, + 12 + ], + [ + 17, + 15 + ], + [ + 15, + 13 + ], + [ + 12, + 13 + ], + [ + 6, + 12 + ], + [ + 7, + 13 + ], + [ + 6, + 7 + ], + [ + 6, + 8 + ], + [ + 7, + 9 + ], + [ + 8, + 10 + ], + [ + 9, + 11 + ], + [ + 2, + 3 + ], + [ + 1, + 2 + ], + [ + 1, + 3 + ], + [ + 2, + 4 + ], + [ + 3, + 5 + ], + [ + 4, + 6 + ], + [ + 5, + 7 + ] + ] + } + ] +} diff --git a/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000292456.jpg b/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000292456.jpg new file mode 100644 index 00000000..3852de57 --- /dev/null +++ b/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000292456.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c8207a06044306b0d271488a22e1a174af5a22e951a710e25a556cf5d212d5c +size 160632 diff --git a/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000425226.jpg b/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000425226.jpg new file mode 100644 index 00000000..0b6a0537 --- /dev/null +++ b/data/test/pose/hand/small_whole_body_hand_coco/train2017/000000425226.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:feadc69a8190787088fda0ac12971d91badc93dbe06057645050fdbec1ce6911 +size 204232 diff --git a/easycv/core/evaluation/__init__.py b/easycv/core/evaluation/__init__.py index 3c5f8c2d..d7eecfe4 100644 --- a/easycv/core/evaluation/__init__.py +++ b/easycv/core/evaluation/__init__.py @@ -4,8 +4,10 @@ from .base_evaluator import Evaluator from .classification_eval import ClsEvaluator from .coco_evaluation import CocoDetectionEvaluator, CoCoPoseTopDownEvaluator from .faceid_pair_eval import FaceIDPairEvaluator +from .keypoint_eval import KeyPointEvaluator from .mse_eval import MSEEvaluator from .retrival_topk_eval import RetrivalTopKEvaluator from .segmentation_eval import SegmentationEvaluator -from .top_down_eval import (keypoint_pck_accuracy, keypoints_from_heatmaps, +from .top_down_eval import (keypoint_auc, keypoint_epe, keypoint_nme, + keypoint_pck_accuracy, keypoints_from_heatmaps, pose_pck_accuracy) diff --git a/easycv/core/evaluation/keypoint_eval.py b/easycv/core/evaluation/keypoint_eval.py new file mode 100644 index 00000000..0549a71f --- /dev/null +++ b/easycv/core/evaluation/keypoint_eval.py @@ -0,0 +1,123 @@ +# Copyright (c) OpenMMLab. All rights reserved. +# Adapt from +# https://github.com/open-mmlab/mmpose/blob/master/mmpose/datasets/datasets/base/kpt_2d_sview_rgb_img_top_down_dataset.py +import numpy as np + +from .base_evaluator import Evaluator +from .builder import EVALUATORS +from .metric_registry import METRICS +from .top_down_eval import (keypoint_auc, keypoint_epe, keypoint_nme, + keypoint_pck_accuracy) + + +@EVALUATORS.register_module +class KeyPointEvaluator(Evaluator): + """ KeyPoint evaluator. + """ + + def __init__(self, + dataset_name=None, + metric_names=['PCK', 'PCKh', 'AUC', 'EPE', 'NME'], + pck_thr=0.2, + pckh_thr=0.7, + auc_nor=30): + """ + + Args: + dataset_name: eval dataset name + metric_names: eval metrics name + pck_thr (float): PCK threshold, default as 0.2. + pckh_thr (float): PCKh threshold, default as 0.7. + auc_nor (float): AUC normalization factor, default as 30 pixel. + """ + super(KeyPointEvaluator, self).__init__(dataset_name, metric_names) + self._pck_thr = pck_thr + self._pckh_thr = pckh_thr + self._auc_nor = auc_nor + self.dataset_name = dataset_name + allowed_metrics = ['PCK', 'PCKh', 'AUC', 'EPE', 'NME'] + for metric in metric_names: + if metric not in allowed_metrics: + raise KeyError(f'metric {metric} is not supported') + + def _evaluate_impl(self, preds, coco_db, **kwargs): + ''' keypoint evaluation code which will be run after + all test batched data are predicted + + Args: + preds: dict with key ``keypoints`` whose shape is Nx3 + coco_db: the db of wholebody coco datasource, sorted by 'bbox_id' + + Return: + a dict, each key is metric_name, value is metric value + ''' + assert len(preds) == len(coco_db) + eval_res = {} + + outputs = [] + gts = [] + masks = [] + box_sizes = [] + threshold_bbox = [] + threshold_head_box = [] + + for pred, item in zip(preds, coco_db): + outputs.append(np.array(pred['keypoints'])[:, :-1]) + gts.append(np.array(item['joints_3d'])[:, :-1]) + masks.append((np.array(item['joints_3d_visible'])[:, 0]) > 0) + if 'PCK' in self.metric_names: + bbox = np.array(item['bbox']) + bbox_thr = np.max(bbox[2:]) + threshold_bbox.append(np.array([bbox_thr, bbox_thr])) + if 'PCKh' in self.metric_names: + head_box_thr = item['head_size'] + threshold_head_box.append( + np.array([head_box_thr, head_box_thr])) + box_sizes.append(item.get('box_size', 1)) + + outputs = np.array(outputs) + gts = np.array(gts) + masks = np.array(masks) + threshold_bbox = np.array(threshold_bbox) + threshold_head_box = np.array(threshold_head_box) + box_sizes = np.array(box_sizes).reshape([-1, 1]) + + if 'PCK' in self.metric_names: + _, pck, _ = keypoint_pck_accuracy(outputs, gts, masks, + self._pck_thr, threshold_bbox) + eval_res['PCK'] = pck + + if 'PCKh' in self.metric_names: + _, pckh, _ = keypoint_pck_accuracy(outputs, gts, masks, + self._pckh_thr, + threshold_head_box) + eval_res['PCKh'] = pckh + + if 'AUC' in self.metric_names: + eval_res['AUC'] = keypoint_auc(outputs, gts, masks, self._auc_nor) + + if 'EPE' in self.metric_names: + eval_res['EPE'] = keypoint_epe(outputs, gts, masks) + + if 'NME' in self.metric_names: + normalize_factor = self._get_normalize_factor( + gts=gts, box_sizes=box_sizes) + eval_res['NME'] = keypoint_nme(outputs, gts, masks, + normalize_factor) + return eval_res + + def _get_normalize_factor(self, gts, *args, **kwargs): + """Get the normalize factor. generally inter-ocular distance measured + as the Euclidean distance between the outer corners of the eyes is + used. This function should be overrode, to measure NME. + + Args: + gts (np.ndarray[N, K, 2]): Groundtruth keypoint location. + + Returns: + np.ndarray[N, 2]: normalized factor + """ + return np.ones([gts.shape[0], 2], dtype=np.float32) + + +METRICS.register_default_best_metric(KeyPointEvaluator, 'PCK', 'max') diff --git a/easycv/core/evaluation/top_down_eval.py b/easycv/core/evaluation/top_down_eval.py index 0659a0de..ebb505e8 100644 --- a/easycv/core/evaluation/top_down_eval.py +++ b/easycv/core/evaluation/top_down_eval.py @@ -178,6 +178,86 @@ def keypoint_pck_accuracy(pred, gt, mask, thr, normalize): return acc, avg_acc, cnt +def keypoint_auc(pred, gt, mask, normalize, num_step=20): + """Calculate the pose accuracy of PCK for each individual keypoint and the + averaged accuracy across all keypoints for coordinates. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + normalize (float): Normalization factor. + + Returns: + float: Area under curve. + """ + nor = np.tile(np.array([[normalize, normalize]]), (pred.shape[0], 1)) + x = [1.0 * i / num_step for i in range(num_step)] + y = [] + for thr in x: + _, avg_acc, _ = keypoint_pck_accuracy(pred, gt, mask, thr, nor) + y.append(avg_acc) + + auc = 0 + for i in range(num_step): + auc += 1.0 / num_step * y[i] + return auc + + +def keypoint_nme(pred, gt, mask, normalize_factor): + """Calculate the normalized mean error (NME). + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + normalize_factor (np.ndarray[N, 2]): Normalization factor. + + Returns: + float: normalized mean error + """ + distances = _calc_distances(pred, gt, mask, normalize_factor) + distance_valid = distances[distances != -1] + return distance_valid.sum() / max(1, len(distance_valid)) + + +def keypoint_epe(pred, gt, mask): + """Calculate the end-point error. + + Note: + - batch_size: N + - num_keypoints: K + + Args: + pred (np.ndarray[N, K, 2]): Predicted keypoint location. + gt (np.ndarray[N, K, 2]): Groundtruth keypoint location. + mask (np.ndarray[N, K]): Visibility of the target. False for invisible + joints, and True for visible. Invisible joints will be ignored for + accuracy calculation. + + Returns: + float: Average end-point error. + """ + + distances = _calc_distances( + pred, gt, mask, + np.ones((pred.shape[0], pred.shape[2]), dtype=np.float32)) + distance_valid = distances[distances != -1] + return distance_valid.sum() / max(1, len(distance_valid)) + + def _taylor(heatmap, coord): """Distribution aware coordinate decoding method. diff --git a/easycv/core/post_processing/pose_transforms.py b/easycv/core/post_processing/pose_transforms.py index 312aa904..23bf3470 100644 --- a/easycv/core/post_processing/pose_transforms.py +++ b/easycv/core/post_processing/pose_transforms.py @@ -83,7 +83,7 @@ def fliplr_regression(regression, allowed_center_mode = {'static', 'root'} assert center_mode in allowed_center_mode, 'Get invalid center_mode ' \ - f'{center_mode}, allowed choices are {allowed_center_mode}' + f'{center_mode}, allowed choices are {allowed_center_mode}' if center_mode == 'static': x_c = center_x diff --git a/easycv/datasets/pose/__init__.py b/easycv/datasets/pose/__init__.py index c56c8f13..06118419 100644 --- a/easycv/datasets/pose/__init__.py +++ b/easycv/datasets/pose/__init__.py @@ -1,6 +1,7 @@ # Copyright (c) Alibaba, Inc. and its affiliates. from . import data_sources # pylint: disable=unused-import from . import pipelines # pylint: disable=unused-import +from .hand_coco_wholebody_dataset import HandCocoWholeBodyDataset from .top_down import PoseTopDownDataset -__all__ = ['PoseTopDownDataset'] +__all__ = ['PoseTopDownDataset', 'HandCocoWholeBodyDataset'] diff --git a/easycv/datasets/pose/data_sources/__init__.py b/easycv/datasets/pose/data_sources/__init__.py index 5d240fa2..b153c7a8 100644 --- a/easycv/datasets/pose/data_sources/__init__.py +++ b/easycv/datasets/pose/data_sources/__init__.py @@ -1,5 +1,8 @@ # Copyright (c) Alibaba, Inc. and its affiliates. from .coco import PoseTopDownSourceCoco +from .hand import HandCocoPoseTopDownSource from .top_down import PoseTopDownSource -__all__ = ['PoseTopDownSourceCoco', 'PoseTopDownSource'] +__all__ = [ + 'PoseTopDownSourceCoco', 'PoseTopDownSource', 'HandCocoPoseTopDownSource' +] diff --git a/easycv/datasets/pose/data_sources/hand/__init__.py b/easycv/datasets/pose/data_sources/hand/__init__.py new file mode 100644 index 00000000..146a1276 --- /dev/null +++ b/easycv/datasets/pose/data_sources/hand/__init__.py @@ -0,0 +1,3 @@ +# !/usr/bin/env python +# -*- encoding: utf-8 -*- +from .coco_hand import HandCocoPoseTopDownSource diff --git a/easycv/datasets/pose/data_sources/hand/coco_hand.py b/easycv/datasets/pose/data_sources/hand/coco_hand.py new file mode 100644 index 00000000..4cff9cfd --- /dev/null +++ b/easycv/datasets/pose/data_sources/hand/coco_hand.py @@ -0,0 +1,276 @@ +# Copyright (c) OpenMMLab. All rights reserved. +# Adapt from +# https://github.com/open-mmlab/mmpose/blob/master/mmpose/datasets/datasets/hand/hand_coco_wholebody_dataset.py +import logging +import os.path as osp + +import numpy as np + +from easycv.datasets.registry import DATASOURCES +from ..top_down import PoseTopDownSource + +COCO_WHOLEBODY_HAND_DATASET_INFO = dict( + dataset_name='coco_wholebody_hand', + paper_info=dict( + author='Jin, Sheng and Xu, Lumin and Xu, Jin and ' + 'Wang, Can and Liu, Wentao and ' + 'Qian, Chen and Ouyang, Wanli and Luo, Ping', + title='Whole-Body Human Pose Estimation in the Wild', + container='Proceedings of the European ' + 'Conference on Computer Vision (ECCV)', + year='2020', + homepage='https://github.com/jin-s13/COCO-WholeBody/', + ), + keypoint_info={ + 0: + dict(name='wrist', id=0, color=[255, 255, 255], type='', swap=''), + 1: + dict(name='thumb1', id=1, color=[255, 128, 0], type='', swap=''), + 2: + dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''), + 3: + dict(name='thumb3', id=3, color=[255, 128, 0], type='', swap=''), + 4: + dict(name='thumb4', id=4, color=[255, 128, 0], type='', swap=''), + 5: + dict( + name='forefinger1', id=5, color=[255, 153, 255], type='', swap=''), + 6: + dict( + name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''), + 7: + dict( + name='forefinger3', id=7, color=[255, 153, 255], type='', swap=''), + 8: + dict( + name='forefinger4', id=8, color=[255, 153, 255], type='', swap=''), + 9: + dict( + name='middle_finger1', + id=9, + color=[102, 178, 255], + type='', + swap=''), + 10: + dict( + name='middle_finger2', + id=10, + color=[102, 178, 255], + type='', + swap=''), + 11: + dict( + name='middle_finger3', + id=11, + color=[102, 178, 255], + type='', + swap=''), + 12: + dict( + name='middle_finger4', + id=12, + color=[102, 178, 255], + type='', + swap=''), + 13: + dict( + name='ring_finger1', id=13, color=[255, 51, 51], type='', swap=''), + 14: + dict( + name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''), + 15: + dict( + name='ring_finger3', id=15, color=[255, 51, 51], type='', swap=''), + 16: + dict( + name='ring_finger4', id=16, color=[255, 51, 51], type='', swap=''), + 17: + dict(name='pinky_finger1', id=17, color=[0, 255, 0], type='', swap=''), + 18: + dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''), + 19: + dict(name='pinky_finger3', id=19, color=[0, 255, 0], type='', swap=''), + 20: + dict(name='pinky_finger4', id=20, color=[0, 255, 0], type='', swap='') + }, + skeleton_info={ + 0: + dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]), + 1: + dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]), + 2: + dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]), + 3: + dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]), + 4: + dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]), + 5: + dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]), + 6: + dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]), + 7: + dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]), + 8: + dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]), + 9: + dict( + link=('middle_finger1', 'middle_finger2'), + id=9, + color=[102, 178, 255]), + 10: + dict( + link=('middle_finger2', 'middle_finger3'), + id=10, + color=[102, 178, 255]), + 11: + dict( + link=('middle_finger3', 'middle_finger4'), + id=11, + color=[102, 178, 255]), + 12: + dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]), + 13: + dict( + link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]), + 14: + dict( + link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]), + 15: + dict( + link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]), + 16: + dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]), + 17: + dict( + link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]), + 18: + dict( + link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]), + 19: + dict( + link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0]) + }, + joint_weights=[1.] * 21, + sigmas=[ + 0.029, 0.022, 0.035, 0.037, 0.047, 0.026, 0.025, 0.024, 0.035, 0.018, + 0.024, 0.022, 0.026, 0.017, 0.021, 0.021, 0.032, 0.02, 0.019, 0.022, + 0.031 + ]) + + +@DATASOURCES.register_module() +class HandCocoPoseTopDownSource(PoseTopDownSource): + """Coco Whole-Body-Hand Source for top-down hand pose estimation. + + "Whole-Body Human Pose Estimation in the Wild", ECCV'2020. + More details can be found in the `paper + `__ . + + The dataset loads raw features and apply specified transforms + to return a dict containing the image tensors and other information. + + COCO-WholeBody Hand keypoint indexes:: + + 0: 'wrist', + 1: 'thumb1', + 2: 'thumb2', + 3: 'thumb3', + 4: 'thumb4', + 5: 'forefinger1', + 6: 'forefinger2', + 7: 'forefinger3', + 8: 'forefinger4', + 9: 'middle_finger1', + 10: 'middle_finger2', + 11: 'middle_finger3', + 12: 'middle_finger4', + 13: 'ring_finger1', + 14: 'ring_finger2', + 15: 'ring_finger3', + 16: 'ring_finger4', + 17: 'pinky_finger1', + 18: 'pinky_finger2', + 19: 'pinky_finger3', + 20: 'pinky_finger4' + + Args: + ann_file (str): Path to the annotation file. + img_prefix (str): Path to a directory where images are held. + Default: None. + data_cfg (dict): config + dataset_info (DatasetInfo): A class containing all dataset info. + test_mode (bool): Store True when building test or + validation dataset. Default: False. + """ + + def __init__(self, + ann_file, + img_prefix, + data_cfg, + dataset_info=None, + test_mode=False): + + if dataset_info is None: + logging.info( + 'dataset_info is missing, use default coco wholebody hand dataset info' + ) + dataset_info = COCO_WHOLEBODY_HAND_DATASET_INFO + + super().__init__( + ann_file, + img_prefix, + data_cfg, + dataset_info=dataset_info, + test_mode=test_mode) + + self.ann_info['use_different_joint_weights'] = False + self.db = self._get_db() + + print(f'=> num_images: {self.num_images}') + print(f'=> load {len(self.db)} samples') + + def _get_db(self): + """Load dataset.""" + gt_db = [] + bbox_id = 0 + num_joints = self.ann_info['num_joints'] + for img_id in self.img_ids: + + ann_ids = self.coco.getAnnIds(imgIds=img_id, iscrowd=False) + objs = self.coco.loadAnns(ann_ids) + + for obj in objs: + for type in ['left', 'right']: + if obj[f'{type}hand_valid'] and max( + obj[f'{type}hand_kpts']) > 0: + joints_3d = np.zeros((num_joints, 3), dtype=np.float32) + joints_3d_visible = np.zeros((num_joints, 3), + dtype=np.float32) + + keypoints = np.array(obj[f'{type}hand_kpts']).reshape( + -1, 3) + joints_3d[:, :2] = keypoints[:, :2] + joints_3d_visible[:, :2] = np.minimum( + 1, keypoints[:, 2:3]) + + image_file = osp.join(self.img_prefix, + self.id2name[img_id]) + center, scale = self._xywh2cs( + *obj[f'{type}hand_box'][:4]) + gt_db.append({ + 'image_file': image_file, + 'image_id': img_id, + 'rotation': 0, + 'center': center, + 'scale': scale, + 'joints_3d': joints_3d, + 'joints_3d_visible': joints_3d_visible, + 'dataset': self.dataset_name, + 'bbox': obj[f'{type}hand_box'], + 'bbox_score': 1, + 'bbox_id': bbox_id + }) + bbox_id = bbox_id + 1 + gt_db = sorted(gt_db, key=lambda x: x['bbox_id']) + + return gt_db diff --git a/easycv/datasets/pose/hand_coco_wholebody_dataset.py b/easycv/datasets/pose/hand_coco_wholebody_dataset.py new file mode 100644 index 00000000..5725aff1 --- /dev/null +++ b/easycv/datasets/pose/hand_coco_wholebody_dataset.py @@ -0,0 +1,70 @@ +# Copyright (c) OpenMMLab. All rights reserved. +# Adapt from +# https://github.com/open-mmlab/mmpose/blob/master/mmpose/datasets/datasets/hand/hand_coco_wholebody_dataset.py + +from easycv.core.evaluation.keypoint_eval import KeyPointEvaluator +from easycv.datasets.pose.data_sources.coco import PoseTopDownSource +from easycv.datasets.registry import DATASETS +from easycv.datasets.shared.base import BaseDataset + + +@DATASETS.register_module() +class HandCocoWholeBodyDataset(BaseDataset): + """CocoWholeBodyDataset for top-down hand pose estimation. + + Args: + data_source: Data_source config dict + pipeline: Pipeline config list + profiling: If set True, will print pipeline time + """ + + def __init__(self, data_source, pipeline, profiling=False): + super(HandCocoWholeBodyDataset, self).__init__(data_source, pipeline, + profiling) + + if not isinstance(self.data_source, PoseTopDownSource): + raise ValueError('Only support `PoseTopDownSource`, but get %s' % + self.data_source) + + def evaluate(self, outputs, evaluators, **kwargs): + if len(evaluators) > 1 or not isinstance(evaluators[0], + KeyPointEvaluator): + raise ValueError( + 'HandCocoWholeBodyDataset only support one `KeyPointEvaluator` now, ' + 'but get %s' % evaluators) + evaluator = evaluators[0] + + image_ids = outputs['image_ids'] + preds = outputs['preds'] + boxes = outputs['boxes'] + bbox_ids = outputs['bbox_ids'] + + kpts = [] + for i, image_id in enumerate(image_ids): + kpts.append({ + 'keypoints': preds[i], + 'center': boxes[i][0:2], + 'scale': boxes[i][2:4], + 'area': boxes[i][4], + 'score': boxes[i][5], + 'image_id': image_id, + 'bbox_id': bbox_ids[i] + }) + kpts = self._sort_and_unique_bboxes(kpts) + eval_res = evaluator.evaluate(kpts, self.data_source.db) + return eval_res + + def _sort_and_unique_bboxes(self, kpts, key='bbox_id'): + """sort kpts and remove the repeated ones.""" + kpts = sorted(kpts, key=lambda x: x[key]) + num = len(kpts) + for i in range(num - 1, 0, -1): + if kpts[i][key] == kpts[i - 1][key]: + del kpts[i] + + return kpts + + def __getitem__(self, idx): + """Get the sample given index.""" + results = self.data_source.get_sample(idx) + return self.pipeline(results) diff --git a/easycv/datasets/pose/pipelines/transforms.py b/easycv/datasets/pose/pipelines/transforms.py index 79f8d6c4..27c7c325 100644 --- a/easycv/datasets/pose/pipelines/transforms.py +++ b/easycv/datasets/pose/pipelines/transforms.py @@ -1,9 +1,9 @@ # Copyright (c) OpenMMLab. All rights reserved. # Adapt from https://github.com/open-mmlab/mmpose/blob/master/mmpose/datasets/pipelines/top_down_transform.py + import cv2 import numpy as np from mmcv.parallel import DataContainer as DC -from torchvision.transforms import functional as F from easycv.core.post_processing import (affine_transform, fliplr_joints, get_affine_transform, get_warp_matrix, diff --git a/tests/core/evaluation/test_keypoint_eval.py b/tests/core/evaluation/test_keypoint_eval.py new file mode 100644 index 00000000..4a5d0216 --- /dev/null +++ b/tests/core/evaluation/test_keypoint_eval.py @@ -0,0 +1,51 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import unittest + +import numpy as np + +from easycv.core.evaluation import KeyPointEvaluator + + +class KeyPointEvaluatorTest(unittest.TestCase): + + def setUp(self): + print(('Testing %s.%s' % (type(self).__name__, self._testMethodName))) + + def test_keypoint_evaluator_pck(self): + evaluator = KeyPointEvaluator(pck_thr=0.5, pckh_thr=0.5, auc_nor=30) + output = np.zeros((5, 3)) + target = np.zeros((5, 3)) + mask = np.zeros((5, 3)) + mask[:, :2] = 1 + # first channel + output[0] = [10, 0, 0] + target[0] = [10, 0, 0] + # second channel + output[1] = [20, 20, 0] + target[1] = [10, 10, 0] + # third channel + output[2] = [0, 0, 0] + target[2] = [-1, 0, 0] + # fourth channel + output[3] = [30, 30, 0] + target[3] = [30, 30, 0] + # fifth channel + output[4] = [0, 10, 0] + target[4] = [0, 10, 0] + preds = {'keypoints': output} + db = { + 'joints_3d': target, + 'joints_3d_visible': mask, + 'bbox': [10, 10, 10, 10], + 'head_size': 10 + } + eval_res = evaluator.evaluate([preds, preds], [db, db]) + self.assertAlmostEqual(eval_res['PCK'], 0.8) + self.assertAlmostEqual(eval_res['PCKh'], 0.8) + self.assertAlmostEqual(eval_res['EPE'], 3.0284271240234375) + self.assertAlmostEqual(eval_res['AUC'], 0.86) + self.assertAlmostEqual(eval_res['NME'], 3.0284271240234375) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/datasets/pose/data_sources/test_coco_hand.py b/tests/datasets/pose/data_sources/test_coco_hand.py new file mode 100644 index 00000000..0338532e --- /dev/null +++ b/tests/datasets/pose/data_sources/test_coco_hand.py @@ -0,0 +1,59 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import random +import unittest + +import numpy as np +from tests.ut_config import SMALL_COCO_WHOLE_BODY_HAND_ROOT + +from easycv.datasets.pose.data_sources import HandCocoPoseTopDownSource + +_DATA_CFG = dict( + image_size=[256, 256], + heatmap_size=[64, 64], + num_output_channels=21, + num_joints=21, + dataset_channel=[list(range(21))], + inference_channel=list(range(21)), +) + + +class HandCocoPoseSourceCocoTest(unittest.TestCase): + + def setUp(self): + print(('Testing %s.%s' % (type(self).__name__, self._testMethodName))) + + def test_top_down_source_coco(self): + data_source = HandCocoPoseTopDownSource( + data_cfg=_DATA_CFG, + ann_file= + f'{SMALL_COCO_WHOLE_BODY_HAND_ROOT}/annotations/small_whole_body_hand_coco.json', + img_prefix=f'{SMALL_COCO_WHOLE_BODY_HAND_ROOT}/train2017/') + index_list = random.choices(list(range(4)), k=3) + for idx in index_list: + data = data_source.get_sample(idx) + self.assertIn('image_file', data) + self.assertIn('image_id', data) + self.assertIn('bbox_score', data) + self.assertIn('bbox_id', data) + self.assertIn('image_id', data) + self.assertEqual(data['center'].shape, (2, )) + self.assertEqual(data['scale'].shape, (2, )) + self.assertEqual(len(data['bbox']), 4) + self.assertEqual(data['joints_3d'].shape, (21, 3)) + self.assertEqual(data['joints_3d_visible'].shape, (21, 3)) + self.assertEqual(data['img'].shape[-1], 3) + ann_info = data['ann_info'] + self.assertEqual(ann_info['image_size'].all(), + np.array([256, 256]).all()) + self.assertEqual(ann_info['heatmap_size'].all(), + np.array([64, 64]).all()) + self.assertEqual(ann_info['num_joints'], 21) + self.assertEqual(len(ann_info['inference_channel']), 21) + self.assertEqual(ann_info['num_output_channels'], 21) + break + + self.assertEqual(len(data_source), 4) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/datasets/pose/test_coco_whole_body_hand_dataset.py b/tests/datasets/pose/test_coco_whole_body_hand_dataset.py new file mode 100644 index 00000000..6f7e3636 --- /dev/null +++ b/tests/datasets/pose/test_coco_whole_body_hand_dataset.py @@ -0,0 +1,75 @@ +# Copyright (c) Alibaba, Inc. and its affiliates. +import unittest + +import torch +from tests.ut_config import SMALL_COCO_WHOLE_BODY_HAND_ROOT + +from easycv.datasets.pose import HandCocoWholeBodyDataset + +_DATA_CFG = dict( + image_size=[256, 256], + heatmap_size=[64, 64], + num_output_channels=21, + num_joints=21, + dataset_channel=[list(range(21))], + inference_channel=list(range(21))) + +_DATASET_ARGS = [{ + 'data_source': + dict( + type='HandCocoPoseTopDownSource', + data_cfg=_DATA_CFG, + ann_file= + f'{SMALL_COCO_WHOLE_BODY_HAND_ROOT}/annotations/small_whole_body_hand_coco.json', + img_prefix=f'{SMALL_COCO_WHOLE_BODY_HAND_ROOT}/train2017/'), + 'pipeline': [ + dict(type='TopDownRandomFlip', flip_prob=0.5), + dict(type='TopDownAffine'), + dict(type='MMToTensor'), + dict(type='TopDownGenerateTarget', sigma=3), + dict( + type='PoseCollect', + keys=['img', 'target', 'target_weight'], + meta_keys=[ + 'image_file', 'joints_3d', 'flip_pairs', 'joints_3d_visible', + 'center', 'scale', 'rotation', 'bbox_score' + ]) + ] +}, {}] + + +class PoseTopDownDatasetTest(unittest.TestCase): + + def setUp(self): + print(('Testing %s.%s' % (type(self).__name__, self._testMethodName))) + + @staticmethod + def build_dataset(index): + dataset = HandCocoWholeBodyDataset( + data_source=_DATASET_ARGS[index].get('data_source', None), + pipeline=_DATASET_ARGS[index].get('pipeline', None)) + + return dataset + + def test_0(self, index=0): + dataset = self.build_dataset(index) + ann_info = dataset.data_source.ann_info + + self.assertEqual(len(dataset), 4) + for i, batch in enumerate(dataset): + self.assertEqual( + batch['img'].shape, + torch.Size([3] + list(ann_info['image_size'][::-1]))) + self.assertEqual(batch['target'].shape, + (ann_info['num_joints'], ) + + tuple(ann_info['heatmap_size'][::-1])) + self.assertEqual(batch['img_metas'].data['joints_3d'].shape, + (ann_info['num_joints'], 3)) + self.assertIn('center', batch['img_metas'].data) + self.assertIn('scale', batch['img_metas'].data) + + break + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/ut_config.py b/tests/ut_config.py index a492db0d..0366b9f9 100644 --- a/tests/ut_config.py +++ b/tests/ut_config.py @@ -118,3 +118,4 @@ PRETRAINED_MODEL_SEGFORMER = os.path.join( ) MODEL_CONFIG_SEGFORMER = ( './configs/segmentation/segformer/segformer_b0_coco.py') +SMALL_COCO_WHOLE_BODY_HAND_ROOT = 'data/test/pose/hand/small_whole_body_hand_coco'