Skip to content

perf(ocsort): reuse the box returned by predict - #580

Open
JESUSROYETH wants to merge 1 commit into
roboflow:developfrom
JESUSROYETH:perf/ocsort-reuse-predicted-box
Open

perf(ocsort): reuse the box returned by predict#580
JESUSROYETH wants to merge 1 commit into
roboflow:developfrom
JESUSROYETH:perf/ocsort-reuse-predicted-box

Conversation

@JESUSROYETH

Copy link
Copy Markdown
Contributor

OC-SORT currently throws away the box returned by predict(), then decodes the same unchanged state through get_state_bbox() before association. This happens because the shared predict helper discards return values at base.py:520-525, and OCSORT decodes again at tracker.py:266-275.

So the returned predictions end up optional in the shared helper. OCSORT asks for them and keeps an id(tracklet) map, so pruning tracks before association cannot move the boxes to a different track. Duplicate timestamps still use get_state_bbox() because prediction is skipped there. The other tracker families use the default path and keep the old loop without building the map.

Validation

I compared develop against itself first, then against this patch. Two 500-frame dynamic streams cover XCYCSR and XYXY, 10,547 detections per representation, duplicate timestamps every 37 frames, and a separate case where one track is pruned between prediction and association. Output boxes were paired by Hungarian IoU, the output IDs and complete per-frame state hashes are exact.

In both cases, the same check passes over 36,928 public MOT17 detections and 45,442 DanceTrack ground-truth boxes. It removes 50,563 redundant decodes on MOT17 and 48,874 on the DanceTrack sample.

pytest -m 'not integration' passes with 1,564 tests, the four evaluator integrations pass, and pre-commit run --all-files is clean.

Performance

CPU-only, Python 3.12.3 and NumPy 1.26.4. Inputs are loaded before timing, run order alternates and garbage collection runs before each sample.

stream develop median [range] this patch median [range] delta paired wins
MOT17, 7 sequences / 2,664 frames 1.615897 s [1.593757, 1.673104] 1.555865 s [1.532014, 1.600218] -3.72% 10/10
DanceTrack, 5 stratified sequences / 3,676 frames 1.858677 s [1.854952, 1.869702] 1.799468 s [1.793562, 1.818832] -3.19% 10/10

I also checked the five callers that do not need returned predictions. A first version built the map unconditionally and made them 0.31-0.57% slower, so I dropped it. With opt-in collection their final MOT17 median deltas are between -0.17% and +0.09%, the ranges overlap, and paired wins are mixed at 4-7/10.

Dynamic prediction arrived in #446. #527 optimized the adjacent OCSORT association path, while #528 cached predicted boxes for BoT-SORT and CBIoU. OCSORT only has one primary predicted-box association stage, so its already returned value stayed unused.

@JESUSROYETH
JESUSROYETH requested a review from SkalskiP as a code owner August 22, 2026 13:52
@Borda
Borda requested a balanced review from Copilot August 23, 2026 12:12
@Borda Borda added the enhancement New feature or request label Aug 23, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Optimizes OC-SORT association by reusing bounding boxes returned during prediction instead of decoding unchanged states again.

Changes:

  • Adds opt-in prediction collection to the shared helper.
  • Reuses predictions by tracklet identity, with duplicate-timestamp fallback.

Reviewed changes

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

File Description
src/trackers/core/base.py Optionally returns predictions keyed by tracklet identity.
src/trackers/core/ocsort/tracker.py Reuses cached predictions during association.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

out_tracker_ids: list[int] = []

self._predict_tracklets(self.tracks, timing)
predicted_boxes_by_tracklet = self._predict_tracklets(self.tracks, timing, return_predictions=True)
@Borda
Borda requested a review from tstanczyk95 August 24, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants