-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] Add COCOPoseMetric #35
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update api docs && suport_matrix documentation.
BTW I was told this metric should be renamed as COCOKeyPointDetection
>>> try: | ||
... from xtcocotools.coco import COCO | ||
... from xtcocotools.cocoeval import COCOeval | ||
... HAS_XTCOCOTOOLS = True | ||
... except ImportError: | ||
... HAS_XTCOCOTOOLS = False | ||
... | ||
>>> ann_file = 'tests/test_metrics/data/coco_pose_sample.json' | ||
>>> coco = COCO(ann_file) | ||
loading annotations into memory... | ||
Done (t=0.00s) | ||
creating index... | ||
index created! | ||
>>> classes = coco.loadCats(coco.getCatIds()) | ||
>>> sigmas = np.array([ | ||
... 0.026, 0.025, 0.025, 0.035, 0.035, 0.079, 0.079, 0.072, 0.072, | ||
... 0.062, 0.062, 0.107, 0.107, 0.087, 0.087, 0.089, 0.089 | ||
... ]).astype(np.float32) | ||
>>> coco_dataset_meta = { | ||
... 'CLASSES': classes, | ||
... 'num_keypoints': 17, | ||
... 'sigmas': sigmas, | ||
... } | ||
>>> def _convert_ann_to_pred_and_gt(ann_file): | ||
... predictions = [] | ||
... groundtruths = [] | ||
... db = load(ann_file) | ||
... imgid2info = dict() | ||
... for img in db['images']: | ||
... imgid2info[img['id']] = img | ||
... for ann in db['annotations']: | ||
... bboxes = np.array(ann['bbox'], dtype=np.float32).reshape(-1, 4) | ||
... keypoints = np.array(ann['keypoints']).reshape((1, -1, 3)) | ||
... prediction = { | ||
... 'id': ann['id'], | ||
... 'img_id': ann['image_id'], | ||
... 'bboxes': bboxes, | ||
... 'keypoints': keypoints[..., :2], | ||
... 'keypoint_scores': keypoints[..., -1], | ||
... 'bbox_scores': np.ones((1, ), dtype=np.float32), | ||
... } | ||
... groundtruth = { | ||
... 'img_id': ann['image_id'], | ||
... 'width': 640, | ||
... 'height': 480, | ||
... 'num_keypoints': ann['num_keypoints'], | ||
... 'raw_ann_info': [copy.deepcopy(ann)], | ||
... } | ||
... if 'area' in ann: | ||
... groundtruth['area'] = ann['area'] | ||
... if 'crowdIndex' in imgid2info[ann['image_id']]: | ||
... groundtruth['crowd_index'] = imgid2info[ | ||
... ann['image_id']]['crowdIndex'] | ||
... predictions.append(prediction) | ||
... groundtruths.append(groundtruth) | ||
... return predictions, groundtruths | ||
>>> predictions, groundtruths = _convert_ann_to_pred_and_gt(ann_file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This example is too long and it doesn't give a clear input format. Should write a plain dict
as input.
>>> coco_pose_metric(predictions, groundtruths) | ||
loading annotations into memory... | ||
Done (t=0.00s) | ||
creating index... | ||
index created! | ||
>>> coco_pose_metric(predictions, groundtruths) | ||
Loading and preparing results... | ||
DONE (t=0.00s) | ||
creating index... | ||
index created! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are there 2 function calls?
>>> coco_pose_metric = CocoPoseMetric( | ||
... ann_file=ann_file, | ||
... dataset_meta=coco_dataset_meta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be 2 example codes to cover the use cases:
ann_file=None
, a simple__call__
methodann_file is not None
, calladd
andcompute
. Should illustrate whatgroundtruths
should be in this case.
self.format_only = format_only | ||
self.outfile_prefix = outfile_prefix | ||
|
||
def add(self, predictions: Sequence[Dict], groundtruths: Sequence[Dict]) -> None: # type: ignore # yapf: disable # noqa: E501 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about making groundtruths
defaults to None
so that it's easier to use this metric with ann_file
? Creating an 'empty' groundtruths
is ambiguous and inconvenient, since we require it has the same length as predictions
predictions (Sequence[dict]): A sequence of dict. Each dict | ||
representing a pose estimation result for an instance, with | ||
the following keys: | ||
- 'id'(int): The id of the instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 'id'(int): The id of the instance | |
- 'id' (int): The id of the instance |
|
||
info = dict( | ||
date_created=str(datetime.datetime.now()), | ||
description='Coco json file converted by mmpose CocoMetric.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
description='Coco json file converted by mmpose CocoMetric.') | |
description='Coco json file converted by mmeval CocoMetric.') |
instance['keypoints'] = np.concatenate([ | ||
instance['keypoints'], instance['keypoint_scores'][:, None] | ||
], | ||
axis=-1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indent is strange
>>> coco_pose_metric = CocoPoseMetric( | ||
... ann_file=ann_file, | ||
... dataset_meta=coco_dataset_meta) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If dataset_meta
is required in this metric, I think it should be explained in docstring
|
||
Args: | ||
kpts (Dict[int, list]): keypoint prediction results. The keys are | ||
'`img_id`' and the values are list that may contain |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'`img_id`' and the values are list that may contain | |
``'img_id'`` and the values are list that may contain |
# ------------------------------------------------------------------------------ | ||
# Adapted from https://github.com/leoxiaobin/deep-high-resolution-net.pytorch | ||
# Original licence: Copyright (c) Microsoft, under the MIT License. | ||
# ------------------------------------------------------------------------------ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this file should be moved to metrics/_vendor
? What do you think @zhouzaida
Close this because duplicated with #97 |
Motivation
Add
COCOPoseMetric
for pose estimation task.PR in mmpose: open-mmlab/mmpose#1777, about the results verification.
Modification
COCOPoseMetric
undermmeval/metrics/coco_pose.py
tests/test_metrics/data/coco_pose_sample.json
,tests/test_metrics/data/crowdpose_sample.json
,tests/test_metrics/data/ap10k_sample.json
and unittests.mmeval/metrics/utils/nms.py
BC-breaking (Optional)
Use cases (Optional)
Checklist