Skip to content

Fix KeyPoints 2D boolean mask indexing (uniform-count selection)#2188

Merged
Borda merged 10 commits intodevelopfrom
copilot/fix-keypoints-filtering-issue
Mar 30, 2026
Merged

Fix KeyPoints 2D boolean mask indexing (uniform-count selection)#2188
Borda merged 10 commits intodevelopfrom
copilot/fix-keypoints-filtering-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

Fixes KeyPoints.__getitem__ to handle 2D boolean mask indexing where each row selects the same number of keypoints. Previously this raised IndexError; it now produces a correct (n, k, 2) result.

Use cases that now work

# Single-object confidence filter — always works (n=1, uniform trivially)
kp1[kp1.confidence > 0.5]

# Select the same subset of joints from every person in the frame
left_side = np.array([[True, False, True, False, True, ...]])  # shape (1, m)
mask = np.tile(left_side, (n, 1))   # broadcast to all n persons
kp[mask]

Limitation (documented)

A 2D mask where different rows select different numbers of True values still raises ValueError — NumPy cannot represent a jagged (n, ?, 2) array. This is the common case when using kp[kp.confidence > 0.5] with multiple objects (each person may have a different number of high-confidence keypoints). For that pattern process each object individually or zero out low-confidence entries in-place.

Changes

  • KeyPoints.__getitem__ / _get_by_2d_bool_mask: New private method handles 2D np.ndarray boolean indices. Applies the mask row-by-row producing a (n, k, 2) result. Raises ValueError with a clear message if rows have different counts or mask shape mismatches.
  • Shape validation: Validates mask.shape against (n_objects, n_keypoints) before processing.
  • Tests: Six new parametrized cases — uniform multi-object, single-object, confidence=None, shape-mismatch ×2, all-False mask, and the canonical single-object kp[kp.confidence > 0.5] expression.

Copilot AI changed the title [WIP] Fix KeyPoints filtering with confidence parameter Fix KeyPoints 2D boolean mask indexing (e.g. keypoints[keypoints.confidence > 0.5]) Mar 30, 2026
Copilot AI requested a review from Borda March 30, 2026 08:05
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77%. Comparing base (1291188) to head (16f0110).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #2188   +/-   ##
=======================================
  Coverage       77%     77%           
=======================================
  Files           62      62           
  Lines         7615    7637   +22     
=======================================
+ Hits          5881    5903   +22     
  Misses        1734    1734           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Borda and others added 5 commits March 30, 2026 22:59
- Break error message string at line 686 to stay within 88-char ruff E501 limit
- Add explicit npt.NDArray[np.float32] | None annotation on conf_selected; use
  cast() at the branch assignment to prevent mypy widening to Optional[Any]
  (mypy 1.19.1 + numpy 2.x stubs treat npt.NDArray as Any, so narrowing via
  `if conf_selected is not None` requires a concrete type from cast, and the
  self.confidence access needs its own is-not-None guard inside the loop)

[resolve #1] /review finding by sw-engineer (report: _outputs/2026/03/output-review-2026-03-30-5.md):
"conf_selected inferred as Optional[Any]; mypy pre-commit hook fails"
[resolve #3] /review finding by linting-expert (report: _outputs/2026/03/output-review-2026-03-30-5.md):
"ruff E501: line too long (89 > 88) at core.py:686"

---
Co-authored-by: Claude Code <noreply@anthropic.com>
[resolve #2] /review finding by linting-expert (report: _outputs/2026/03/output-review-2026-03-30-5.md):
"PT011: pytest.raises(ValueError) too broad — missing match= parameter at test_core.py:295"

---
Co-authored-by: Claude Code <noreply@anthropic.com>
Validate that the mask shape matches (n_objects, n_keypoints) before
processing. A row-count mismatch now raises ValueError with a clear message
instead of a confusing IndexError; a column-count mismatch similarly raises
ValueError instead of silently producing incorrect results.

[resolve #4] /review finding by sw-engineer (report: _outputs/2026/03/output-review-2026-03-30-5.md):
"No shape validation between index and self.xy — mismatched masks silently misfilter or raise IndexError"

---
Co-authored-by: Claude Code <noreply@anthropic.com>
Four new parametrized cases:
- confidence=None path: 2D mask on a KeyPoints with no confidence array
- column count mismatch: raises ValueError matching "column count"
- row count mismatch: raises ValueError matching "row count"
- all-False mask: all rows select 0 keypoints — equal counts (0==0), result has shape (n, 0, 2)

[resolve #5] /review finding by qa-specialist (report: _outputs/2026/03/output-review-2026-03-30-5.md):
"Missing edge-case tests: confidence=None path, shape-mismatch mask, empty result, all-False mask"

---
Co-authored-by: Claude Code <noreply@anthropic.com>
@Borda Borda marked this pull request as ready for review March 30, 2026 22:22
@Borda Borda requested a review from SkalskiP as a code owner March 30, 2026 22:22
Copilot AI review requested due to automatic review settings March 30, 2026 22:22
@Borda Borda changed the title Fix KeyPoints 2D boolean mask indexing (e.g. keypoints[keypoints.confidence > 0.5]) Fix KeyPoints 2D boolean mask indexing Mar 30, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes KeyPoints.__getitem__ behavior when indexing with a 2D boolean mask (e.g., keypoints[keypoints.confidence > 0.5]) by adding explicit handling for (n, m) boolean masks and adding tests for the new behavior.

Changes:

  • Added a dedicated __getitem__ branch to support 2D boolean mask filtering of keypoints per object, with validation for shape consistency.
  • Added parametrized tests covering valid 2D-mask filtering and expected ValueError cases (row/column mismatch and unequal per-row selection counts).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/supervision/key_points/core.py Implements 2D boolean mask handling in KeyPoints.__getitem__.
tests/key_points/test_core.py Adds test cases for 2D boolean mask indexing behavior and error conditions.

Comment thread src/supervision/key_points/core.py Outdated
Comment thread src/supervision/key_points/core.py Outdated
Comment thread src/supervision/key_points/core.py Outdated
Borda and others added 2 commits March 31, 2026 00:26
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI requested a review from Borda March 30, 2026 22:29
…ct test

The 2D boolean mask path requires every row to select the same number of
keypoints (uniform-count invariant) so the result fits a rectangular
(n, k, 2) array. The docstring now explains this clearly and notes that
kp[kp.confidence > 0.5] works for n==1 but raises ValueError for n>1 when
the threshold yields different keypoint counts per object.

Also adds the canonical single-object confidence-filter test case to
guard against regressions on the primary advertised use case.

---
Co-authored-by: Claude Code <noreply@anthropic.com>
@Borda Borda changed the title Fix KeyPoints 2D boolean mask indexing Fix KeyPoints 2D boolean mask indexing (uniform-count selection) Mar 30, 2026
@Borda Borda merged commit 85ba8be into develop Mar 30, 2026
27 checks passed
@Borda Borda deleted the copilot/fix-keypoints-filtering-issue branch March 30, 2026 23:48
@Borda Borda mentioned this pull request Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[KeyPoints] - KeyPoints doesn't work like Detections filtering

3 participants