ultralytics 8.0.237__py3-none-any.whl → 8.0.239__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ultralytics might be problematic. Click here for more details.

Files changed (137) hide show
  1. ultralytics/__init__.py +2 -2
  2. ultralytics/cfg/__init__.py +241 -138
  3. ultralytics/cfg/datasets/DOTAv1.5.yaml +1 -1
  4. ultralytics/cfg/datasets/DOTAv1.yaml +1 -1
  5. ultralytics/cfg/datasets/dota8.yaml +34 -0
  6. ultralytics/data/__init__.py +9 -2
  7. ultralytics/data/annotator.py +4 -4
  8. ultralytics/data/augment.py +186 -169
  9. ultralytics/data/base.py +54 -48
  10. ultralytics/data/build.py +34 -23
  11. ultralytics/data/converter.py +242 -70
  12. ultralytics/data/dataset.py +117 -95
  13. ultralytics/data/explorer/__init__.py +5 -0
  14. ultralytics/data/explorer/explorer.py +170 -97
  15. ultralytics/data/explorer/gui/__init__.py +1 -0
  16. ultralytics/data/explorer/gui/dash.py +146 -76
  17. ultralytics/data/explorer/utils.py +87 -25
  18. ultralytics/data/loaders.py +75 -62
  19. ultralytics/data/split_dota.py +44 -36
  20. ultralytics/data/utils.py +160 -142
  21. ultralytics/engine/exporter.py +348 -292
  22. ultralytics/engine/model.py +102 -66
  23. ultralytics/engine/predictor.py +74 -55
  24. ultralytics/engine/results.py +63 -40
  25. ultralytics/engine/trainer.py +192 -144
  26. ultralytics/engine/tuner.py +66 -59
  27. ultralytics/engine/validator.py +31 -26
  28. ultralytics/hub/__init__.py +54 -31
  29. ultralytics/hub/auth.py +28 -25
  30. ultralytics/hub/session.py +282 -133
  31. ultralytics/hub/utils.py +64 -42
  32. ultralytics/models/__init__.py +1 -1
  33. ultralytics/models/fastsam/__init__.py +1 -1
  34. ultralytics/models/fastsam/model.py +6 -6
  35. ultralytics/models/fastsam/predict.py +3 -2
  36. ultralytics/models/fastsam/prompt.py +55 -48
  37. ultralytics/models/fastsam/val.py +1 -1
  38. ultralytics/models/nas/__init__.py +1 -1
  39. ultralytics/models/nas/model.py +9 -8
  40. ultralytics/models/nas/predict.py +8 -6
  41. ultralytics/models/nas/val.py +11 -9
  42. ultralytics/models/rtdetr/__init__.py +1 -1
  43. ultralytics/models/rtdetr/model.py +11 -9
  44. ultralytics/models/rtdetr/train.py +18 -16
  45. ultralytics/models/rtdetr/val.py +25 -19
  46. ultralytics/models/sam/__init__.py +1 -1
  47. ultralytics/models/sam/amg.py +13 -14
  48. ultralytics/models/sam/build.py +44 -42
  49. ultralytics/models/sam/model.py +6 -6
  50. ultralytics/models/sam/modules/decoders.py +6 -4
  51. ultralytics/models/sam/modules/encoders.py +37 -35
  52. ultralytics/models/sam/modules/sam.py +5 -4
  53. ultralytics/models/sam/modules/tiny_encoder.py +95 -73
  54. ultralytics/models/sam/modules/transformer.py +3 -2
  55. ultralytics/models/sam/predict.py +39 -27
  56. ultralytics/models/utils/loss.py +99 -95
  57. ultralytics/models/utils/ops.py +34 -31
  58. ultralytics/models/yolo/__init__.py +1 -1
  59. ultralytics/models/yolo/classify/__init__.py +1 -1
  60. ultralytics/models/yolo/classify/predict.py +8 -6
  61. ultralytics/models/yolo/classify/train.py +37 -31
  62. ultralytics/models/yolo/classify/val.py +26 -24
  63. ultralytics/models/yolo/detect/__init__.py +1 -1
  64. ultralytics/models/yolo/detect/predict.py +8 -6
  65. ultralytics/models/yolo/detect/train.py +47 -37
  66. ultralytics/models/yolo/detect/val.py +100 -82
  67. ultralytics/models/yolo/model.py +31 -25
  68. ultralytics/models/yolo/obb/__init__.py +1 -1
  69. ultralytics/models/yolo/obb/predict.py +13 -12
  70. ultralytics/models/yolo/obb/train.py +3 -3
  71. ultralytics/models/yolo/obb/val.py +80 -58
  72. ultralytics/models/yolo/pose/__init__.py +1 -1
  73. ultralytics/models/yolo/pose/predict.py +17 -12
  74. ultralytics/models/yolo/pose/train.py +28 -25
  75. ultralytics/models/yolo/pose/val.py +91 -64
  76. ultralytics/models/yolo/segment/__init__.py +1 -1
  77. ultralytics/models/yolo/segment/predict.py +10 -8
  78. ultralytics/models/yolo/segment/train.py +16 -15
  79. ultralytics/models/yolo/segment/val.py +90 -68
  80. ultralytics/nn/__init__.py +26 -6
  81. ultralytics/nn/autobackend.py +144 -112
  82. ultralytics/nn/modules/__init__.py +96 -13
  83. ultralytics/nn/modules/block.py +28 -7
  84. ultralytics/nn/modules/conv.py +41 -23
  85. ultralytics/nn/modules/head.py +67 -59
  86. ultralytics/nn/modules/transformer.py +49 -32
  87. ultralytics/nn/modules/utils.py +20 -15
  88. ultralytics/nn/tasks.py +215 -141
  89. ultralytics/solutions/ai_gym.py +59 -47
  90. ultralytics/solutions/distance_calculation.py +22 -15
  91. ultralytics/solutions/heatmap.py +76 -54
  92. ultralytics/solutions/object_counter.py +46 -39
  93. ultralytics/solutions/speed_estimation.py +13 -16
  94. ultralytics/trackers/__init__.py +1 -1
  95. ultralytics/trackers/basetrack.py +1 -0
  96. ultralytics/trackers/bot_sort.py +2 -1
  97. ultralytics/trackers/byte_tracker.py +10 -7
  98. ultralytics/trackers/track.py +7 -7
  99. ultralytics/trackers/utils/gmc.py +25 -25
  100. ultralytics/trackers/utils/kalman_filter.py +85 -42
  101. ultralytics/trackers/utils/matching.py +8 -7
  102. ultralytics/utils/__init__.py +173 -151
  103. ultralytics/utils/autobatch.py +10 -10
  104. ultralytics/utils/benchmarks.py +76 -86
  105. ultralytics/utils/callbacks/__init__.py +1 -1
  106. ultralytics/utils/callbacks/base.py +29 -29
  107. ultralytics/utils/callbacks/clearml.py +51 -43
  108. ultralytics/utils/callbacks/comet.py +81 -66
  109. ultralytics/utils/callbacks/dvc.py +33 -26
  110. ultralytics/utils/callbacks/hub.py +44 -26
  111. ultralytics/utils/callbacks/mlflow.py +31 -24
  112. ultralytics/utils/callbacks/neptune.py +35 -25
  113. ultralytics/utils/callbacks/raytune.py +9 -4
  114. ultralytics/utils/callbacks/tensorboard.py +16 -11
  115. ultralytics/utils/callbacks/wb.py +39 -33
  116. ultralytics/utils/checks.py +189 -141
  117. ultralytics/utils/dist.py +15 -12
  118. ultralytics/utils/downloads.py +112 -96
  119. ultralytics/utils/errors.py +1 -1
  120. ultralytics/utils/files.py +11 -11
  121. ultralytics/utils/instance.py +22 -22
  122. ultralytics/utils/loss.py +117 -67
  123. ultralytics/utils/metrics.py +224 -158
  124. ultralytics/utils/ops.py +39 -29
  125. ultralytics/utils/patches.py +3 -3
  126. ultralytics/utils/plotting.py +217 -120
  127. ultralytics/utils/tal.py +19 -13
  128. ultralytics/utils/torch_utils.py +138 -109
  129. ultralytics/utils/triton.py +12 -10
  130. ultralytics/utils/tuner.py +49 -47
  131. {ultralytics-8.0.237.dist-info → ultralytics-8.0.239.dist-info}/METADATA +5 -4
  132. ultralytics-8.0.239.dist-info/RECORD +188 -0
  133. ultralytics-8.0.237.dist-info/RECORD +0 -187
  134. {ultralytics-8.0.237.dist-info → ultralytics-8.0.239.dist-info}/LICENSE +0 -0
  135. {ultralytics-8.0.237.dist-info → ultralytics-8.0.239.dist-info}/WHEEL +0 -0
  136. {ultralytics-8.0.237.dist-info → ultralytics-8.0.239.dist-info}/entry_points.txt +0 -0
  137. {ultralytics-8.0.237.dist-info → ultralytics-8.0.239.dist-info}/top_level.txt +0 -0
@@ -66,7 +66,7 @@ class SpeedEstimator:
66
66
  spdl_dist_thresh (int): Euclidean distance threshold for speed line
67
67
  """
68
68
  if reg_pts is None:
69
- print('Region points not provided, using default values')
69
+ print("Region points not provided, using default values")
70
70
  else:
71
71
  self.reg_pts = reg_pts
72
72
  self.names = names
@@ -114,8 +114,9 @@ class SpeedEstimator:
114
114
  cls (str): object class name
115
115
  track (list): tracking history for tracks path drawing
116
116
  """
117
- speed_label = str(int(
118
- self.dist_data[track_id])) + 'km/ph' if track_id in self.dist_data else self.names[int(cls)]
117
+ speed_label = (
118
+ str(int(self.dist_data[track_id])) + "km/ph" if track_id in self.dist_data else self.names[int(cls)]
119
+ )
119
120
  bbox_color = colors(int(track_id)) if track_id in self.dist_data else (255, 0, 255)
120
121
 
121
122
  self.annotator.box_label(box, speed_label, bbox_color)
@@ -132,19 +133,16 @@ class SpeedEstimator:
132
133
  """
133
134
 
134
135
  if self.reg_pts[0][0] < track[-1][0] < self.reg_pts[1][0]:
136
+ if self.reg_pts[1][1] - self.spdl_dist_thresh < track[-1][1] < self.reg_pts[1][1] + self.spdl_dist_thresh:
137
+ direction = "known"
135
138
 
136
- if (self.reg_pts[1][1] - self.spdl_dist_thresh < track[-1][1] < self.reg_pts[1][1] + self.spdl_dist_thresh):
137
- direction = 'known'
138
-
139
- elif (self.reg_pts[0][1] - self.spdl_dist_thresh < track[-1][1] <
140
- self.reg_pts[0][1] + self.spdl_dist_thresh):
141
- direction = 'known'
139
+ elif self.reg_pts[0][1] - self.spdl_dist_thresh < track[-1][1] < self.reg_pts[0][1] + self.spdl_dist_thresh:
140
+ direction = "known"
142
141
 
143
142
  else:
144
- direction = 'unknown'
145
-
146
- if self.trk_previous_times[trk_id] != 0 and direction != 'unknown':
143
+ direction = "unknown"
147
144
 
145
+ if self.trk_previous_times[trk_id] != 0 and direction != "unknown":
148
146
  if trk_id not in self.trk_idslist:
149
147
  self.trk_idslist.append(trk_id)
150
148
 
@@ -178,7 +176,6 @@ class SpeedEstimator:
178
176
  self.annotator.draw_region(reg_pts=self.reg_pts, color=(255, 0, 0), thickness=self.region_thickness)
179
177
 
180
178
  for box, trk_id, cls in zip(self.boxes, self.trk_ids, self.clss):
181
-
182
179
  track = self.store_track_info(trk_id, box)
183
180
 
184
181
  if trk_id not in self.trk_previous_times:
@@ -194,10 +191,10 @@ class SpeedEstimator:
194
191
 
195
192
  def display_frames(self):
196
193
  """Display frame."""
197
- cv2.imshow('Ultralytics Speed Estimation', self.im0)
198
- if cv2.waitKey(1) & 0xFF == ord('q'):
194
+ cv2.imshow("Ultralytics Speed Estimation", self.im0)
195
+ if cv2.waitKey(1) & 0xFF == ord("q"):
199
196
  return
200
197
 
201
198
 
202
- if __name__ == '__main__':
199
+ if __name__ == "__main__":
203
200
  SpeedEstimator()
@@ -4,4 +4,4 @@ from .bot_sort import BOTSORT
4
4
  from .byte_tracker import BYTETracker
5
5
  from .track import register_tracker
6
6
 
7
- __all__ = 'register_tracker', 'BOTSORT', 'BYTETracker' # allow simpler import
7
+ __all__ = "register_tracker", "BOTSORT", "BYTETracker" # allow simpler import
@@ -55,6 +55,7 @@ class BaseTrack:
55
55
  _count = 0
56
56
 
57
57
  def __init__(self):
58
+ """Initializes a new track with unique ID and foundational tracking attributes."""
58
59
  self.track_id = 0
59
60
  self.is_activated = False
60
61
  self.state = TrackState.New
@@ -39,6 +39,7 @@ class BOTrack(STrack):
39
39
  bo_track.predict()
40
40
  bo_track.update(new_track, frame_id)
41
41
  """
42
+
42
43
  shared_kalman = KalmanFilterXYWH()
43
44
 
44
45
  def __init__(self, tlwh, score, cls, feat=None, feat_history=50):
@@ -176,7 +177,7 @@ class BOTSORT(BYTETracker):
176
177
  def get_dists(self, tracks, detections):
177
178
  """Get distances between tracks and detections using IoU and (optionally) ReID embeddings."""
178
179
  dists = matching.iou_distance(tracks, detections)
179
- dists_mask = (dists > self.proximity_thresh)
180
+ dists_mask = dists > self.proximity_thresh
180
181
 
181
182
  # TODO: mot20
182
183
  # if not self.args.mot20:
@@ -112,8 +112,9 @@ class STrack(BaseTrack):
112
112
 
113
113
  def re_activate(self, new_track, frame_id, new_id=False):
114
114
  """Reactivates a previously lost track with a new detection."""
115
- self.mean, self.covariance = self.kalman_filter.update(self.mean, self.covariance,
116
- self.convert_coords(new_track.tlwh))
115
+ self.mean, self.covariance = self.kalman_filter.update(
116
+ self.mean, self.covariance, self.convert_coords(new_track.tlwh)
117
+ )
117
118
  self.tracklet_len = 0
118
119
  self.state = TrackState.Tracked
119
120
  self.is_activated = True
@@ -136,8 +137,9 @@ class STrack(BaseTrack):
136
137
  self.tracklet_len += 1
137
138
 
138
139
  new_tlwh = new_track.tlwh
139
- self.mean, self.covariance = self.kalman_filter.update(self.mean, self.covariance,
140
- self.convert_coords(new_tlwh))
140
+ self.mean, self.covariance = self.kalman_filter.update(
141
+ self.mean, self.covariance, self.convert_coords(new_tlwh)
142
+ )
141
143
  self.state = TrackState.Tracked
142
144
  self.is_activated = True
143
145
 
@@ -192,7 +194,7 @@ class STrack(BaseTrack):
192
194
 
193
195
  def __repr__(self):
194
196
  """Return a string representation of the BYTETracker object with start and end frames and track ID."""
195
- return f'OT_{self.track_id}_({self.start_frame}-{self.end_frame})'
197
+ return f"OT_{self.track_id}_({self.start_frame}-{self.end_frame})"
196
198
 
197
199
 
198
200
  class BYTETracker:
@@ -275,7 +277,7 @@ class BYTETracker:
275
277
  strack_pool = self.joint_stracks(tracked_stracks, self.lost_stracks)
276
278
  # Predict the current location with KF
277
279
  self.multi_predict(strack_pool)
278
- if hasattr(self, 'gmc') and img is not None:
280
+ if hasattr(self, "gmc") and img is not None:
279
281
  warp = self.gmc.apply(img, dets)
280
282
  STrack.multi_gmc(strack_pool, warp)
281
283
  STrack.multi_gmc(unconfirmed, warp)
@@ -349,7 +351,8 @@ class BYTETracker:
349
351
  self.removed_stracks = self.removed_stracks[-999:] # clip remove stracks to 1000 maximum
350
352
  return np.asarray(
351
353
  [x.tlbr.tolist() + [x.track_id, x.score, x.cls, x.idx] for x in self.tracked_stracks if x.is_activated],
352
- dtype=np.float32)
354
+ dtype=np.float32,
355
+ )
353
356
 
354
357
  def get_kalmanfilter(self):
355
358
  """Returns a Kalman filter object for tracking bounding boxes."""
@@ -10,7 +10,7 @@ from .bot_sort import BOTSORT
10
10
  from .byte_tracker import BYTETracker
11
11
 
12
12
  # A mapping of tracker types to corresponding tracker classes
13
- TRACKER_MAP = {'bytetrack': BYTETracker, 'botsort': BOTSORT}
13
+ TRACKER_MAP = {"bytetrack": BYTETracker, "botsort": BOTSORT}
14
14
 
15
15
 
16
16
  def on_predict_start(predictor: object, persist: bool = False) -> None:
@@ -24,15 +24,15 @@ def on_predict_start(predictor: object, persist: bool = False) -> None:
24
24
  Raises:
25
25
  AssertionError: If the tracker_type is not 'bytetrack' or 'botsort'.
26
26
  """
27
- if predictor.args.task == 'obb':
28
- raise NotImplementedError('ERROR ❌ OBB task does not support track mode!')
29
- if hasattr(predictor, 'trackers') and persist:
27
+ if predictor.args.task == "obb":
28
+ raise NotImplementedError("ERROR ❌ OBB task does not support track mode!")
29
+ if hasattr(predictor, "trackers") and persist:
30
30
  return
31
31
 
32
32
  tracker = check_yaml(predictor.args.tracker)
33
33
  cfg = IterableSimpleNamespace(**yaml_load(tracker))
34
34
 
35
- if cfg.tracker_type not in ['bytetrack', 'botsort']:
35
+ if cfg.tracker_type not in ["bytetrack", "botsort"]:
36
36
  raise AssertionError(f"Only 'bytetrack' and 'botsort' are supported for now, but got '{cfg.tracker_type}'")
37
37
 
38
38
  trackers = []
@@ -76,5 +76,5 @@ def register_tracker(model: object, persist: bool) -> None:
76
76
  model (object): The model object to register tracking callbacks for.
77
77
  persist (bool): Whether to persist the trackers if they already exist.
78
78
  """
79
- model.add_callback('on_predict_start', partial(on_predict_start, persist=persist))
80
- model.add_callback('on_predict_postprocess_end', partial(on_predict_postprocess_end, persist=persist))
79
+ model.add_callback("on_predict_start", partial(on_predict_start, persist=persist))
80
+ model.add_callback("on_predict_postprocess_end", partial(on_predict_postprocess_end, persist=persist))
@@ -33,7 +33,7 @@ class GMC:
33
33
  applySparseOptFlow(self, raw_frame, detections=None): Applies the Sparse Optical Flow method to a raw frame.
34
34
  """
35
35
 
36
- def __init__(self, method: str = 'sparseOptFlow', downscale: int = 2) -> None:
36
+ def __init__(self, method: str = "sparseOptFlow", downscale: int = 2) -> None:
37
37
  """
38
38
  Initialize a video tracker with specified parameters.
39
39
 
@@ -46,34 +46,31 @@ class GMC:
46
46
  self.method = method
47
47
  self.downscale = max(1, int(downscale))
48
48
 
49
- if self.method == 'orb':
49
+ if self.method == "orb":
50
50
  self.detector = cv2.FastFeatureDetector_create(20)
51
51
  self.extractor = cv2.ORB_create()
52
52
  self.matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
53
53
 
54
- elif self.method == 'sift':
54
+ elif self.method == "sift":
55
55
  self.detector = cv2.SIFT_create(nOctaveLayers=3, contrastThreshold=0.02, edgeThreshold=20)
56
56
  self.extractor = cv2.SIFT_create(nOctaveLayers=3, contrastThreshold=0.02, edgeThreshold=20)
57
57
  self.matcher = cv2.BFMatcher(cv2.NORM_L2)
58
58
 
59
- elif self.method == 'ecc':
59
+ elif self.method == "ecc":
60
60
  number_of_iterations = 5000
61
61
  termination_eps = 1e-6
62
62
  self.warp_mode = cv2.MOTION_EUCLIDEAN
63
63
  self.criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps)
64
64
 
65
- elif self.method == 'sparseOptFlow':
66
- self.feature_params = dict(maxCorners=1000,
67
- qualityLevel=0.01,
68
- minDistance=1,
69
- blockSize=3,
70
- useHarrisDetector=False,
71
- k=0.04)
65
+ elif self.method == "sparseOptFlow":
66
+ self.feature_params = dict(
67
+ maxCorners=1000, qualityLevel=0.01, minDistance=1, blockSize=3, useHarrisDetector=False, k=0.04
68
+ )
72
69
 
73
- elif self.method in ['none', 'None', None]:
70
+ elif self.method in ["none", "None", None]:
74
71
  self.method = None
75
72
  else:
76
- raise ValueError(f'Error: Unknown GMC method:{method}')
73
+ raise ValueError(f"Error: Unknown GMC method:{method}")
77
74
 
78
75
  self.prevFrame = None
79
76
  self.prevKeyPoints = None
@@ -97,11 +94,11 @@ class GMC:
97
94
  array([[1, 2, 3],
98
95
  [4, 5, 6]])
99
96
  """
100
- if self.method in ['orb', 'sift']:
97
+ if self.method in ["orb", "sift"]:
101
98
  return self.applyFeatures(raw_frame, detections)
102
- elif self.method == 'ecc':
99
+ elif self.method == "ecc":
103
100
  return self.applyEcc(raw_frame, detections)
104
- elif self.method == 'sparseOptFlow':
101
+ elif self.method == "sparseOptFlow":
105
102
  return self.applySparseOptFlow(raw_frame, detections)
106
103
  else:
107
104
  return np.eye(2, 3)
@@ -149,7 +146,7 @@ class GMC:
149
146
  try:
150
147
  (cc, H) = cv2.findTransformECC(self.prevFrame, frame, H, self.warp_mode, self.criteria, None, 1)
151
148
  except Exception as e:
152
- LOGGER.warning(f'WARNING: find transform failed. Set warp as identity {e}')
149
+ LOGGER.warning(f"WARNING: find transform failed. Set warp as identity {e}")
153
150
 
154
151
  return H
155
152
 
@@ -182,11 +179,11 @@ class GMC:
182
179
 
183
180
  # Find the keypoints
184
181
  mask = np.zeros_like(frame)
185
- mask[int(0.02 * height):int(0.98 * height), int(0.02 * width):int(0.98 * width)] = 255
182
+ mask[int(0.02 * height) : int(0.98 * height), int(0.02 * width) : int(0.98 * width)] = 255
186
183
  if detections is not None:
187
184
  for det in detections:
188
185
  tlbr = (det[:4] / self.downscale).astype(np.int_)
189
- mask[tlbr[1]:tlbr[3], tlbr[0]:tlbr[2]] = 0
186
+ mask[tlbr[1] : tlbr[3], tlbr[0] : tlbr[2]] = 0
190
187
 
191
188
  keypoints = self.detector.detect(frame, mask)
192
189
 
@@ -228,11 +225,14 @@ class GMC:
228
225
  prevKeyPointLocation = self.prevKeyPoints[m.queryIdx].pt
229
226
  currKeyPointLocation = keypoints[m.trainIdx].pt
230
227
 
231
- spatialDistance = (prevKeyPointLocation[0] - currKeyPointLocation[0],
232
- prevKeyPointLocation[1] - currKeyPointLocation[1])
228
+ spatialDistance = (
229
+ prevKeyPointLocation[0] - currKeyPointLocation[0],
230
+ prevKeyPointLocation[1] - currKeyPointLocation[1],
231
+ )
233
232
 
234
- if (np.abs(spatialDistance[0]) < maxSpatialDistance[0]) and \
235
- (np.abs(spatialDistance[1]) < maxSpatialDistance[1]):
233
+ if (np.abs(spatialDistance[0]) < maxSpatialDistance[0]) and (
234
+ np.abs(spatialDistance[1]) < maxSpatialDistance[1]
235
+ ):
236
236
  spatialDistances.append(spatialDistance)
237
237
  matches.append(m)
238
238
 
@@ -283,7 +283,7 @@ class GMC:
283
283
  H[0, 2] *= self.downscale
284
284
  H[1, 2] *= self.downscale
285
285
  else:
286
- LOGGER.warning('WARNING: not enough matching points')
286
+ LOGGER.warning("WARNING: not enough matching points")
287
287
 
288
288
  # Store to next iteration
289
289
  self.prevFrame = frame.copy()
@@ -350,7 +350,7 @@ class GMC:
350
350
  H[0, 2] *= self.downscale
351
351
  H[1, 2] *= self.downscale
352
352
  else:
353
- LOGGER.warning('WARNING: not enough matching points')
353
+ LOGGER.warning("WARNING: not enough matching points")
354
354
 
355
355
  self.prevFrame = frame.copy()
356
356
  self.prevKeyPoints = copy.copy(keypoints)
@@ -17,7 +17,7 @@ class KalmanFilterXYAH:
17
17
 
18
18
  def __init__(self):
19
19
  """Initialize Kalman filter model matrices with motion and observation uncertainty weights."""
20
- ndim, dt = 4, 1.
20
+ ndim, dt = 4, 1.0
21
21
 
22
22
  # Create Kalman filter model matrices
23
23
  self._motion_mat = np.eye(2 * ndim, 2 * ndim)
@@ -27,8 +27,8 @@ class KalmanFilterXYAH:
27
27
 
28
28
  # Motion and observation uncertainty are chosen relative to the current state estimate. These weights control
29
29
  # the amount of uncertainty in the model.
30
- self._std_weight_position = 1. / 20
31
- self._std_weight_velocity = 1. / 160
30
+ self._std_weight_position = 1.0 / 20
31
+ self._std_weight_velocity = 1.0 / 160
32
32
 
33
33
  def initiate(self, measurement: np.ndarray) -> tuple:
34
34
  """
@@ -47,9 +47,15 @@ class KalmanFilterXYAH:
47
47
  mean = np.r_[mean_pos, mean_vel]
48
48
 
49
49
  std = [
50
- 2 * self._std_weight_position * measurement[3], 2 * self._std_weight_position * measurement[3], 1e-2,
51
- 2 * self._std_weight_position * measurement[3], 10 * self._std_weight_velocity * measurement[3],
52
- 10 * self._std_weight_velocity * measurement[3], 1e-5, 10 * self._std_weight_velocity * measurement[3]]
50
+ 2 * self._std_weight_position * measurement[3],
51
+ 2 * self._std_weight_position * measurement[3],
52
+ 1e-2,
53
+ 2 * self._std_weight_position * measurement[3],
54
+ 10 * self._std_weight_velocity * measurement[3],
55
+ 10 * self._std_weight_velocity * measurement[3],
56
+ 1e-5,
57
+ 10 * self._std_weight_velocity * measurement[3],
58
+ ]
53
59
  covariance = np.diag(np.square(std))
54
60
  return mean, covariance
55
61
 
@@ -66,11 +72,17 @@ class KalmanFilterXYAH:
66
72
  velocities are initialized to 0 mean.
67
73
  """
68
74
  std_pos = [
69
- self._std_weight_position * mean[3], self._std_weight_position * mean[3], 1e-2,
70
- self._std_weight_position * mean[3]]
75
+ self._std_weight_position * mean[3],
76
+ self._std_weight_position * mean[3],
77
+ 1e-2,
78
+ self._std_weight_position * mean[3],
79
+ ]
71
80
  std_vel = [
72
- self._std_weight_velocity * mean[3], self._std_weight_velocity * mean[3], 1e-5,
73
- self._std_weight_velocity * mean[3]]
81
+ self._std_weight_velocity * mean[3],
82
+ self._std_weight_velocity * mean[3],
83
+ 1e-5,
84
+ self._std_weight_velocity * mean[3],
85
+ ]
74
86
  motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))
75
87
 
76
88
  mean = np.dot(mean, self._motion_mat.T)
@@ -90,8 +102,11 @@ class KalmanFilterXYAH:
90
102
  (tuple[ndarray, ndarray]): Returns the projected mean and covariance matrix of the given state estimate.
91
103
  """
92
104
  std = [
93
- self._std_weight_position * mean[3], self._std_weight_position * mean[3], 1e-1,
94
- self._std_weight_position * mean[3]]
105
+ self._std_weight_position * mean[3],
106
+ self._std_weight_position * mean[3],
107
+ 1e-1,
108
+ self._std_weight_position * mean[3],
109
+ ]
95
110
  innovation_cov = np.diag(np.square(std))
96
111
 
97
112
  mean = np.dot(self._update_mat, mean)
@@ -111,11 +126,17 @@ class KalmanFilterXYAH:
111
126
  velocities are initialized to 0 mean.
112
127
  """
113
128
  std_pos = [
114
- self._std_weight_position * mean[:, 3], self._std_weight_position * mean[:, 3],
115
- 1e-2 * np.ones_like(mean[:, 3]), self._std_weight_position * mean[:, 3]]
129
+ self._std_weight_position * mean[:, 3],
130
+ self._std_weight_position * mean[:, 3],
131
+ 1e-2 * np.ones_like(mean[:, 3]),
132
+ self._std_weight_position * mean[:, 3],
133
+ ]
116
134
  std_vel = [
117
- self._std_weight_velocity * mean[:, 3], self._std_weight_velocity * mean[:, 3],
118
- 1e-5 * np.ones_like(mean[:, 3]), self._std_weight_velocity * mean[:, 3]]
135
+ self._std_weight_velocity * mean[:, 3],
136
+ self._std_weight_velocity * mean[:, 3],
137
+ 1e-5 * np.ones_like(mean[:, 3]),
138
+ self._std_weight_velocity * mean[:, 3],
139
+ ]
119
140
  sqr = np.square(np.r_[std_pos, std_vel]).T
120
141
 
121
142
  motion_cov = [np.diag(sqr[i]) for i in range(len(mean))]
@@ -143,21 +164,23 @@ class KalmanFilterXYAH:
143
164
  projected_mean, projected_cov = self.project(mean, covariance)
144
165
 
145
166
  chol_factor, lower = scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)
146
- kalman_gain = scipy.linalg.cho_solve((chol_factor, lower),
147
- np.dot(covariance, self._update_mat.T).T,
148
- check_finite=False).T
167
+ kalman_gain = scipy.linalg.cho_solve(
168
+ (chol_factor, lower), np.dot(covariance, self._update_mat.T).T, check_finite=False
169
+ ).T
149
170
  innovation = measurement - projected_mean
150
171
 
151
172
  new_mean = mean + np.dot(innovation, kalman_gain.T)
152
173
  new_covariance = covariance - np.linalg.multi_dot((kalman_gain, projected_cov, kalman_gain.T))
153
174
  return new_mean, new_covariance
154
175
 
155
- def gating_distance(self,
156
- mean: np.ndarray,
157
- covariance: np.ndarray,
158
- measurements: np.ndarray,
159
- only_position: bool = False,
160
- metric: str = 'maha') -> np.ndarray:
176
+ def gating_distance(
177
+ self,
178
+ mean: np.ndarray,
179
+ covariance: np.ndarray,
180
+ measurements: np.ndarray,
181
+ only_position: bool = False,
182
+ metric: str = "maha",
183
+ ) -> np.ndarray:
161
184
  """
162
185
  Compute gating distance between state distribution and measurements. A suitable distance threshold can be
163
186
  obtained from `chi2inv95`. If `only_position` is False, the chi-square distribution has 4 degrees of freedom,
@@ -183,14 +206,14 @@ class KalmanFilterXYAH:
183
206
  measurements = measurements[:, :2]
184
207
 
185
208
  d = measurements - mean
186
- if metric == 'gaussian':
209
+ if metric == "gaussian":
187
210
  return np.sum(d * d, axis=1)
188
- elif metric == 'maha':
211
+ elif metric == "maha":
189
212
  cholesky_factor = np.linalg.cholesky(covariance)
190
213
  z = scipy.linalg.solve_triangular(cholesky_factor, d.T, lower=True, check_finite=False, overwrite_b=True)
191
214
  return np.sum(z * z, axis=0) # square maha
192
215
  else:
193
- raise ValueError('Invalid distance metric')
216
+ raise ValueError("Invalid distance metric")
194
217
 
195
218
 
196
219
  class KalmanFilterXYWH(KalmanFilterXYAH):
@@ -220,10 +243,15 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
220
243
  mean = np.r_[mean_pos, mean_vel]
221
244
 
222
245
  std = [
223
- 2 * self._std_weight_position * measurement[2], 2 * self._std_weight_position * measurement[3],
224
- 2 * self._std_weight_position * measurement[2], 2 * self._std_weight_position * measurement[3],
225
- 10 * self._std_weight_velocity * measurement[2], 10 * self._std_weight_velocity * measurement[3],
226
- 10 * self._std_weight_velocity * measurement[2], 10 * self._std_weight_velocity * measurement[3]]
246
+ 2 * self._std_weight_position * measurement[2],
247
+ 2 * self._std_weight_position * measurement[3],
248
+ 2 * self._std_weight_position * measurement[2],
249
+ 2 * self._std_weight_position * measurement[3],
250
+ 10 * self._std_weight_velocity * measurement[2],
251
+ 10 * self._std_weight_velocity * measurement[3],
252
+ 10 * self._std_weight_velocity * measurement[2],
253
+ 10 * self._std_weight_velocity * measurement[3],
254
+ ]
227
255
  covariance = np.diag(np.square(std))
228
256
  return mean, covariance
229
257
 
@@ -240,11 +268,17 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
240
268
  velocities are initialized to 0 mean.
241
269
  """
242
270
  std_pos = [
243
- self._std_weight_position * mean[2], self._std_weight_position * mean[3],
244
- self._std_weight_position * mean[2], self._std_weight_position * mean[3]]
271
+ self._std_weight_position * mean[2],
272
+ self._std_weight_position * mean[3],
273
+ self._std_weight_position * mean[2],
274
+ self._std_weight_position * mean[3],
275
+ ]
245
276
  std_vel = [
246
- self._std_weight_velocity * mean[2], self._std_weight_velocity * mean[3],
247
- self._std_weight_velocity * mean[2], self._std_weight_velocity * mean[3]]
277
+ self._std_weight_velocity * mean[2],
278
+ self._std_weight_velocity * mean[3],
279
+ self._std_weight_velocity * mean[2],
280
+ self._std_weight_velocity * mean[3],
281
+ ]
248
282
  motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))
249
283
 
250
284
  mean = np.dot(mean, self._motion_mat.T)
@@ -264,8 +298,11 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
264
298
  (tuple[ndarray, ndarray]): Returns the projected mean and covariance matrix of the given state estimate.
265
299
  """
266
300
  std = [
267
- self._std_weight_position * mean[2], self._std_weight_position * mean[3],
268
- self._std_weight_position * mean[2], self._std_weight_position * mean[3]]
301
+ self._std_weight_position * mean[2],
302
+ self._std_weight_position * mean[3],
303
+ self._std_weight_position * mean[2],
304
+ self._std_weight_position * mean[3],
305
+ ]
269
306
  innovation_cov = np.diag(np.square(std))
270
307
 
271
308
  mean = np.dot(self._update_mat, mean)
@@ -285,11 +322,17 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
285
322
  velocities are initialized to 0 mean.
286
323
  """
287
324
  std_pos = [
288
- self._std_weight_position * mean[:, 2], self._std_weight_position * mean[:, 3],
289
- self._std_weight_position * mean[:, 2], self._std_weight_position * mean[:, 3]]
325
+ self._std_weight_position * mean[:, 2],
326
+ self._std_weight_position * mean[:, 3],
327
+ self._std_weight_position * mean[:, 2],
328
+ self._std_weight_position * mean[:, 3],
329
+ ]
290
330
  std_vel = [
291
- self._std_weight_velocity * mean[:, 2], self._std_weight_velocity * mean[:, 3],
292
- self._std_weight_velocity * mean[:, 2], self._std_weight_velocity * mean[:, 3]]
331
+ self._std_weight_velocity * mean[:, 2],
332
+ self._std_weight_velocity * mean[:, 3],
333
+ self._std_weight_velocity * mean[:, 2],
334
+ self._std_weight_velocity * mean[:, 3],
335
+ ]
293
336
  sqr = np.square(np.r_[std_pos, std_vel]).T
294
337
 
295
338
  motion_cov = [np.diag(sqr[i]) for i in range(len(mean))]
@@ -13,7 +13,7 @@ try:
13
13
  except (ImportError, AssertionError, AttributeError):
14
14
  from ultralytics.utils.checks import check_requirements
15
15
 
16
- check_requirements('lapx>=0.5.2') # update to lap package from https://github.com/rathaROG/lapx
16
+ check_requirements("lapx>=0.5.2") # update to lap package from https://github.com/rathaROG/lapx
17
17
  import lap
18
18
 
19
19
 
@@ -70,8 +70,9 @@ def iou_distance(atracks: list, btracks: list) -> np.ndarray:
70
70
  (np.ndarray): Cost matrix computed based on IoU.
71
71
  """
72
72
 
73
- if (len(atracks) > 0 and isinstance(atracks[0], np.ndarray)) \
74
- or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):
73
+ if (len(atracks) > 0 and isinstance(atracks[0], np.ndarray)) or (
74
+ len(btracks) > 0 and isinstance(btracks[0], np.ndarray)
75
+ ):
75
76
  atlbrs = atracks
76
77
  btlbrs = btracks
77
78
  else:
@@ -80,13 +81,13 @@ def iou_distance(atracks: list, btracks: list) -> np.ndarray:
80
81
 
81
82
  ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float32)
82
83
  if len(atlbrs) and len(btlbrs):
83
- ious = bbox_ioa(np.ascontiguousarray(atlbrs, dtype=np.float32),
84
- np.ascontiguousarray(btlbrs, dtype=np.float32),
85
- iou=True)
84
+ ious = bbox_ioa(
85
+ np.ascontiguousarray(atlbrs, dtype=np.float32), np.ascontiguousarray(btlbrs, dtype=np.float32), iou=True
86
+ )
86
87
  return 1 - ious # cost matrix
87
88
 
88
89
 
89
- def embedding_distance(tracks: list, detections: list, metric: str = 'cosine') -> np.ndarray:
90
+ def embedding_distance(tracks: list, detections: list, metric: str = "cosine") -> np.ndarray:
90
91
  """
91
92
  Compute distance between tracks and detections based on embeddings.
92
93