Meta Byte Track
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

track.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # vim: expandtab:ts=4:sw=4
  2. class TrackState:
  3. """
  4. Enumeration type for the single target track state. Newly created tracks are
  5. classified as `tentative` until enough evidence has been collected. Then,
  6. the track state is changed to `confirmed`. Tracks that are no longer alive
  7. are classified as `deleted` to mark them for removal from the set of active
  8. tracks.
  9. """
  10. Tentative = 1
  11. Confirmed = 2
  12. Deleted = 3
  13. class Track:
  14. """
  15. A single target track with state space `(x, y, a, h)` and associated
  16. velocities, where `(x, y)` is the center of the bounding box, `a` is the
  17. aspect ratio and `h` is the height.
  18. Parameters
  19. ----------
  20. mean : ndarray
  21. Mean vector of the initial state distribution.
  22. covariance : ndarray
  23. Covariance matrix of the initial state distribution.
  24. track_id : int
  25. A unique track identifier.
  26. n_init : int
  27. Number of consecutive detections before the track is confirmed. The
  28. track state is set to `Deleted` if a miss occurs within the first
  29. `n_init` frames.
  30. max_age : int
  31. The maximum number of consecutive misses before the track state is
  32. set to `Deleted`.
  33. feature : Optional[ndarray]
  34. Feature vector of the detection this track originates from. If not None,
  35. this feature is added to the `features` cache.
  36. Attributes
  37. ----------
  38. mean : ndarray
  39. Mean vector of the initial state distribution.
  40. covariance : ndarray
  41. Covariance matrix of the initial state distribution.
  42. track_id : int
  43. A unique track identifier.
  44. hits : int
  45. Total number of measurement updates.
  46. age : int
  47. Total number of frames since first occurance.
  48. time_since_update : int
  49. Total number of frames since last measurement update.
  50. state : TrackState
  51. The current track state.
  52. features : List[ndarray]
  53. A cache of features. On each measurement update, the associated feature
  54. vector is added to this list.
  55. """
  56. def __init__(self, mean, covariance, track_id, class_id, n_init, max_age,
  57. feature=None):
  58. self.mean = mean
  59. self.covariance = covariance
  60. self.track_id = track_id
  61. self.class_id = class_id
  62. self.hits = 1
  63. self.age = 1
  64. self.time_since_update = 0
  65. self.state = TrackState.Tentative
  66. self.features = []
  67. if feature is not None:
  68. self.features.append(feature)
  69. self._n_init = n_init
  70. self._max_age = max_age
  71. def to_tlwh(self):
  72. """Get current position in bounding box format `(top left x, top left y,
  73. width, height)`.
  74. Returns
  75. -------
  76. ndarray
  77. The bounding box.
  78. """
  79. ret = self.mean[:4].copy()
  80. ret[2] *= ret[3]
  81. ret[:2] -= ret[2:] / 2
  82. return ret
  83. def to_tlbr(self):
  84. """Get current position in bounding box format `(min x, miny, max x,
  85. max y)`.
  86. Returns
  87. -------
  88. ndarray
  89. The bounding box.
  90. """
  91. ret = self.to_tlwh()
  92. ret[2:] = ret[:2] + ret[2:]
  93. return ret
  94. def increment_age(self):
  95. self.age += 1
  96. self.time_since_update += 1
  97. def predict(self, kf):
  98. """Propagate the state distribution to the current time step using a
  99. Kalman filter prediction step.
  100. Parameters
  101. ----------
  102. kf : kalman_filter.KalmanFilter
  103. The Kalman filter.
  104. """
  105. self.mean, self.covariance = kf.predict(self.mean, self.covariance)
  106. self.increment_age()
  107. def update(self, kf, detection):
  108. """Perform Kalman filter measurement update step and update the feature
  109. cache.
  110. Parameters
  111. ----------
  112. kf : kalman_filter.KalmanFilter
  113. The Kalman filter.
  114. detection : Detection
  115. The associated detection.
  116. """
  117. self.mean, self.covariance = kf.update(
  118. self.mean, self.covariance, detection.to_xyah())
  119. self.features.append(detection.feature)
  120. self.hits += 1
  121. self.time_since_update = 0
  122. if self.state == TrackState.Tentative and self.hits >= self._n_init:
  123. self.state = TrackState.Confirmed
  124. def mark_missed(self):
  125. """Mark this track as missed (no association at the current time step).
  126. """
  127. if self.state == TrackState.Tentative:
  128. self.state = TrackState.Deleted
  129. elif self.time_since_update > self._max_age:
  130. self.state = TrackState.Deleted
  131. def is_tentative(self):
  132. """Returns True if this track is tentative (unconfirmed).
  133. """
  134. return self.state == TrackState.Tentative
  135. def is_confirmed(self):
  136. """Returns True if this track is confirmed."""
  137. return self.state == TrackState.Confirmed
  138. def is_deleted(self):
  139. """Returns True if this track is dead and should be deleted."""
  140. return self.state == TrackState.Deleted