Frame By Frame Linkers
Base class for frame by frame linkers. The current implementation follows the tracks handling strategy proposed in KOFT [9].
- class byotrack.implementation.linker.frame_by_frame.base.AssociationMethod(value)
Bases:
EnumAssociation methods (Greedy or Jonker-Volgenant)
- GREEDY
Select the best match between tracks and detections iteratively until no match can be selected below the cost limit eta. It is usually not optimal for tracking but it is much faster.
- OPT_HARD
Solve the linear association problem (see pylapy). Hard threshold the association matrix with the cost limit eta.
- OPT_SMOOTH
Solve a cost_limit extended association problem (see pylapy) It relaxes the linear association problem, allowing to not link a node for the cost limit eta.
- class byotrack.implementation.linker.frame_by_frame.base.TrackHandler(n_valid: int, n_gap: int, start: int, identifier: int)
Bases:
objectHandle a track during the tracking procedure
It accumulates the track data at each new association and store the optional motion model data.
A TrackHandler is created for each unlinked detections in the linking process and then updated with the following associated detections. At the beginining, the track is considered HYPOTHETICAL. For a track to be considered valid, it requires n_valid consecutive associated detections after the track creation (state: HYPOTHETICAL => VALID). It a miss detection occurs during this time interval, then the track is deleted and considered invalid (state: HYPOTHETICAL => INVALID).
Once confirmed, a VALID track is resilient to miss detections, waiting n_gap frames before ending the track (VALID => FINISHED).
- n_valid
Number of frames with a correct association required to validate the track at its creation.
- Type:
- track_state
Current state of the handler
- Type:
- track_ids
Index of the track at each frame in the linker.active_tracks list. It allows the linker to store data as tensor and be able to rebuild tracks at the end.
- Type:
List[int]
- class TrackState(value)
Bases:
IntEnumTrackState of a TrackHandler
- HYPOTHETICAL
Initial state before validation of the track.
- VALID
The track has been validated and is still active
- FINISHED
The track is valid and finished
- INVALID
The track is not valid and deleted
- class byotrack.implementation.linker.frame_by_frame.base.OnlineFlowExtractor(optflow: OpticalFlow)
Bases:
objectExtract optical flow maps online from a video
- class byotrack.implementation.linker.frame_by_frame.base.FrameByFrameLinkerParameters(association_threshold: float, n_valid=3, n_gap=3, association_method: str | AssociationMethod = AssociationMethod.OPT_SMOOTH)
Bases:
objectParameters of the abstract FrameByFrameLinker
- association_threshold
This is the main hyperparameter, it defines the threshold on the distance used not to link tracks with detections. It prevents to link with false positive detections.
- Type:
- n_valid
Number of frames with a correct association required to validate the track at its creation. Default: 3
- Type:
- association_method
The frame-by-frame association to use. See AssociationMethod. It can be provided as a string. (Choice: GREEDY, OPT_HARD, OPT_SMOOTH) Default: OPT_SMOOTH
- Type:
- class byotrack.implementation.linker.frame_by_frame.base.FrameByFrameLinker(specs: FrameByFrameLinkerParameters, optflow: OpticalFlow | None = None, features_extractor: FeaturesExtractor | None = None, save_all=False)
Bases:
OnlineLinkerLinks detections online using frame-by-frame association
Abstract class for frame-by-frame linker. It decomposes the update step in 5 parts:
Optional optical flow computations (Handled by this class)
Motion modeling to predict track positions (motion_model)
Track-to-detection cost computation (cost)
Solving the linear association problem (Handled by this class)
Post matching update to handle tracks (post_association)
The association relies on the AssociationMethod enum and tracks handling is done with TrackHandler.
It follows the tracks handling strategy describe in KOFT [9].
- specs
Parameters specifications of the algorithm. See FrameByFrameLinkerParameters.
- optflow
Optional wrapper around the given optional OpticalFlow that will extract flow maps of the video online. (The underlying OpticalFlow object is accessible in self.optflow.optflow) Default: None
- Type:
Optional[OnlineFlowExtractor]
- features_extractor
Optional features extractor that will extract features for the detections, which could be useful for tracking. Default: None
- Type:
Optional[FeaturesExtractor]
- save_all
Save metadata useless for the final building of tracks but that could be useful for analysis. For instance, it will keep invalid tracks. Or the computed features inside the Detections objects.
- Type:
- inactive_tracks
Terminated tracks
- Type:
List[TrackHandler]
- active_tracks
Current track handlers
- Type:
List[TrackHandler]
- all_positions
Positions of the active tracks at each seen frames. Using the valid track handlers track_ids, it allows the reconstruction of tracks.
- Type:
List[torch.Tensor]
- reset() None
Reset the linking algorithm
Flush all data stored from a previous linking and prepare a new linking
- collect() List[Track]
Collect and build all the tracks up to the last given frame
- Returns:
Tracks from the last reset to the last given frame.
- Return type:
Collection[byotrack.Track]
- abstract motion_model() None
Optional modelisation of motion for tracks
It can be used to update some internal state of the tracker after the optical flow computation and before the distance computation.
- abstract cost(frame: ndarray, detections: Detections) Tuple[Tensor, float]
Compute the association cost between active tracks and detections
It also returns the threshold to use (Depending on the dist you use, association_threshold could be related to a more meaning full quantity than the cost itself). For instance, when using a squared Euclidean distance, the association threshold could be express as the distance in pixel, and this function could square it. For likelihood association, you could provide the association threshold as a probability and use -log(threshold) as the true threshold. (See KalmanLinker and NearestNeighborLinker)
- Parameters:
frame (np.ndarray) – The current frame of the video Shape: (H, W, C), dtype: float
detections (byotrack.Detections) – Detections for the given frame
- Returns:
- The cost matrix between active tracks and detections
Shape: (n_tracks, n_dets), dtype: float32
- float: The association threshold to use.
It can be different than self.association_threshold depeding on the dist build here
- Return type:
torch.Tensor
- abstract post_association(frame: ndarray, detections: Detections, links: Tensor)
Update the tracks and the internal variables of the tracker
It should call the update method of each active tracks and update any internal model/data. It should also create new track handlers for each extra detection. Finally, it is also responsible to register the position of each active track in all_positions for the current time frame.
- Parameters:
frame (np.ndarray) – The current frame of the video Shape: (H, W, C), dtype: float
detections (byotrack.Detections) – Detections for the given frame
links (torch.Tensor) – The links made between active tracks and the detections Shape: (L, 2), dtype: int32
- update_active_tracks(links: Tensor) Tensor
Calls update for active tracks and return a boolean mask that indicates which track is still active
Tracks that are terminated are stored inside inactive_tracks and dropped from active_tracks.
It can be called inside post_association to simplify the code.
- Parameters:
links (torch.Tensor) – The links made between active tracks and the detections Shape: (L, 2), dtype: int32
- Returns:
Boolean tensor indicating True for still active tracks
- Return type:
torch.Tensor
- handle_extra_detections(detections: Detections, links: Tensor) Tensor
Handle extra detections by creating new track handlers
It can be called inside post_association to create track handlers from extra detections. It will return the extra detections positions and ids to be further used by post_association.
- Parameters:
detections (byotrack.Detections) – Detections for the given frame
links (torch.Tensor) – The links made between active tracks and the detections Shape: (L, 2), dtype: int32
- update(frame: ndarray, detections: Detections) None
Progress in the linking step by one frame
Will update the internal algorithm by a single frame and its detections.
- Parameters:
frame (np.ndarray) – Frame of the video Shape: (H, W, C), dtype: float
detections (byotrack.Detections) – Detections for the given frame
- byotrack.implementation.linker.frame_by_frame.greedy_lap.greedy_assignment_solver(dist: ndarray, eta: float = inf)
Solve assignement problem in a greedy way
Iteratively select the minimum cost, then deleting its row/column.
Stops when the cost matrix is empty (no more rows or columns) or if the selected cost is higher than eta
- Parameters:
dist (np.ndarray) – Distance matrix Shape: (N, M), dtype: float
eta (float) – Hard thresholding Default: inf (No thresholding)
- Returns:
- Links (i, j)
Shape: (L, 2), dtype: uint16
- Return type:
np.ndarray