Commit Graph

4893 Commits

Author SHA1 Message Date
jirka ef8ba557a1 releasing `0.29.0.rc0` 2026-06-11 18:37:56 +02:00
Piotr Skalski caf060521d
refactor: enrich `KeyPoints` with visibility mask, split confidence fields, and redesign uncertainty annotator (#2286)
- Added `KeyPoints.visible` mask support for per-keypoint visibility
- Split confidence into `keypoint_confidence` and `detection_confidence`
- Kept legacy `KeyPoints.confidence` as deprecated forwarding alias
- Updated `KeyPoints` slicing/filtering to preserve visibility and confidence fields
- Fixed `KeyPoints.__getitem__` row-index normalization for NumPy scalar, 0-D array, and boolean indexing
- Fixed `detection_confidence` indexing to use normalized row indices
- Updated `VertexAnnotator` to skip invisible keypoints
- Updated `EdgeAnnotator` to skip invisible keypoints and edges
- Added per-class skeleton support to `EdgeAnnotator`
- Added multi-skeleton support to `VertexLabelAnnotator`
- Added label validation for `VertexLabelAnnotator`
- Added color-list length validation for keypoint annotators
- Added `VertexEllipseAreaAnnotator`
- Added `VertexEllipseOutlineAnnotator`
- Added `VertexEllipseHaloAnnotator`
- Kept/exported `VertexEllipseAnnotator` alongside the new ellipse variants
- Standardized keypoint annotator docstrings and executable examples
- Added/updated `validate_detection_confidence` and `validate_visible`
- Removed/cleaned old keypoint validator shims
- Added regression tests for visibility, confidence fields, multi-skeleton behavior, and indexing edge cases
- Updated helpers and RF-DETR/keypoint tests for the new confidence/visibility model
- Added API design principles to contributing docs
- Ignored local multi-skeleton test script in `.gitignore`

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-06-11 18:34:33 +02:00
Jirka Borovec b8ebc14489
docs(agents): refine AGENTS.md (#2308) 2026-06-10 22:25:31 +02:00
Tamil Adhavan S K 8a4063086f
chore: update YOLO OBB annotation export support (#2302)
* fix(yolo): validate OBB corner shape and test is_obb=False passthrough
* docs(config): add attribute docstring to ORIENTED_BOX_COORDINATES

---------

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[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-10 15:28:42 +02:00
Shahid Ul Islam a549f44792
Add OBB support to ConfusionMatrix via MetricTarget (#2247)
* feat(metrics): OBB support in ConfusionMatrix, MASKS guard, shape validation
* refactor(tests): extract reusable ConfusionMatrix MASKS test cases
* refine(metrics): exclude metric_target from ConfusionMatrix.__eq__
* refactor(metrics): consolidate _assert_supported_target call sites
* fix(metrics): normalise OBB (N,4,2) shape explicitly in detections_to_tensor
* test(metrics): add OBB wrong-target-cols case to validate_input_tensors
* test(metrics): add OBB edge-case parametrize cases to detections_to_tensor
* test(metrics): replace validate_input_tensors with _validate_input_tensors in test_detection
* refactor(metrics): make ConfusionMatrix unhashable
* fix(metrics): add shape validation to evaluate_detection_batch
* fix(metrics): cast class_id to float32 in detections_to_tensor
* test(metrics): fix test_evaluate_detection_batch targets shape

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-06-10 13:29:33 +02:00
Ruben cb9d3dccb8
chore(deprecation): use `TargetMode` enum to silence deprecate `FutureWarnings` on import (#2304)
* fix(deprecation): use TargetMode enum to silence deprecate FutureWarnings on import
* chore: bump `pydeprecate` dependency to v0.9 and update lockfile

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
2026-06-09 23:40:16 +02:00
Agis Kounelis ace3ebd03e
fix(detection): make `Detections.area` OBB-aware (#2306)
* fix(detection): make Detections.area OBB-aware

When detections carry ORIENTED_BOX_COORDINATES (the four xyxyxyxy corners),
the area property returned the area of the derived axis-aligned bounding
box instead of the rotated body. The AABB overestimates by up to ~2x for a
45-degree rotation, which silently miscomputes downstream values — most
visibly the area-sorted z-ordering inside MaskAnnotator / HaloAnnotator,
and any user code that filters detections by area.

* docs(detection): use string literal in Detections.area doctest
* test(detection): single-line docstring on test_uses_oriented_box_corners_when_present
* fix(detection): validate (N,4,2) shape of OBB data field in Detections.area
* perf(detection): replace np.roll pair with cross-diagonal shoelace in Detections.area
* perf(detection): cast x/y slices to float64 instead of full corners array
* refactor(detection): extract obb_polygon_area to detection/utils/boxes.py
* test(detection): add test_raises_on_malformed_obb_coordinates_shape
* test(detection): assert per-branch dtype contract for Detections.area
* docs(detection): document OBB dispatch contract and dtype in Detections.area docstring

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-09 22:20:34 +02:00
Jirka Borovec 9faa4f6133
chore: update `mdformat` hook arguments to disable wrapping (#2307)
* chore: update `mdformat` hook arguments to disable wrapping
* 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>
2026-06-09 16:15:05 +02:00
Jirka Borovec 97f4951f08
docs(contributing): formalise test conventions and doctest guidelines (#2305)
* formalise test conventions and doctest guidelines
* strengthen doctest rule and add syntax guide
* relax doctest rule to strong recommendation
* fix line-length ref and heading depth rules

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-09 15:51:18 +02:00
Agis Kounelis 3b485f719a
refine(detection): make `with_nms` and `with_nmm` OBB-aware (#2303)
* fix(detection): make with_nms and with_nmm OBB-aware
* perf(detection): bound rasterization canvas in oriented_box_iou_batch
* fix(detection): with_nmm OBB/AABB xyxy fix; 3-path dispatch docs
* fix(detection): shape validation, NMM assert, docstring/Examples
* test(detection): with_nmm fallback, OBB AABB fix, boundary and IOS tests
* docs(changelog): document OBB with_nms/nmm behaviour change for #2303
* docs(detection): convert OBB NMS/NMM examples to doctests
* refactor(test): group OBB NMS/NMM tests into classes
* refactor(test): merge duplicate NMS class-awareness tests via parametrize
* refactor(test): parametrize overlap-metric and dispatch tests

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-06-09 13:11:09 +02:00
Agis Kounelis c92458b70e
fix(dataset): preserve OBB rotation in `DetectionDataset.as_yolo` (#2289)
DetectionDataset.from_yolo accepts is_obb=True and stores the four
corners in detections.data["xyxyxyxy"], but DetectionDataset.as_yolo
has no matching option and only reads xyxy/mask. The standard
from_yolo -> split -> as_yolo flow silently writes 5-token
axis-aligned lines, and re-loading the saved file with is_obb=True
crashes the validator because it expects 9 tokens.

Add is_obb to as_yolo, save_yolo_annotations, and
detections_to_yolo_annotations. When True, the four corners from
data["xyxyxyxy"] are serialized via the existing object_to_yolo
polygon path. Masks are ignored, mirroring from_yolo(is_obb=True)
semantics. A missing xyxyxyxy raises ValueError early.

- Add UserWarning in as_yolo when area/approx params passed with is_obb=True (silently ignored)
- Add UserWarning in detections_to_yolo_annotations when mask present + is_obb=True
- Update ValueError message to include expected shape (N, 4, 2) for manual callers
- Add Google-style docstrings to detections_to_yolo_annotations and save_yolo_annotations
- Add test: N>1 OBB detections per image (corner indexing via data-dict slicing)
- Add test: dataset round-trip with background-only (no label file) image
- Add test: as_yolo() without is_obb=True on OBB-loaded dataset emits 5-token lines
- Replace all tempfile.TemporaryDirectory / os.path.join / os.makedirs
  with pytest tmp_path and pathlib Path
- Merge 3 load-mask tests into parametrized test_load_yolo_annotations_mask_behaviour
  (obb-no-mask, obb-force_masks-ignored, segmentation-produces-mask)
- Merge token-count tests into parametrized test_dataset_as_yolo_obb_output_token_count
  (obb-save-nine-tokens, default-save-five-tokens)
- Split corner accuracy into dedicated test_dataset_as_yolo_obb_round_trip_corner_accuracy
- Drop import os and import tempfile

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
2026-06-08 15:31:04 +02:00
dependabot[bot] eef8c96d95
⬆️ Bump the github-actions group with 2 updates (#2300)
Bumps the github-actions group with 2 updates: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `astral-sh/setup-uv` from 8.1.0 to 8.2.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](08807647e7...fac544c07d)

Updates `codecov/codecov-action` from 6 to 7
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 8.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: codecov/codecov-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-08 13:45:31 +02:00
Andrew Barnes b82d6f95be
fix: normalize file extension filters (#2298)
* fix: normalize file extension filters
* fix(file): add is_file and empty-ext guards
* test(file): collapse extension tests into parametrized form
* fix: match multi-part extension suffix tails

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Codex <codex@openai.com>
2026-06-08 13:41:25 +02:00
Andrew Barnes b18a30ea1a
fix: support grayscale letterbox images (#2297)
- Delete letterbox_image alpha block (lines 266-270): block wrote to
  caller's input array, not image_with_borders; used wrong coordinate
  system (resized vs original dims); redundant since cv2.copyMakeBorder
  already sets alpha=0 in padded regions when given a 3-element value
- Add test_letterbox_image_for_rgba_opencv_image: asserts padded alpha=0,
  interior alpha preserved, and input array not mutated after call
- Update letterbox_image docstring: image param lists (H,W,3)/(H,W,4)/
  (H,W)/PIL shapes; add Note on BGRA alpha behavior; add grayscale doctest

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-07 11:06:21 -06:00
Andrew Barnes 35006d7342
fix: sort YOLO class names by numeric keys (#2296)
* fix: sort yolo class names by numeric keys
* fix(yolo): reject double-hyphen keys in _is_int_like predicate
* fix(yolo): raise ValueError for mixed numeric/non-numeric names keys
* test(yolo): parametrize _extract_class_names with all key-type cases
* refine(yolo): rename lambda param key→k to avoid shadowing outer variable
* docs(yolo): comment bool guard in _is_int_like
* docs(yolo): docstring for _extract_class_names

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-07 10:54:43 -06:00
Jirka Borovec 3410d92daa
refactor: privatize validation helpers (#2294)
* refactor: privatize validation helpers
* fix: correct error message in _validate_keypoint_confidence

- Fix f"({n, m})" -> f"({n}, {m})" (set literal -> proper shape string)
- Fix error message "1D" -> "2D" to match actual array dimensionality

* fix: correct error message in _validate_xy

- Fix f"({n, m},)" -> f"({n}, {m}, 2) or ({n}, {m}, 3)"
- Fix error message "2D" -> "3D" to match actual array dimensionality

* bump pydeprecate version to >=0.9,<0.10 and fix type ignore tag for decorator
* chore: extend deprecation removal timeline to 0.32.0 across validators

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-06 13:15:54 -06:00
Piotr Skalski 5a8e211a04 Docs/api design principles contributing (#2292)
* fix: resolve ruff line-length and mypy union syntax errors in keypoints module

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: add API design principles to CONTRIBUTING.md

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 18:09:09 -06:00
Piotr Skalski 1e8a48559b
Revert "feat: store keypoints on detections (#2290)" (#2291)
This reverts commit e03111e67c.
2026-06-04 11:43:48 -06:00
Jirka Borovec e03111e67c
feat: store keypoints on detections (#2290)
* docs: add API design principles to contribution guidelines
* feat: store keypoints on detections
* test: add "keypoints" to internal test cases
* docs: document keypoints field semantics and add docstring + dtype guard
* refactor: deduplicate keypoints shape check and add K-mismatch guard
* docs: clarify Detections.keypoints vs sv.KeyPoints decision rule and add KeyPoints filter example
* feat(key_points): add KeyPoints.from_detections() cross-container adapter
* test: extend keypoints test coverage — dtype guard, __eq__, dynamic field sets
* test: expand keypoints test coverage (M7/M8)
* fix: correct validate_xy expected_shape and dimensionality message
* fix: add ndim guard in KeyPoints.from_detections
* test: add unit tests for KeyPoints.from_detections adapter
* refactor: fix class_id cast and import formatting in key_points

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-04 09:09:37 -06:00
Lourdhu Raju 0c67942d32
Refactor/polygon zone doctest (#2264)
Replaces the static python code block with a pycon doctest using
primitive numpy inputs, so the example is now executed and verified
by `pytest --doctest-modules`. Removes the external YOLO, ByteTrack,
and cv2 dependencies from the example.

Follows the same pattern as PR #2207 (LineZone). Part of the
documentation-as-tests effort tracked in #2106.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 08:33:46 +02:00
Ritwij Aryan Parmar 7d2259669b
Fix OBB IoU for non-square canvases (#2282)
* Fix OBB IoU canvas dimensions
* test(metrics): fix OBB metric parametrize — remove MAP, add smoke test
* test(metrics): clarify MAP OBB test is smoke test only
* test(iou): parametrize OBB scaling invariance test with y-dominant case
* fix(iou): add empty-input guard and x/y axis docs to oriented_box_iou_batch

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-06-01 09:20:38 +02:00
tarunbommawar27 fb02e5c959
docs: clarify MaskAnnotator mask requirements (#2279)
* docs: clarify MaskAnnotator mask requirements
* Potential fix for pull request finding

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-29 10:24:45 +02:00
Jirka Borovec 918b6139ef
feat(keypoints): add keypoint conversion bridge (#2277)
* feat(keypoints): add RF-DETR keypoint conversion bridge
* feat: add RF-DETR keypoint uncertainty visualization
* refactor(keypoints): remove deprecated RF-DETR keypoint conversion logic
* refactor: improve internal handling of keypoint data and detection utilities
* fix(keypoints): handle non-finite confidence values and empty keypoint arrays
* docs(keypoint): add VertexEllipseAnnotator to annotators docs
* docs(keypoints): add Example block to KeyPoints.from_rfdetr docstring
* docs(keypoints): document source_shape HW ordering in from_rfdetr
* feat(keypoints): validate precision_cholesky shape in from_rfdetr
* refine(keypoints): add warning log for silent precision matrix failures
* fix(keypoints): fix mypy type errors in VertexEllipseAnnotator
* test(keypoints): add confidence_threshold filter test for VertexEllipseAnnotator
* test(keypoints): add max_axis_length cap and constructor validator tests
* docs(keypoints): document max_axis_length=None risk in VertexEllipseAnnotator
* docs(keypoints): add Raises section to VertexEllipseAnnotator.annotate docstring
* docs(keypoints): document confidence scale convention in from_rfdetr
* docs(keypoints): note from_rfdetr input convention in KeyPoints class docstring
* fix(types): improve type hinting for internal and keypoints modules
* fix(keypoints): handle None class_id in from_rfdetr conversion

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-28 10:36:41 +02:00
Madhav-C 81218c5f1b
fix(coco): emit 1-indexed `category_id` in COCO export (#2276)
* fix): emit 1-indexed category_id in COCO export
* test): add regression and guard tests for 1-indexed category_id
* docs): warn in coco_annotations_to_detections that remap is required

---------

Co-authored-by: madhavcodez <madhavcodez@users.noreply.github.com>
Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-27 10:40:32 +02:00
Mahbod 2c3a2ef6f9
fix(detection): preserve `class_name` string dtype on empty `Detections.from_inference` (#2270)
* fix): preserve class_name string dtype on empty Detections.from_inference
* test): fix stale float64 dtype expectation in test_process_roboflow_result
* docs): document data[class_name] contract in from_inference Returns
* fix): set string-dtype class_name on empty from_ultralytics and from_vlm paths
* test): strengthen from_inference empty-path dtype test
* test): cover SDK .dict() path for empty predictions in from_inference
* docs): add docstring to process_roboflow_result
* test): use dtype.kind comparison for empty/non-empty class_name
* docs): update example in `process_roboflow_result` docstring

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-27 10:39:49 +02:00
Mahbod 2fdb970430
fix(annotators): avoid divide-by-zero in HeatMapAnnotator on empty detections (#2269)
When HeatMapAnnotator is called on a fresh annotator with empty detections
(common on the first frames of a video before the model produces any output),
self.heat_mask is all zeros, so temp / temp.max() raises
RuntimeWarning: invalid value encountered in divide and produces nan/inf
in-flight. Skip the normalisation when temp.max() == 0; the resulting
all-zero heat mask filters out via the > 0 check below, so the scene is
returned unchanged.

- Fix `kernel_size: int = 25` → `int | None = 25`; document None disables blur
- Add Note to annotate docstring: empty detections returns scene unchanged
- Add happy path test: single detection must produce visible heat output
- Add stateful tests: empty→real and real→empty sequence coverage

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-26 22:27:07 +02:00
dependabot[bot] fb2dec9775
⬆️ Update pydeprecate requirement from <0.8,>=0.7 to >=0.7,<0.9 (#2268)
Updates the requirements on [pydeprecate](https://github.com/Borda/pyDeprecate) to permit the latest version.
- [Release notes](https://github.com/Borda/pyDeprecate/releases)
- [Changelog](https://github.com/Borda/pyDeprecate/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Borda/pyDeprecate/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: pydeprecate
  dependency-version: 0.8.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-25 11:30:37 +02:00
Madhav-C befdb7c661
fix(dataset): make COCO annotation/image ids chainable across splits (#2267)
* fix(dataset): make COCO annotation/image ids chainable across splits (#768)

Exporting train/valid/test splits with DetectionDataset.as_coco
previously restarted image_id and annotation_id at 1 for every split,
producing three JSON files whose ids collided and could not be safely
merged into a single COCO collection.

Adds optional starting_image_id and starting_annotation_id parameters
to save_coco_annotations and DetectionDataset.as_coco (default 1 to
preserve existing behavior) and returns a (next_image_id,
next_annotation_id) tuple so callers can feed the result of one
export straight into the next:

    next_image, next_ann = train.as_coco(annotations_path="train.json")
    next_image, next_ann = valid.as_coco(
        annotations_path="valid.json",
        starting_image_id=next_image,
        starting_annotation_id=next_ann,
    )
    test.as_coco(
        annotations_path="test.json",
        starting_image_id=next_image,
        starting_annotation_id=next_ann,
    )

The images-only branch of as_coco (annotations_path=None) round-trips
the starting ids unchanged so chaining still works there.

Adds 4 regression tests covering defaults, custom starting ids,
end-to-end three-split chaining with global uniqueness assertions,
and the images-only round-trip.

* docs: address review polish on COCO id-chaining
* fix(dataset): align save_coco_annotations approximation_percentage default to 0.0
* docs(dataset): add one-line summary to save_coco_annotations docstring
* docs: add changelog entry for COCO id chaining (PR #2267)
* docs(dataset): document file_name uniqueness limitation in save_coco_annotations
* feat(dataset): validate starting_image_id and starting_annotation_id >= 1
* docs(dataset): add Example section to save_coco_annotations docstring
* docs(dataset): unpack final as_coco return value in chaining example
* test(dataset): add COCO chaining tests and fix test helper for zero detections

---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 21:41:42 +02:00
Copilot cb259065a5
Add `from_coco` regression coverage for multi-segment COCO masks (#2258)
* test: cover from_coco multi-segment masks
* test: add from_coco multi-segment regression
* test: extract coco multi-segment fixture
* test(coco): move multi-segment mask test to TestFromCocoMasks
* test(coco): fix fixture area and document bbox intent
* test(coco): add force_masks=True sibling test for multi-segment masks
* test(coco): add uneven-length segments case to TestFromCocoMasks
* test(coco): parametrize force_masks in TestFromCocoMasks

---------

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>
2026-05-22 20:42:11 +02:00
Madhav-C 4b856f1c04
docs(examples): fix outdated CLI flag names in `heatmap_and_track` README (#2266)
The README listed `--track_threshold` and `--match_threshold`, but
script.py exposes `--track_activation_threshold` and
`--minimum_matching_threshold` (the CLI surface is derived from the
main() signature by jsonargparse.auto_cli). Following the README as
written produced "unknown argument" errors.

Aligns the README with the actual CLI surface.
2026-05-22 20:00:30 +02:00
Copilot 6461d3fbac
Restructure annotator docs tabs to avoid Material’s 20-tab limit (#2257)
* Initial plan
* fix: split annotator docs tabs into categories
* test: harden annotator docs regression test
* docs: fix blur example assignment
* docs(annotators): restructure tabs, harden regression tests
* docs(annotators): remove broken oriented box preview image

---------

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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 19:54:33 +02:00
Jirka Borovec 2c13b269e6
Update changelog after version `0.28.0` release
Updated the date modified and added a new entry for version 0.28.0 with details on sv.CompactMask.
2026-05-22 19:14:29 +02:00
Jirka Borovec f1176270eb
Bump version to `0.29.0.dev` 2026-05-22 19:12:20 +02:00
Copilot 5b883fed5b
Guard `InferenceSlicer` against OBB callback crashes when `thread_workers > 1` (#2256)
* fix: serialize OBB inference slicer callbacks
* test: simplify OBB slicer regression test
* refactor: simplify OBB slicer fallback path
* test: make OBB slicer regression deterministic
* fix(slicer): add thread_workers validation and lock for OBB warn flag
* docs(slicer): document OBB fallback, merge order, perf note, dual-use key

---------

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: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-05-22 18:53:26 +02:00
Jirka Borovec e7376d558e
ci(tests): disable matplotlib GUI and exclude non-test dirs from collection (#2262) 2026-05-20 23:40:21 +02:00
dependabot[bot] 17d7717515
⬆️ Bump pymdown-extensions from 10.16.1 to 10.21.3 in the uv group across 1 directory (#2255)
Bumps the uv group with 1 update in the / directory: [pymdown-extensions](https://github.com/facelessuser/pymdown-extensions).


Updates `pymdown-extensions` from 10.16.1 to 10.21.3
- [Release notes](https://github.com/facelessuser/pymdown-extensions/releases)
- [Commits](https://github.com/facelessuser/pymdown-extensions/compare/10.16.1...10.21.3)

---
updated-dependencies:
- dependency-name: pymdown-extensions
  dependency-version: 10.21.3
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 11:59:25 +02:00
dependabot[bot] 7e6df44d86
⬆️ Bump idna from 3.10 to 3.15 in the uv group across 1 directory (#2254)
Bumps the uv group with 1 update in the / directory: [idna](https://github.com/kjd/idna).


Updates `idna` from 3.10 to 3.15
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md)
- [Commits](https://github.com/kjd/idna/compare/v3.10...v3.15)

---
updated-dependencies:
- dependency-name: idna
  dependency-version: '3.15'
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-20 11:50:16 +02:00
Youssef Ibrahim 01ec36b31d
fix: return empty int ndarray instead of None for class_id on empty VLM parse (#2239)
When from_paligemma or from_google_gemini_2_0 find no detections (no regex
matches, JSON decode error, or empty bounding-box list), they previously
returned None for class_id. All other early-exit and filter paths already
return a zero-length ndarray of dtype int. This inconsistency causes
downstream AttributeError when callers unconditionally call .shape or
iterate over the result.

Affected paths:
- from_paligemma: matches.shape[0] == 0 branch
- from_google_gemini_2_0: JSONDecodeError branch and len(xyxy) == 0 branch

---------

Co-authored-by: YousefZahran1 <youssefzahran.y@gmail.com>
Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
2026-05-19 14:31:44 +02:00
Prem f4b0767a88
docs: add sample image download and sv.plot_image() to detect_and_annotate tutorial (#2242)
* docs: add sample image download and sv.plot_image() to detect_and_annotate tutorial
* Potential fix for pull request finding

---------

Co-authored-by: PatelPrem21 <prem_23247@ldrp.ac.in>
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 Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-19 14:22:49 +02:00
SATISH K C 7e28315595
fix: preserve audio stream in process_video (#2252)
- Move `tempfile.mkstemp` + `os.close` inside `try` block so OSError (disk full,
  unwritable dir) is caught by the existing `except Exception` handler instead of
  propagating to the caller, preserving the warn-and-degrade contract
- Pass `dir=os.path.dirname(os.path.abspath(video_path))` so the temp file is on
  the same filesystem as the output, restoring `os.rename` semantics in `shutil.move`
- Initialise `tmp_path = None` before `try`; guard `finally` with
  `tmp_path is not None` to satisfy mypy and avoid referencing an unbound name
- Add `-loglevel error -nostats` so ffmpeg only writes actual errors to stderr
  (eliminates progress/stats spam that would buffer in PIPE indefinitely)
- Decode `result.stderr` and include it in the warning when ffmpeg exits
  non-zero, so failure messages surface diagnostically instead of being discarded
- Change bare `process_video(...)` call to `sv.process_video(...)` so the
  example matches the public API pattern and does not raise NameError for users
  copying the snippet
- Remove unused `import cv2` which was never referenced in the example body
- Clarify that missing/failing ffmpeg warns and continues rather than raising
- Add install hint for ffmpeg (apt/brew)
- Note that audio is truncated to match the processed video duration (-shortest)
- test_mux_audio_moves_file_on_success: mock subprocess.run returncode=0;
  assert shutil.move is called once with video_path as destination — catches
  any regression that drops the move call after a successful ffmpeg run
- test_mux_audio_swallows_subprocess_exception: mock subprocess.run raising
  OSError; assert no exception escapes _mux_audio and original file is intact
- Fix failed_result.stderr = b"" in test_mux_audio_warns_on_ffmpeg_failure
  to match the updated _mux_audio which now decodes result.stderr
- Skip _mux_audio when writer_worker.is_alive() after join timeout to avoid
  muxing an incomplete output file
- Fix test_mux_audio_moves_file_on_success: patch os.replace (not shutil.move)
  to match implementation changed in 2027938d
- Move four test_mux_audio_* free functions into TestMuxAudio class
- Strip mux_audio_ prefix from method names; class carries the unit
- Condense multi-line docstrings to single-line per testing rules
- Collapse test_warns_when_ffmpeg_missing, test_warns_on_ffmpeg_failure,
  test_swallows_subprocess_exception into one parametrized
  test_file_unchanged_on_failure[ffmpeg_missing|ffmpeg_fails|subprocess_raises]
- Promote two class methods back to module-level functions
- Collapse nested with-patch statements into single with a, b: form

---------

Co-authored-by: jirka <6035284+Borda@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-19 14:09:45 +02:00
Jirka Borovec b68b41ae7a
ci(docs): skip RC tags, strip .postX, fix latest alias deploy (#2253)
- Skip mike deploy for RC releases (tags containing rc/RC)
- Strip .postX suffix before deploying (0.27.0.post1 → 0.27.0)
- Add -u flag to latest deploy to handle existing alias

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-05-19 12:02:24 +02:00
dependabot[bot] 6fb4e80837
⬆️ Bump mistune from 3.1.3 to 3.2.1 in the uv group across 1 directory (#2250)
Bumps the uv group with 1 update in the / directory: [mistune](https://github.com/lepture/mistune).


Updates `mistune` from 3.1.3 to 3.2.1
- [Release notes](https://github.com/lepture/mistune/releases)
- [Changelog](https://github.com/lepture/mistune/blob/main/docs/changes.rst)
- [Commits](https://github.com/lepture/mistune/compare/v3.1.3...v3.2.1)

---
updated-dependencies:
- dependency-name: mistune
  dependency-version: 3.2.1
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 13:02:13 +02:00
JFrench-Enterprise 7dce60697f
Simplified wording Update README.md (#2249)
---------

Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-13 18:25:06 +02:00
dependabot[bot] 26ae68a2b6
⬆️ Bump AButler/upload-release-assets from 3.0 to 4.0 in the github-actions group (#2243)
Bumps the github-actions group with 1 update: [AButler/upload-release-assets](https://github.com/abutler/upload-release-assets).


Updates `AButler/upload-release-assets` from 3.0 to 4.0
- [Release notes](https://github.com/abutler/upload-release-assets/releases)
- [Commits](https://github.com/abutler/upload-release-assets/compare/v3.0...v4.0)

---
updated-dependencies:
- dependency-name: AButler/upload-release-assets
  dependency-version: '4.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 17:58:05 +02:00
dependabot[bot] 878e6414da
⬆️ Bump jupyter-server from 2.16.0 to 2.18.0 in the uv group across 1 directory (#2245)
Bumps the uv group with 1 update in the / directory: [jupyter-server](https://github.com/jupyter-server/jupyter_server).


Updates `jupyter-server` from 2.16.0 to 2.18.0
- [Release notes](https://github.com/jupyter-server/jupyter_server/releases)
- [Changelog](https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jupyter-server/jupyter_server/compare/v2.16.0...v2.18.0)

---
updated-dependencies:
- dependency-name: jupyter-server
  dependency-version: 2.18.0
  dependency-type: indirect
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-13 17:57:51 +02:00
Jirka Borovec 2beeda7851
docs: link "Memory-Efficient Instance Segmentation" notebook and update deprecations (#2241)
* link "Memory-Efficient Instance Segmentation" notebook and update deprecations
* fix(notebook): correct broken Colab badge URL in compact-mask-sam3

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-05-01 00:49:15 +02:00
dependabot[bot] 6ec8fa9a23
⬆️ Bump notebook from 7.4.4 to 7.5.6 in the uv group across 1 directory (#2238)
Bumps the uv group with 1 update in the / directory: [notebook](https://github.com/jupyter/notebook).


Updates `notebook` from 7.4.4 to 7.5.6
- [Release notes](https://github.com/jupyter/notebook/releases)
- [Changelog](https://github.com/jupyter/notebook/blob/@jupyter-notebook/tree@7.5.6/CHANGELOG.md)
- [Commits](https://github.com/jupyter/notebook/compare/@jupyter-notebook/tree@7.4.4...@jupyter-notebook/tree@7.5.6)

---
updated-dependencies:
- dependency-name: notebook
  dependency-version: 7.5.6
  dependency-type: direct:development
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-30 23:52:40 +02:00
Jirka Borovec 1f199de502
drop outdated release_process.md 2026-04-30 23:52:00 +02:00
Jirka Borovec d8a25481c4
chore(notebooks): migrate demo scripts to Jupyter notebooks (#2240)
- Removed `convert_to_ipynb.sh` script and standalone `.py` demo files.
- Added `docs/notebooks/compact-mask-sam3.ipynb` showcasing new features (`sv.CompactMask` and `sv.Detections.from_sam3`) introduced in version `0.28.0`.
2026-04-30 23:49:11 +02:00
Jirka Borovec 87b1b86f39
releasing `0.28.0` (#2220)
* docs: add 0.28.0 changelog entries and release demo notebook
* feat: add script for converting Python scripts to Jupyter notebooks
* chore: reorganize imports in release-demo notebook and update lint config
* docs: fix broken link in changelog entry for ConfusionMatrix

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-04-30 17:11:50 +02:00