-
Notifications
You must be signed in to change notification settings - Fork 588
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
Add COCO-styled mAR to evaluate_detections #5274
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
db36821
Add COCO-styled mAR to evaluate_detections
manushreegangwar fcf4caf
Make recall_sweep optional
manushreegangwar 5e38914
add mAR to eval table
ritch 667984d
Fix line length
manushreegangwar 450d254
Update docs
manushreegangwar 770c7d6
lint
brimoor e94c8a0
include recall_sweep in serialization
brimoor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
| `voxel51.com <https://voxel51.com/>`_ | ||
| | ||
""" | ||
|
||
import logging | ||
from collections import defaultdict | ||
|
||
|
@@ -50,7 +51,7 @@ class COCOEvaluationConfig(DetectionEvaluationConfig): | |
tolerance (None): a tolerance, in pixels, when generating approximate | ||
polylines for instance masks. Typical values are 1-3 pixels | ||
compute_mAP (False): whether to perform the necessary computations so | ||
that mAP and PR curves can be generated | ||
that mAP, mAR, and PR curves can be generated | ||
iou_threshs (None): a list of IoU thresholds to use when computing mAP | ||
and PR curves. Only applicable when ``compute_mAP`` is True | ||
max_preds (None): the maximum number of predicted objects to evaluate | ||
|
@@ -218,6 +219,7 @@ def generate_results( | |
thresholds, | ||
iou_threshs, | ||
classes, | ||
recall_sweep, | ||
) = _compute_pr_curves( | ||
samples, self.config, classes=classes, progress=progress | ||
) | ||
|
@@ -231,6 +233,7 @@ def generate_results( | |
recall, | ||
iou_threshs, | ||
classes, | ||
recall_sweep=recall_sweep, | ||
thresholds=thresholds, | ||
missing=missing, | ||
backend=self, | ||
|
@@ -253,6 +256,8 @@ class COCODetectionResults(DetectionResults): | |
recall: an array of recall values | ||
iou_threshs: an array of IoU thresholds | ||
classes: the list of possible classes | ||
recall_sweep (None): an array of recall values of shape | ||
``num_iou x num_classes`` | ||
thresholds (None): an optional array of decision thresholds of shape | ||
``num_iou_threshs x num_classes x num_recall`` | ||
missing (None): a missing label string. Any unmatched objects are | ||
|
@@ -270,6 +275,7 @@ def __init__( | |
recall, | ||
iou_threshs, | ||
classes, | ||
recall_sweep=None, | ||
thresholds=None, | ||
missing=None, | ||
backend=None, | ||
|
@@ -287,11 +293,15 @@ def __init__( | |
self.precision = np.asarray(precision) | ||
self.recall = np.asarray(recall) | ||
self.iou_threshs = np.asarray(iou_threshs) | ||
self.recall_sweep = recall_sweep | ||
self.thresholds = ( | ||
np.asarray(thresholds) if thresholds is not None else None | ||
) | ||
|
||
self._classwise_AP = np.mean(precision, axis=(0, 2)) | ||
self._classwise_AR = ( | ||
np.mean(recall_sweep, axis=0) if recall_sweep is not None else None | ||
) | ||
|
||
def plot_pr_curves( | ||
self, classes=None, iou_thresh=None, backend="plotly", **kwargs | ||
|
@@ -376,6 +386,36 @@ def mAP(self, classes=None): | |
|
||
return np.mean(classwise_AP) | ||
|
||
def mAR(self, classes=None): | ||
"""Computes COCO-style mean average recall (mAR) for the specified | ||
classes. | ||
|
||
See `this page <https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py>`_ | ||
for more details about COCO-style mAR. | ||
|
||
Args: | ||
classes (None): a list of classes for which to compute mAR | ||
|
||
Returns: | ||
the mAR in ``[0, 1]`` | ||
""" | ||
if self._classwise_AR is None: | ||
raise Exception( | ||
"Classwise AR is not available. mAR can't be computed." | ||
) | ||
|
||
if classes is not None: | ||
class_inds = np.array([self._get_class_index(c) for c in classes]) | ||
classwise_AR = self._classwise_AR[class_inds] | ||
else: | ||
classwise_AR = self._classwise_AR | ||
|
||
classwise_AR = classwise_AR[classwise_AR > -1] | ||
if classwise_AR.size == 0: | ||
return -1 | ||
|
||
return np.mean(classwise_AR) | ||
|
||
def _get_iou_thresh_inds(self, iou_thresh=None): | ||
if iou_thresh is None: | ||
return np.arange(len(self.iou_threshs)) | ||
|
@@ -410,6 +450,7 @@ def _from_dict(cls, d, samples, config, eval_key, **kwargs): | |
precision = d["precision"] | ||
recall = d["recall"] | ||
iou_threshs = d["iou_threshs"] | ||
recall_sweep = d.get("recall_sweep", None) | ||
thresholds = d.get("thresholds", None) | ||
return super()._from_dict( | ||
d, | ||
|
@@ -419,6 +460,7 @@ def _from_dict(cls, d, samples, config, eval_key, **kwargs): | |
precision=precision, | ||
recall=recall, | ||
iou_threshs=iou_threshs, | ||
recall_sweep=recall_sweep, | ||
thresholds=thresholds, | ||
**kwargs, | ||
) | ||
|
@@ -713,6 +755,7 @@ def _compute_pr_curves(samples, config, classes=None, progress=None): | |
precision = -np.ones((num_threshs, num_classes, 101)) | ||
thresholds = -np.ones((num_threshs, num_classes, 101)) | ||
recall = np.linspace(0, 1, 101) | ||
recall_sweep = -np.ones((num_threshs, num_classes)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improve error handling in recall computation The bare except blocks should be replaced with specific exception handling to avoid masking unexpected errors. - try:
- for ri, pi in enumerate(inds):
- q[ri] = pre[pi]
- t[ri] = confs[pi]
- except:
- pass
+ try:
+ for ri, pi in enumerate(inds):
+ q[ri] = pre[pi]
+ t[ri] = confs[pi]
+ except IndexError as e:
+ logger.warning(f"Error computing precision values: {e}") Also applies to: 806-806, 808-808 |
||
for idx, _thresh_matches in enumerate(thresh_matches): | ||
for c, matches in _thresh_matches.items(): | ||
c_idx = class_idx_map.get(c, None) | ||
|
@@ -760,8 +803,9 @@ def _compute_pr_curves(samples, config, classes=None, progress=None): | |
|
||
precision[idx][c_idx] = q | ||
thresholds[idx][c_idx] = t | ||
recall_sweep[idx][c_idx] = rec[-1] | ||
|
||
return precision, recall, thresholds, iou_threshs, classes | ||
return precision, recall, thresholds, iou_threshs, classes, recall_sweep | ||
|
||
|
||
def _copy_labels(labels): | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Remove unused exception variable
Since “e” is never used, it is preferable to remove the variable name or handle it properly.
📝 Committable suggestion
🧰 Tools
🪛 Ruff (0.8.2)
140-140: Local variable
e
is assigned to but never usedRemove assignment to unused variable
e
(F841)