> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/workflows/blocks/blocks/video-processing/track-class-lock.md).

# Track Class Lock

Lock the class label of each tracked object by majority voting, eliminating class flicker in video workflows where a model alternates between similar classes for the same physical object.

## How This Block Works

This block maintains per-track voting state, keyed by the video\_identifier embedded in the image's video metadata:

1. Pre-lock, every qualifying frame (confidence >= vote\_confidence) counts as a vote for the predicted class. A class becomes locked once it collects min\_votes votes AND leads the runner-up class by at least lead\_margin votes.
2. Post-lock, the locked class is written into every subsequent detection of that track. Reported confidence is the running mean of counted votes (clamped to 1.0).
3. A locked class can only change after switch\_after CONSECUTIVE qualifying frames of the same challenger class. Challenger evidence is streak-scoped: both the streak counter and its confidence sum reset whenever the streak breaks, and on a successful switch the new class's tallies are seeded from the streak values only, so reported confidence never exceeds 1.0.
4. When a NEW tracker id appears where a locked track recently disappeared (within reattach\_window frames, bounding box IoU >= reattach\_iou), the new track inherits the lost track's lock and voting state. This makes locks survive tracker id switches caused by short detection gaps or occlusions. Only locked tracks are inherited, and a track still present in the current frame is never inherited. Set reattach\_window to 0 to disable re-attachment.
5. State for tracks unseen for state\_ttl frames is purged.

Each detection is annotated with a boolean `class_locked` flag in detections.data.

## Requirements

Detections must carry tracker\_id (wire this block after a tracking block such as Byte Tracker). The image's video\_metadata is used to maintain separate state per video stream.

### Type identifier

Use the following identifier in step `"type"` field: `roboflow_core/track_class_lock@v1` to add the block as a step in your workflow.

### Properties

| **Name**          | **Type** | **Description**                                                                                                                                                                                                                                        | Refs |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---- |
| `name`            | `str`    | Enter a unique identifier for this step..                                                                                                                                                                                                              | ❌    |
| `min_votes`       | `int`    | Cumulative qualifying votes a class needs before the initial lock is acquired. Higher values delay locking but make the initial decision more reliable..                                                                                               | ✅    |
| `vote_confidence` | `float`  | Minimum prediction confidence for a frame to count, both for pre-lock votes and post-lock challenger streaks. Frames below this threshold are ignored..                                                                                                | ✅    |
| `lead_margin`     | `int`    | Number of votes by which the top class must lead the runner-up before locking. Prevents premature locks when two classes are contested..                                                                                                               | ✅    |
| `switch_after`    | `int`    | Number of CONSECUTIVE qualifying frames of the same challenger class required to change an existing lock. Any interruption resets the streak. Minimum 1 (a value of 1 switches on a single contrary frame; use >= 2 to enforce a multi-frame streak).. | ✅    |
| `state_ttl`       | `int`    | Number of frames after which state of unseen tracks is purged..                                                                                                                                                                                        | ✅    |
| `reattach_window` | `int`    | When a NEW tracker id appears where a locked track disappeared within this many frames, the new track inherits the lost track's lock and votes. Bridges tracker id switches caused by short detection gaps. Set to 0 to disable re-attachment..        | ✅    |
| `reattach_iou`    | `float`  | Minimum IoU between a new detection's bounding box and a recently lost locked track's last known bounding box for the lock to be inherited. Higher values require the object to reappear closer to where it vanished..                                 | ✅    |

The **Refs** column marks possibility to parametrise the property with dynamic values available in `workflow` runtime. See *Bindings* for more info.

### Runtime compatibility

`soft` - runtime `hosted_serverless`, `dedicated_deployment`; execution `remote`; input `video` : Block keeps per-video state in process memory (keyed by video\_metadata.video\_identifier). With remote step execution on stateless or multi-replica HTTP runtimes, successive requests may be served by different worker processes, so the state resets between calls and the output is meaningless for tracking / counting / aggregation. Use local step execution in a persistent WebRTC session for stable cross-frame results.

`soft` - input `image` : Block depends on temporal context from video or repeated-frame workflows. With a still image/photo, there is no meaningful history to track, compare, aggregate, or visualize, so the block provides little or no benefit.

### Input and Output Bindings

The available connections depend on its binding kinds. Check what binding kinds `Track Class Lock` in version `v1` has.

<details>

<summary>Input and output bindings</summary>

* input
  * `image` ([*`image`*](/workflows/developer-guide/developer-guide/kinds/image.md)): Image with embedded video metadata. The video\_metadata contains video\_identifier used to maintain separate voting state for different videos..
  * `detections` (*Union\[*[*`rle_instance_segmentation_prediction`*](/workflows/developer-guide/developer-guide/kinds/rle-instance-segmentation-prediction.md)*,* [*`object_detection_prediction`*](/workflows/developer-guide/developer-guide/kinds/object-detection-prediction.md)*,* [*`instance_segmentation_prediction`*](/workflows/developer-guide/developer-guide/kinds/instance-segmentation-prediction.md)*,* [*`keypoint_detection_prediction`*](/workflows/developer-guide/developer-guide/kinds/keypoint-detection-prediction.md)*]*): Tracked predictions (object detection, instance segmentation, keypoint detection or RLE instance segmentation). Must include tracker\_id information from a tracking block..
  * `min_votes` ([*`integer`*](/workflows/developer-guide/developer-guide/kinds/integer.md)): Cumulative qualifying votes a class needs before the initial lock is acquired. Higher values delay locking but make the initial decision more reliable..
  * `vote_confidence` ([*`float_zero_to_one`*](/workflows/developer-guide/developer-guide/kinds/float-zero-to-one.md)): Minimum prediction confidence for a frame to count, both for pre-lock votes and post-lock challenger streaks. Frames below this threshold are ignored..
  * `lead_margin` ([*`integer`*](/workflows/developer-guide/developer-guide/kinds/integer.md)): Number of votes by which the top class must lead the runner-up before locking. Prevents premature locks when two classes are contested..
  * `switch_after` ([*`integer`*](/workflows/developer-guide/developer-guide/kinds/integer.md)): Number of CONSECUTIVE qualifying frames of the same challenger class required to change an existing lock. Any interruption resets the streak. Minimum 1 (a value of 1 switches on a single contrary frame; use >= 2 to enforce a multi-frame streak)..
  * `state_ttl` ([*`integer`*](/workflows/developer-guide/developer-guide/kinds/integer.md)): Number of frames after which state of unseen tracks is purged..
  * `reattach_window` ([*`integer`*](/workflows/developer-guide/developer-guide/kinds/integer.md)): When a NEW tracker id appears where a locked track disappeared within this many frames, the new track inherits the lost track's lock and votes. Bridges tracker id switches caused by short detection gaps. Set to 0 to disable re-attachment..
  * `reattach_iou` ([*`float_zero_to_one`*](/workflows/developer-guide/developer-guide/kinds/float-zero-to-one.md)): Minimum IoU between a new detection's bounding box and a recently lost locked track's last known bounding box for the lock to be inherited. Higher values require the object to reappear closer to where it vanished..
* output
  * `tracked_detections` (*Union\[*[*`object_detection_prediction`*](/workflows/developer-guide/developer-guide/kinds/object-detection-prediction.md)*,* [*`instance_segmentation_prediction`*](/workflows/developer-guide/developer-guide/kinds/instance-segmentation-prediction.md)*,* [*`keypoint_detection_prediction`*](/workflows/developer-guide/developer-guide/kinds/keypoint-detection-prediction.md)*,* [*`rle_instance_segmentation_prediction`*](/workflows/developer-guide/developer-guide/kinds/rle-instance-segmentation-prediction.md)*]*): Prediction with detected bounding boxes in form of sv.Detections(...) object if `object_detection_prediction` or Prediction with detected bounding boxes and segmentation masks in form of sv.Detections(...) object if `instance_segmentation_prediction` or Prediction with detected bounding boxes and detected keypoints in form of sv.Detections(...) object if `keypoint_detection_prediction` or Prediction with detected bounding boxes and RLE-encoded segmentation masks in form of sv.Detections(...) object if `rle_instance_segmentation_prediction`.

</details>

<details>

<summary>Example JSON definition</summary>

```json
{
	    "name": "<your_step_name_here>",
	    "type": "roboflow_core/track_class_lock@v1",
	    "image": "<block_does_not_provide_example>",
	    "detections": "$steps.byte_tracker.tracked_detections",
	    "min_votes": 10,
	    "vote_confidence": 0.8,
	    "lead_margin": 3,
	    "switch_after": 15,
	    "state_ttl": 300,
	    "reattach_window": 30,
	    "reattach_iou": 0.3
	}
```

</details>
