Tracking services
Source: src/app/application/services/tracking
Tracking links detections of the same object across frames into tracks (a stable ID per object). The Application tracking services start a worker from reviewed detections and commit its finished tracks into layers C and D. Algorithm details are in tracking infrastructure.
Arrows are calls or signals in time order. The tracking handler connects
the worker's signals and later calls sync_tracking_cache; the services never
connect them.
| Part | Role |
|---|---|
TrackingService |
Facade-facing entry: coverage check, start, sync |
TrackingWorkerManager |
Validates the source, clears C/D, creates the worker |
TrackingResultProcessor |
Writes finished tracks into C and D |
Before starting: coverage check
get_detection_frame_coverage returns (frames with A entries, total frames).
An empty A entry counts as processed; a missing entry does not. The UI uses
it to offer Okay or Proceed Anyway on partial coverage before anything
is cleared; running detection must finish first.
Evidence, not proof
Imported or older projects only provide stored entries, not proof that a detection run completed.
Starting a run
The service logs the request, rejects an empty session id
(InvalidSessionIdException), and delegates to the manager, which:
- rejects a second run (
TrackingWorkerAlreadyRunningException); - accepts only A or B as source (
UnsupportedLayerExceptionfor C/D); - for B, seeds missing B frames from A with filtered clones; existing B frames are never replaced;
- rejects an empty source (
EmptyLayerException); - clears C and D;
- builds the worker from the source layer, session state, and strategy; the
adapter starts it immediately (
start=True).
Arrows show data flow. B is the usual input so human review influences the tracks; the dashed arrow is the alternative (A as input).
C and D are cleared before the worker finishes
Earlier manual D edits are lost when a new run starts, and a failed run leaves C/D empty. The worker deep-copies the source detections and the session settings at construction, so later edits do not change that run.
Committing results
When the worker emits finished_processing, the handler calls
sync_tracking_cache, which fetches the worker's frame-indexed tracks
(TrackingWorkerNotFoundException if there is no worker) and asks the result
processor to:
- overwrite C with the tracks (machine output, never hand-edited);
- replace D's machine boxes across the whole frame range using the current tracker-confidence filter, keeping manual D boxes.
D can therefore differ from C on purpose. After syncing, the handler selects
the tracking tab and re-renders the frame. A worker failure arrives through
error_occurred, handled by the handler's _on_tracking_failed.
Editing D afterwards
Directional deletion of a track's occurrences edits only D, excluding the
current frame. Display IDs such as -4 resolve to stored keys such as
track:-4. Frames missing from D in older projects are first seeded from C
with the same filter; deleting the last box leaves an initialised empty frame
so later reads cannot resurrect it from C. That logic belongs to the tracking
layer service; see Layer services. Layer roles:
Video layers; strategies:
Tracking domain.