Add BenchmarkEvaluator with basic precision/recall computation - #1870
Add BenchmarkEvaluator with basic precision/recall computation#1870Muhammedswalihu wants to merge 6 commits into
Conversation
|
Muhammed Swalihu seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
|
Hi @SkalskiP @onuralpszr — I've submitted this PR for the BenchmarkEvaluator (Issue #1778 ). Let me know if you'd like me to fix the |
|
Hi @Muhammedswalihu, this seems like a really valuable feature! |
|
Hi @soumik12345 , thanks for the review! I’ll go ahead and: Replace the placeholder logic in BenchmarkEvaluator with full precision/recall/mAP computation, Add a working demo example (maybe in a Colab notebook for clarity), and Improve the test coverage with more edge cases and per-class evaluation. Let me know if there’s anything specific you’d like to see included. Appreciate the opportunity — excited to take this further! |
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
|
Hi @soumik12345, I've added a Colab-style demo notebook BenchmarkEvaluator_Demo.ipynb! It includes:
This should help users understand and adopt the module more easily. Let me know if you'd like me to polish or extend this notebook further! |
soumik12345
left a comment
There was a problem hiding this comment.
Hi @Muhammedswalihu, thanks for providing the PoC!
Please feel free to proceed with the actual implementation.
Also, there's no need to commit the notebook to supervision, you can just attach a colab notebook in a comment when the PR is ready for review with the complete logic.
| # TODO: Add class alignment, matching using IoU | ||
| tp = len(self.predictions.xyxy) # Placeholder | ||
| fp = 0 | ||
| fn = len(self.ground_truth.xyxy) - tp |
There was a problem hiding this comment.
The logic here is incomplete, please add the correct logic to compute precision and recall.
| from supervision.metrics.benchmark import BenchmarkEvaluator | ||
|
|
||
|
|
||
| def test_basic_precision_recall(): |
There was a problem hiding this comment.
This too seems like a placeholder test; please proceed with the implementation and add comprehensive unit tests.
|
Great initiative on the BenchmarkEvaluator! This addresses a crucial need for standardized evaluation metrics. I'd like to offer some technical guidance to help you complete the implementation effectively. Key Implementation Recommendations:
Performance Considerations:
This evaluator will be invaluable for the community's benchmarking needs. Happy to provide more specific implementation details if needed! Best regards, |
There was a problem hiding this comment.
Pull request overview
This PR adds a new BenchmarkEvaluator utility intended to compute basic object-detection precision/recall for Detections pairs, alongside a small unit test and a demo notebook.
Changes:
- Introduces
BenchmarkEvaluatorwith acompute_precision_recall()API and asummary()helper. - Adds a unit test for the perfect-match case.
- Adds a Jupyter notebook demonstrating intended usage.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| supervision/metrics/benchmark.py | Adds BenchmarkEvaluator (currently placed outside the src/ package discovery root and includes placeholder metric logic). |
| tests/metrics/test_benchmark.py | Adds an initial unit test for precision/recall (currently too narrow to validate FP/FN, class mismatch, or IoU threshold behavior). |
| BenchmarkEvaluator_Demo.ipynb | Adds a demo notebook (currently calls a non-existent per-class method). |
Comments suppressed due to low confidence (1)
supervision/metrics/benchmark.py:40
summary()prints directly to stdout, which is an unexpected side effect for a library utility and makes the method hard to use in applications/tests. Prefer returning a string (or the metrics dict) and letting callers decide how to log/print it.
metrics = self.compute_precision_recall()
print("Benchmark Summary:")
for k, v in metrics.items():
print(f"{k}: {v:.4f}")
| # supervision/metrics/benchmark.py | ||
|
|
||
| from typing import Dict, Optional | ||
|
|
||
| from supervision.detection.core import Detections |
| def compute_precision_recall(self) -> Dict[str, float]: | ||
| """ | ||
| Compute basic precision and recall metrics. | ||
| For demo purposes — you will expand this. | ||
| """ | ||
| # TODO: Add class alignment, matching using IoU | ||
| tp = len(self.predictions.xyxy) # Placeholder | ||
| fp = 0 | ||
| fn = len(self.ground_truth.xyxy) - tp | ||
|
|
||
| precision = tp / (tp + fp) if (tp + fp) > 0 else 0 | ||
| recall = tp / (tp + fn) if (tp + fn) > 0 else 0 | ||
|
|
||
| return {"precision": precision, "recall": recall} |
| ground_truth: Detections, | ||
| predictions: Detections, | ||
| class_map: Optional[Dict[str, str]] = None, | ||
| iou_threshold: float = 0.5, | ||
| ): |
| import numpy as np | ||
|
|
||
| from supervision.detection.core import Detections | ||
| from supervision.metrics.benchmark import BenchmarkEvaluator | ||
|
|
||
|
|
||
| def test_basic_precision_recall(): | ||
| gt = Detections(xyxy=np.array([[0, 0, 100, 100]]), class_id=np.array([0])) | ||
| pred = Detections(xyxy=np.array([[0, 0, 100, 100]]), class_id=np.array([0])) | ||
|
|
||
| evaluator = BenchmarkEvaluator(ground_truth=gt, predictions=pred) | ||
| metrics = evaluator.compute_precision_recall() | ||
|
|
||
| assert metrics["precision"] == 1.0 | ||
| assert metrics["recall"] == 1.0 |
| "per_class = evaluator.compute_precision_recall_per_class()\n", | ||
| "for cls, metric in per_class.items():\n", | ||
| " print(\n", | ||
| " f\"Class {cls} - Precision: {metric['precision']:.2f}, Recall: {metric['recall']:.2f}\"\n", | ||
| " )" | ||
| ] |
Summary
This PR introduces a utility class
BenchmarkEvaluatorinsupervision/metrics/benchmark.pyto support benchmarking object detection results across different datasets or models.Features
Detectionsobjects for ground truth and predictiontests/metrics/test_benchmark.pyMotivation
Addresses Issue #1778: Improving object detection benchmarking process for unrelated datasets.
Let me know if you'd like me to extend this in future PRs with:
Thanks for the opportunity to contribute!