Skip to content

feat: add person tracking, subject selection, and stature scaling - #1041

Merged
mprib merged 4 commits into
mainfrom
feature/person-selection-and-stature
Nov 8, 2026
Merged

mprib merged 4 commits into
mainfrom
feature/person-selection-and-stature

Conversation

@mprib

@mprib mprib commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Per-frame largest-person selection can switch to a bystander when the calibration subject leaves a view.
Add a box-first scripting path that selects a person over the recording before estimating keypoints, plus model-defined stature scaling.

Summary

  • Add model-card-selected YOLOX detection, camera-local ByteTrack identities, and pose estimation within detected boxes. Include detector weights in model readiness and downloads, reject out-of-image keypoints, and discard boxes with no area after clipping.
  • Add BoxTracks, covered-image-area subject selection, explicit edge filtering, and selected-box keypoint extraction. Use the existing timestamp machinery to preserve declared frame correspondence, including shared anchor frames, and expose a minimum number of distinct camera views for triangulation.
  • Add model-defined stature chains and ModelCard.stature_cue() for CaptureVolume.scaled(). Use the median complete-frame chain length without an empirical correction.

The feature work is grouped into three commits matching these steps.
A separate test-only follow-up waits for Qt to delete retired camera cards before checking the exact expected IDs, fixing a pre-existing CI race.

Subject selection runs independently in each camera and assumes the intended subject dominates covered image area.
It does not establish identity across cameras or join fragmented tracks.
Anchor frames declare known alignment rather than estimating timing offsets.
Recording-level selection and stature scaling are scripting APIs.

Built-in model cards now load from the installed package rather than being seeded into the model directory.
User cards with the same filename as a built-in card are ignored.
RTMPose-m Halpe26 uses YOLOX-M; the other supplied pose cards retain YOLOX-S.

Test plan

  • Full suite with Xvfb and xdist: 896 passed, one expected unresolvable-depth-cue warning.
  • Focused checks at rewritten commit boundaries: 24 detector/tracker checks and 68 selection/timestamp/triangulation checks; 36 anchoring/stature checks also passed.
  • Changed-source type checks, Ruff lint, and formatting checks.
  • Strict documentation builds for the recording-selection and final states.
  • Regression coverage for padding-only detector output, empty result shapes, and score correspondence when retaining a partly clipped box.

CI follow-up verification: the four workspace-feedback tests pass, and the affected test passes ten fresh-process repetitions.

mprib added 4 commits November 7, 2026 19:16
Run a model-card-selected YOLOX detector before top-down pose estimation,
exposing all person boxes, per-camera ByteTrack identities, and pose within
a selected box. No detected person gives no pose; cards without a detector
retain full-frame inference. Drop out-of-image keypoints.

Load built-in cards from the package and include detector weights, sources,
and licenses in readiness and downloads. RTMPose-m Halpe26 uses YOLOX-M;
other supplied pose cards keep YOLOX-S. Preserve observed boxes and scores
for the recording-level selection introduced in the next commit.

Discard boxes with non-positive area after clipping to the source frame.
Predictions entirely in letterbox padding otherwise become flat boxes and
can abort the downstream recording extraction. Apply the same mask to
scores, preserving valid partly clipped boxes and empty-array shapes.

Verified: 24 focused tracker, registry, download, ByteTrack, and detector
regression tests pass; source type, lint, and formatting checks pass.
The padding-only and mixed valid/invalid regressions use stub sessions
without loading weights or running real model inference.
…oints

Add the box-first scripting workflow: track detected people, select the
track covering the greatest image area in each camera, filter boxes by an
explicit source-pixel margin, and estimate pose only in retained boxes.
BoxTracks preserves camera-local identities, source coordinates, frames,
times, confidence, and rotation metadata. Selection assumes the intended
subject dominates covered area in each camera; it does not match identities
across cameras or join fragmented tracks.

Require the existing SynchronizedTimestamps object at the tracking call
site. Add a shared-anchor constructor with an optional known frame rate
so recordings retain known frame correspondence despite unequal lengths.
This declares alignment rather than discovering offsets. The scripting
guide describes source frame indices separately from sync indices and
anchor-relative times, including negative times before an anchor.

Expose a minimum number of distinct posed camera views for triangulation.
Include the workflow and recording assumptions in the guides.
Verified: 68 focused selection, timestamp, and rigid-constraint checks pass;
source type, lint, formatting, and strict documentation checks pass.
Add a Stature cue to CaptureVolume.scaled() and define named body chains in
Halpe26 model cards. ModelCard.stature_cue() resolves names to keypoint IDs.
Scale uses the median complete-frame sum of the two heel-to-shoulder chains
and shoulder-midpoint-to-head distance, with an explicit reconstructed
object when necessary.

Reuse the existing scale-cue mechanism and caller-supplied grounding
offsets. No height-entry GUI or foot-based levelling is added. This uses
a measured stature and the chosen model's keypoints; it does not establish
model-independent anatomical accuracy or apply an empirical correction.

Verified: 36 anchoring and stature-card tests and the final 896-test suite
pass, with one expected unresolvable-depth-cue warning. Source type, lint,
formatting, and strict documentation checks pass. The combined feature was
independently reviewed, and the detector padding and timing-documentation
fixes are folded into their respective preceding commits.
The workspace feedback test waited for the coordinator to discover camera 2, then immediately counted recursive CameraThumbnailCard descendants. Grid rebuild removes old cards from the layout but deletes them later through Qt, so macOS and Windows could count retired cards alongside the replacement cards as [0, 0, 1, 1, 2].

Wait for the same exact [0, 1, 2] condition through qtbot.waitUntil so queued cleanup completes. Do not weaken the expected IDs, add a fixed delay, or change production widget behavior. An offscreen probe confirmed that only three cards occupy the layout while old QObject descendants await deferred deletion.

Verified: all four workspace feedback tests pass, the affected test passes ten fresh-process repetitions, and Ruff lint/format checks pass. The full suite is running; macOS CI will verify the runner-specific failure.
@mprib
mprib merged commit 5546c5e into main Nov 8, 2026
5 checks passed
@mprib
mprib deleted the feature/person-selection-and-stature branch November 8, 2026 18:03
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.

1 participant