Spaces:
Runtime error
Runtime error
# vim: expandtab:ts=4:sw=4 | |
class TrackState: | |
""" | |
Enumeration type for the single target track state. Newly created tracks are | |
classified as `tentative` until enough evidence has been collected. Then, | |
the track state is changed to `confirmed`. Tracks that are no longer alive | |
are classified as `deleted` to mark them for removal from the set of active | |
tracks. | |
""" | |
Tentative = 1 | |
Confirmed = 2 | |
Deleted = 3 | |
class Track: | |
""" | |
A single target track with state space `(x, y, a, h)` and associated | |
velocities, where `(x, y)` is the center of the bounding box, `a` is the | |
aspect ratio and `h` is the height. | |
Parameters | |
---------- | |
mean : ndarray | |
Mean vector of the initial state distribution. | |
covariance : ndarray | |
Covariance matrix of the initial state distribution. | |
track_id : int | |
A unique track identifier. | |
n_init : int | |
Number of consecutive detections before the track is confirmed. The | |
track state is set to `Deleted` if a miss occurs within the first | |
`n_init` frames. | |
max_age : int | |
The maximum number of consecutive misses before the track state is | |
set to `Deleted`. | |
feature : Optional[ndarray] | |
Feature vector of the detection this track originates from. If not None, | |
this feature is added to the `features` cache. | |
Attributes | |
---------- | |
mean : ndarray | |
Mean vector of the initial state distribution. | |
covariance : ndarray | |
Covariance matrix of the initial state distribution. | |
track_id : int | |
A unique track identifier. | |
hits : int | |
Total number of measurement updates. | |
age : int | |
Total number of frames since first occurance. | |
time_since_update : int | |
Total number of frames since last measurement update. | |
state : TrackState | |
The current track state. | |
features : List[ndarray] | |
A cache of features. On each measurement update, the associated feature | |
vector is added to this list. | |
""" | |
def __init__(self, mean, covariance, track_id, class_id, n_init, max_age, | |
feature=None): | |
self.mean = mean | |
self.covariance = covariance | |
self.track_id = track_id | |
self.class_id = class_id | |
self.hits = 1 | |
self.age = 1 | |
self.time_since_update = 0 | |
self.state = TrackState.Tentative | |
self.features = [] | |
if feature is not None: | |
self.features.append(feature) | |
self._n_init = n_init | |
self._max_age = max_age | |
def to_tlwh(self): | |
"""Get current position in bounding box format `(top left x, top left y, | |
width, height)`. | |
Returns | |
------- | |
ndarray | |
The bounding box. | |
""" | |
ret = self.mean[:4].copy() | |
ret[2] *= ret[3] | |
ret[:2] -= ret[2:] / 2 | |
return ret | |
def to_tlbr(self): | |
"""Get current position in bounding box format `(min x, miny, max x, | |
max y)`. | |
Returns | |
------- | |
ndarray | |
The bounding box. | |
""" | |
ret = self.to_tlwh() | |
ret[2:] = ret[:2] + ret[2:] | |
return ret | |
def increment_age(self): | |
self.age += 1 | |
self.time_since_update += 1 | |
def predict(self, kf): | |
"""Propagate the state distribution to the current time step using a | |
Kalman filter prediction step. | |
Parameters | |
---------- | |
kf : kalman_filter.KalmanFilter | |
The Kalman filter. | |
""" | |
self.mean, self.covariance = kf.predict(self.mean, self.covariance) | |
self.increment_age() | |
def update(self, kf, detection): | |
"""Perform Kalman filter measurement update step and update the feature | |
cache. | |
Parameters | |
---------- | |
kf : kalman_filter.KalmanFilter | |
The Kalman filter. | |
detection : Detection | |
The associated detection. | |
""" | |
self.mean, self.covariance = kf.update( | |
self.mean, self.covariance, detection.to_xyah()) | |
self.features.append(detection.feature) | |
self.hits += 1 | |
self.time_since_update = 0 | |
if self.state == TrackState.Tentative and self.hits >= self._n_init: | |
self.state = TrackState.Confirmed | |
def mark_missed(self): | |
"""Mark this track as missed (no association at the current time step). | |
""" | |
if self.state == TrackState.Tentative: | |
self.state = TrackState.Deleted | |
elif self.time_since_update > self._max_age: | |
self.state = TrackState.Deleted | |
def is_tentative(self): | |
"""Returns True if this track is tentative (unconfirmed). | |
""" | |
return self.state == TrackState.Tentative | |
def is_confirmed(self): | |
"""Returns True if this track is confirmed.""" | |
return self.state == TrackState.Confirmed | |
def is_deleted(self): | |
"""Returns True if this track is dead and should be deleted.""" | |
return self.state == TrackState.Deleted |