* make pixel and kernel size dynamic
* fix: zero-area guard and is-not-None check in Blur/PixelateAnnotator
- Skip loop iteration when clip_boxes produces x2<=x1 or y2<=y1 (zero-area ROI) to prevent cv2.error crash in both annotators
- Replace falsy `or` pattern with explicit `is not None` so kernel_size=0 / pixel_size=0 are not silently treated as dynamic
- Replace hardcoded `cv2.mean(roi)[:3]` with ndim-aware fill: scalar for grayscale, channel-matched tuple for colour images; avoids shape mismatch broadcast error on single-channel frames
- test_annotate_bbox_smaller_than_pixel_size_does_not_raise: guards against the OpenCV resize crash from issue #703 when bbox < pixel_size
- test_annotate_grayscale_image_does_not_raise: normal pixelation path on 2-D grayscale frame
- test_annotate_grayscale_image_small_roi_does_not_raise: avg-fill fallback on 2-D grayscale frame
- Add ValueError guard in BlurAnnotator.__init__ and PixelateAnnotator.__init__ for explicit sizes < 1; previously passed straight to cv2 causing ZeroDivisionError or OpenCV assertion failures
- Add parametrized tests for invalid sizes (0, -1, -10) and zero-area bbox skipping for both annotators
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
* fix: preserve area and iscrowd from detection data in COCO export
* fix: use np.asarray().item() to satisfy mypy in iscrowd/area extraction
* test: shorten test name to fix ruff E501 line-length violation
* test: verify data["area"] overrides bbox area when mask is present
* test: stricter iscrowd type check (bool subclass fix)
* test: stricter iscrowd type check in preserves_iscrowd_from_data
* test: stricter iscrowd type check in iscrowd_is_int_when_mask_provided
* fix: prefer data["iscrowd"] over geometry when mask is present
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
When a user's callback accidentally runs inference on the full image instead
of the provided slice, detections get incorrect offsets applied, causing a
repeating grid pattern. Add a validation check in _run_callback that emits a
SupervisionWarnings warning when any detection coordinate exceeds the slice
dimensions or is negative. An instance flag prevents repeated warnings across
many slices.
- Wrap _out_of_slice_bounds_warned check-and-set in threading.Lock to prevent duplicate warnings under ThreadPoolExecutor with thread_workers > 1
- Change stacklevel=2 to stacklevel=1 — under executor.submit the stacklevel=2 frame points into concurrent.futures internals, not user code
- Assert exactly 1 warning fires with thread_workers=4 (validates Lock fix)
- Assert no warning for detection touching but not exceeding slice boundary (pins > vs >= semantics)
- Assert second slicer call does not re-warn (documents once-per-instance semantic)
- Extract warning message into `msg` variable to satisfy E501 line-length limit
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Borda <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit adds support for 4-digit and 8-digit hexadecimal color codes
with alpha channel (e.g., #FF00FF80 for 50% transparent magenta).
Changes:
- Extended Color dataclass with optional alpha field (default 255)
- Updated _validate_color_hex to accept lengths 3, 4, 6, 8
- Updated from_hex to parse 4-digit (#RGBA) and 8-digit (#RRGGBBAA) hex codes
- Modified as_hex to return #RRGGBBAA when alpha != 255
- Added as_rgba() and as_bgra() methods
- Added from_rgba_tuple() and from_bgra_tuple() class methods
- Updated __eq__ and __hash__ to include alpha channel
- Added comprehensive unit tests for all RGBA functionality
- Updated docstrings with examples of new alpha channel support
---------
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: prevent single object from appearing in multiple polygon zones
when checking if a detection is inside a polygon zone, the previous implementation
would clip the bounding box to fit within each ROI's dimensions before calculating
anchor points. This caused the same detection to produce different anchor points
for different ROIs, allowing it to be counted as present in multiple zones.
* Add regression test for PolygonZone trigger issue #1987 and remove unused `frame_resolution_wh` attribute
* refactor(polygon_zone): vectorize trigger() and strengthen tests
Replace the O(n×m) Python double-loop in PolygonZone.trigger() with
vectorized NumPy. Semantics are identical: compute a (num_anchors,
num_detections) in_bounds mask, use np.clip solely for safe fancy-index
access, then AND with the polygon mask and reduce with np.all(axis=0).
Also removes the now-unused `from dataclasses import replace` import and
a latent np.all(axis=1) call on a 1D array.
Test improvements:
- Group into TestPolygonZoneInit / TestPolygonZoneTrigger classes
- Replace the trivially-passing regression (sum=0 on both old and new
code) with adjacent zones + straddling detection that gives sum=2 on
the old clip_boxes implementation and sum=1 on the fix
- Rename tests to describe behaviour, not issue numbers
- Add test_out_of_bounds_anchor_excluded and
test_anchor_on_polygon_boundary_included edge cases
* test(polygon_zone): verify current_count updates with expected results during trigger
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor docstrings in `scr/supervision/detection`
* Enhance docstrings across multiple modules: clarify attributes/args, improve formatting, and update logic for handling sentinel values in metrics calculation.
* Ensure consistent handling of `class_id` as integer across YOLO and Pascal VOC formats, fix NoneType handling in line zone logic, and add test coverage for multiclass annotator with None `class_id`.
* Enforce `class_id` as integer in YOLO export, update line zone class count docstrings, and add test for non-integer `class_id`.
* Apply suggestions from code review
---------
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* refactor docstrings in draw, classification, and key_points
* Refactor type annotations, logging, and empty output handling across key modules
* Refactor type annotations in `core.py` to include conditional `TYPE_CHECKING` for `torch` imports
* Apply suggestions from code review
---------
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
DetectionDataset.__init__ now maps class_id to class names using
CLASS_NAME_DATA_FIELD so that LabelAnnotator displays human-readable
labels instead of raw integer IDs.
---------
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
* Fix `detections_to_coco_annotations` function for empty polygons.
* Add `segmentation` empty field for bboxes coco format
* update coco.py
Always include box, area, and segmentation in the result COCO JSON.
* `as_coco()` : Add COCO format disjoint masks support
* Fix `force_masks` parameter on `from_coco()` function
Allows reconstruction of disjointed masks
* Ensures the mask is binary
* Refactor `coco_annotations_to_masks` to handle disjoint polygon segmentation and missing segmentation gracefully. Add corresponding unit tests.
* Refactor `coco_annotations_to_masks` for improved type annotations and cleaner formatting
* Add warnings for handling empty polygons during COCO segmentation and related unit tests
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix mask_annotate for int dtypes
* Add depreciation warning
* Add dtype=bool to test masks
* Remove ValueError (testing)
* Ensure boolean masks are consistently used in `Detections` and update validations, tests, and warnings for stricter type handling.
* Apply suggestions from code review
---------
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Added color utility functions: hex_to_rgba, rgba_to_hex, is_valid_hex with tests
* Parametrize hex and RGBA utility tests in `test_utils.py` for improved clarity and coverage
* Enhance hex and RGBA utilities: improve test coverage, validations, and docstrings; refactor shared logic.
* Refactor color input handling with `_normalize_color_input` utility; add hex string support across annotators and enhance test coverage
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
* make force_masks consistent with yolo and voc
* Refactor mask detection logic across dataset formats to improve consistency and clarity. Rename helper functions for better readability. Add parametrized test cases with descriptive IDs.
* Refactor PASCAL VOC and COCO mask handling to improve consistency, add tests for mixed annotations and mask inference logic.
* Apply suggestions from code review
---------
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* fix exteranl track ids getting assigned too early
* Fixed docstring to correct minimum_matching_threshold explaination
* Change overlap value for duplicate tracks to be 0.05
* Add test to ensure ByteTracker handles short-lived tracks without consuming external IDs
---------
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
* Add ImageAssets for download
* Update directory for consistency with video assets directory and add soccer image
* Fix unaligned table
* Add support for `ImageAssets` and extend `download_assets` functionality to handle both image and video assets.
* Refactor `Assets` enum initialization and improve `download_assets` logic with enhanced file checks and re-download handling. Add new tests for invalid asset cases and update existing test assertions.
* Simplify `download_assets` type handling and refactor `Assets` enum with additional attributes for filename and md5_hash.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Supersedes #1967
* fix: COCO-compliant mAR calculation
* Add complex test of mAP
* fix(metrics): cast optional detections fields in mAR metric for mypy
* Add `create_yolo_dataset` utility and refactor tests with fixtures for reusable scenarios
* Refine docstrings for clarity and consistency, adding inline formatting and fixing typos in test helpers and metrics.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
* Added support for creating Detections instances from SAM3 output - both from `inference` and from RF hosted server (dict)
* added tests, addressed pr comments
* fix(pre_commit): 🎨 auto format pre-commit hooks
* Apply suggestions from code review
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* fix: add validation for RGB/BGR color values in Color class
- Add range validation (0-255) to from_rgb_tuple() and from_bgr_tuple()
- Raise ValueError for invalid color values with descriptive messages
- Add comprehensive tests for both valid and invalid cases
- Update docstrings to document the new validation behavior
* fix(pre_commit): 🎨 auto format pre-commit hooks
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
* Extend docstrings to test cases for enhanced readability and consistency across testing modules
* Extend test case docstrings across multiple modules for improved clarity and consistency
* Refactor test case docstrings for clarity and consistency in `test_annotators.py`
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* refactor: reorganize project structure and update module imports
* configure setuptools to use 'src' layout and adjust package discovery
* refactor: move tests to `tests` directory and update imports accordingly
* update lint and mypy configurations to align with `src` and `tests` structure
* update test imports to use corrected `tests.helpers` module path
* fix(pre_commit): 🎨 auto format pre-commit hooks