dgenerate-ultralytics-headless 8.3.137__py3-none-any.whl → 8.3.224__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.
Files changed (215) hide show
  1. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/METADATA +41 -34
  2. dgenerate_ultralytics_headless-8.3.224.dist-info/RECORD +285 -0
  3. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/WHEEL +1 -1
  4. tests/__init__.py +7 -6
  5. tests/conftest.py +15 -39
  6. tests/test_cli.py +17 -17
  7. tests/test_cuda.py +17 -8
  8. tests/test_engine.py +36 -10
  9. tests/test_exports.py +98 -37
  10. tests/test_integrations.py +12 -15
  11. tests/test_python.py +126 -82
  12. tests/test_solutions.py +319 -135
  13. ultralytics/__init__.py +27 -9
  14. ultralytics/cfg/__init__.py +83 -87
  15. ultralytics/cfg/datasets/Argoverse.yaml +4 -4
  16. ultralytics/cfg/datasets/DOTAv1.5.yaml +2 -2
  17. ultralytics/cfg/datasets/DOTAv1.yaml +2 -2
  18. ultralytics/cfg/datasets/GlobalWheat2020.yaml +2 -2
  19. ultralytics/cfg/datasets/HomeObjects-3K.yaml +4 -5
  20. ultralytics/cfg/datasets/ImageNet.yaml +3 -3
  21. ultralytics/cfg/datasets/Objects365.yaml +24 -20
  22. ultralytics/cfg/datasets/SKU-110K.yaml +9 -9
  23. ultralytics/cfg/datasets/VOC.yaml +10 -13
  24. ultralytics/cfg/datasets/VisDrone.yaml +43 -33
  25. ultralytics/cfg/datasets/african-wildlife.yaml +5 -5
  26. ultralytics/cfg/datasets/brain-tumor.yaml +4 -5
  27. ultralytics/cfg/datasets/carparts-seg.yaml +5 -5
  28. ultralytics/cfg/datasets/coco-pose.yaml +26 -4
  29. ultralytics/cfg/datasets/coco.yaml +4 -4
  30. ultralytics/cfg/datasets/coco128-seg.yaml +2 -2
  31. ultralytics/cfg/datasets/coco128.yaml +2 -2
  32. ultralytics/cfg/datasets/coco8-grayscale.yaml +103 -0
  33. ultralytics/cfg/datasets/coco8-multispectral.yaml +2 -2
  34. ultralytics/cfg/datasets/coco8-pose.yaml +23 -2
  35. ultralytics/cfg/datasets/coco8-seg.yaml +2 -2
  36. ultralytics/cfg/datasets/coco8.yaml +2 -2
  37. ultralytics/cfg/datasets/construction-ppe.yaml +32 -0
  38. ultralytics/cfg/datasets/crack-seg.yaml +5 -5
  39. ultralytics/cfg/datasets/dog-pose.yaml +32 -4
  40. ultralytics/cfg/datasets/dota8-multispectral.yaml +2 -2
  41. ultralytics/cfg/datasets/dota8.yaml +2 -2
  42. ultralytics/cfg/datasets/hand-keypoints.yaml +29 -4
  43. ultralytics/cfg/datasets/lvis.yaml +9 -9
  44. ultralytics/cfg/datasets/medical-pills.yaml +4 -5
  45. ultralytics/cfg/datasets/open-images-v7.yaml +7 -10
  46. ultralytics/cfg/datasets/package-seg.yaml +5 -5
  47. ultralytics/cfg/datasets/signature.yaml +4 -4
  48. ultralytics/cfg/datasets/tiger-pose.yaml +20 -4
  49. ultralytics/cfg/datasets/xView.yaml +5 -5
  50. ultralytics/cfg/default.yaml +96 -93
  51. ultralytics/cfg/trackers/botsort.yaml +16 -17
  52. ultralytics/cfg/trackers/bytetrack.yaml +9 -11
  53. ultralytics/data/__init__.py +4 -4
  54. ultralytics/data/annotator.py +12 -12
  55. ultralytics/data/augment.py +531 -564
  56. ultralytics/data/base.py +76 -81
  57. ultralytics/data/build.py +206 -42
  58. ultralytics/data/converter.py +179 -78
  59. ultralytics/data/dataset.py +121 -121
  60. ultralytics/data/loaders.py +114 -91
  61. ultralytics/data/split.py +28 -15
  62. ultralytics/data/split_dota.py +67 -48
  63. ultralytics/data/utils.py +110 -89
  64. ultralytics/engine/exporter.py +422 -460
  65. ultralytics/engine/model.py +224 -252
  66. ultralytics/engine/predictor.py +94 -89
  67. ultralytics/engine/results.py +345 -595
  68. ultralytics/engine/trainer.py +231 -134
  69. ultralytics/engine/tuner.py +279 -73
  70. ultralytics/engine/validator.py +53 -46
  71. ultralytics/hub/__init__.py +26 -28
  72. ultralytics/hub/auth.py +30 -16
  73. ultralytics/hub/google/__init__.py +34 -36
  74. ultralytics/hub/session.py +53 -77
  75. ultralytics/hub/utils.py +23 -109
  76. ultralytics/models/__init__.py +1 -1
  77. ultralytics/models/fastsam/__init__.py +1 -1
  78. ultralytics/models/fastsam/model.py +36 -18
  79. ultralytics/models/fastsam/predict.py +33 -44
  80. ultralytics/models/fastsam/utils.py +4 -5
  81. ultralytics/models/fastsam/val.py +12 -14
  82. ultralytics/models/nas/__init__.py +1 -1
  83. ultralytics/models/nas/model.py +16 -20
  84. ultralytics/models/nas/predict.py +12 -14
  85. ultralytics/models/nas/val.py +4 -5
  86. ultralytics/models/rtdetr/__init__.py +1 -1
  87. ultralytics/models/rtdetr/model.py +9 -9
  88. ultralytics/models/rtdetr/predict.py +22 -17
  89. ultralytics/models/rtdetr/train.py +20 -16
  90. ultralytics/models/rtdetr/val.py +79 -59
  91. ultralytics/models/sam/__init__.py +8 -2
  92. ultralytics/models/sam/amg.py +53 -38
  93. ultralytics/models/sam/build.py +29 -31
  94. ultralytics/models/sam/model.py +33 -38
  95. ultralytics/models/sam/modules/blocks.py +159 -182
  96. ultralytics/models/sam/modules/decoders.py +38 -47
  97. ultralytics/models/sam/modules/encoders.py +114 -133
  98. ultralytics/models/sam/modules/memory_attention.py +38 -31
  99. ultralytics/models/sam/modules/sam.py +114 -93
  100. ultralytics/models/sam/modules/tiny_encoder.py +268 -291
  101. ultralytics/models/sam/modules/transformer.py +59 -66
  102. ultralytics/models/sam/modules/utils.py +55 -72
  103. ultralytics/models/sam/predict.py +745 -341
  104. ultralytics/models/utils/loss.py +118 -107
  105. ultralytics/models/utils/ops.py +118 -71
  106. ultralytics/models/yolo/__init__.py +1 -1
  107. ultralytics/models/yolo/classify/predict.py +28 -26
  108. ultralytics/models/yolo/classify/train.py +50 -81
  109. ultralytics/models/yolo/classify/val.py +68 -61
  110. ultralytics/models/yolo/detect/predict.py +12 -15
  111. ultralytics/models/yolo/detect/train.py +56 -46
  112. ultralytics/models/yolo/detect/val.py +279 -223
  113. ultralytics/models/yolo/model.py +167 -86
  114. ultralytics/models/yolo/obb/predict.py +7 -11
  115. ultralytics/models/yolo/obb/train.py +23 -25
  116. ultralytics/models/yolo/obb/val.py +107 -99
  117. ultralytics/models/yolo/pose/__init__.py +1 -1
  118. ultralytics/models/yolo/pose/predict.py +12 -14
  119. ultralytics/models/yolo/pose/train.py +31 -69
  120. ultralytics/models/yolo/pose/val.py +119 -254
  121. ultralytics/models/yolo/segment/predict.py +21 -25
  122. ultralytics/models/yolo/segment/train.py +12 -66
  123. ultralytics/models/yolo/segment/val.py +126 -305
  124. ultralytics/models/yolo/world/train.py +53 -45
  125. ultralytics/models/yolo/world/train_world.py +51 -32
  126. ultralytics/models/yolo/yoloe/__init__.py +7 -7
  127. ultralytics/models/yolo/yoloe/predict.py +30 -37
  128. ultralytics/models/yolo/yoloe/train.py +89 -71
  129. ultralytics/models/yolo/yoloe/train_seg.py +15 -17
  130. ultralytics/models/yolo/yoloe/val.py +56 -41
  131. ultralytics/nn/__init__.py +9 -11
  132. ultralytics/nn/autobackend.py +179 -107
  133. ultralytics/nn/modules/__init__.py +67 -67
  134. ultralytics/nn/modules/activation.py +8 -7
  135. ultralytics/nn/modules/block.py +302 -323
  136. ultralytics/nn/modules/conv.py +61 -104
  137. ultralytics/nn/modules/head.py +488 -186
  138. ultralytics/nn/modules/transformer.py +183 -123
  139. ultralytics/nn/modules/utils.py +15 -20
  140. ultralytics/nn/tasks.py +327 -203
  141. ultralytics/nn/text_model.py +81 -65
  142. ultralytics/py.typed +1 -0
  143. ultralytics/solutions/__init__.py +12 -12
  144. ultralytics/solutions/ai_gym.py +19 -27
  145. ultralytics/solutions/analytics.py +36 -26
  146. ultralytics/solutions/config.py +29 -28
  147. ultralytics/solutions/distance_calculation.py +23 -24
  148. ultralytics/solutions/heatmap.py +17 -19
  149. ultralytics/solutions/instance_segmentation.py +21 -19
  150. ultralytics/solutions/object_blurrer.py +16 -17
  151. ultralytics/solutions/object_counter.py +48 -53
  152. ultralytics/solutions/object_cropper.py +22 -16
  153. ultralytics/solutions/parking_management.py +61 -58
  154. ultralytics/solutions/queue_management.py +19 -19
  155. ultralytics/solutions/region_counter.py +63 -50
  156. ultralytics/solutions/security_alarm.py +22 -25
  157. ultralytics/solutions/similarity_search.py +107 -60
  158. ultralytics/solutions/solutions.py +343 -262
  159. ultralytics/solutions/speed_estimation.py +35 -31
  160. ultralytics/solutions/streamlit_inference.py +104 -40
  161. ultralytics/solutions/templates/similarity-search.html +31 -24
  162. ultralytics/solutions/trackzone.py +24 -24
  163. ultralytics/solutions/vision_eye.py +11 -12
  164. ultralytics/trackers/__init__.py +1 -1
  165. ultralytics/trackers/basetrack.py +18 -27
  166. ultralytics/trackers/bot_sort.py +48 -39
  167. ultralytics/trackers/byte_tracker.py +94 -94
  168. ultralytics/trackers/track.py +7 -16
  169. ultralytics/trackers/utils/gmc.py +37 -69
  170. ultralytics/trackers/utils/kalman_filter.py +68 -76
  171. ultralytics/trackers/utils/matching.py +13 -17
  172. ultralytics/utils/__init__.py +251 -275
  173. ultralytics/utils/autobatch.py +19 -7
  174. ultralytics/utils/autodevice.py +68 -38
  175. ultralytics/utils/benchmarks.py +169 -130
  176. ultralytics/utils/callbacks/base.py +12 -13
  177. ultralytics/utils/callbacks/clearml.py +14 -15
  178. ultralytics/utils/callbacks/comet.py +139 -66
  179. ultralytics/utils/callbacks/dvc.py +19 -27
  180. ultralytics/utils/callbacks/hub.py +8 -6
  181. ultralytics/utils/callbacks/mlflow.py +6 -10
  182. ultralytics/utils/callbacks/neptune.py +11 -19
  183. ultralytics/utils/callbacks/platform.py +73 -0
  184. ultralytics/utils/callbacks/raytune.py +3 -4
  185. ultralytics/utils/callbacks/tensorboard.py +9 -12
  186. ultralytics/utils/callbacks/wb.py +33 -30
  187. ultralytics/utils/checks.py +163 -114
  188. ultralytics/utils/cpu.py +89 -0
  189. ultralytics/utils/dist.py +24 -20
  190. ultralytics/utils/downloads.py +176 -146
  191. ultralytics/utils/errors.py +11 -13
  192. ultralytics/utils/events.py +113 -0
  193. ultralytics/utils/export/__init__.py +7 -0
  194. ultralytics/utils/{export.py → export/engine.py} +81 -63
  195. ultralytics/utils/export/imx.py +294 -0
  196. ultralytics/utils/export/tensorflow.py +217 -0
  197. ultralytics/utils/files.py +33 -36
  198. ultralytics/utils/git.py +137 -0
  199. ultralytics/utils/instance.py +105 -120
  200. ultralytics/utils/logger.py +404 -0
  201. ultralytics/utils/loss.py +99 -61
  202. ultralytics/utils/metrics.py +649 -478
  203. ultralytics/utils/nms.py +337 -0
  204. ultralytics/utils/ops.py +263 -451
  205. ultralytics/utils/patches.py +70 -31
  206. ultralytics/utils/plotting.py +253 -223
  207. ultralytics/utils/tal.py +48 -61
  208. ultralytics/utils/torch_utils.py +244 -251
  209. ultralytics/utils/tqdm.py +438 -0
  210. ultralytics/utils/triton.py +22 -23
  211. ultralytics/utils/tuner.py +11 -10
  212. dgenerate_ultralytics_headless-8.3.137.dist-info/RECORD +0 -272
  213. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/entry_points.txt +0 -0
  214. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/licenses/LICENSE +0 -0
  215. {dgenerate_ultralytics_headless-8.3.137.dist-info → dgenerate_ultralytics_headless-8.3.224.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import copy
4
6
 
5
7
  import cv2
@@ -9,8 +11,7 @@ from ultralytics.utils import LOGGER
9
11
 
10
12
 
11
13
  class GMC:
12
- """
13
- Generalized Motion Compensation (GMC) class for tracking and object detection in video frames.
14
+ """Generalized Motion Compensation (GMC) class for tracking and object detection in video frames.
14
15
 
15
16
  This class provides methods for tracking and detecting objects based on several tracking algorithms including ORB,
16
17
  SIFT, ECC, and Sparse Optical Flow. It also supports downscaling of frames for computational efficiency.
@@ -41,8 +42,7 @@ class GMC:
41
42
  """
42
43
 
43
44
  def __init__(self, method: str = "sparseOptFlow", downscale: int = 2) -> None:
44
- """
45
- Initialize a Generalized Motion Compensation (GMC) object with tracking method and downscale factor.
45
+ """Initialize a Generalized Motion Compensation (GMC) object with tracking method and downscale factor.
46
46
 
47
47
  Args:
48
48
  method (str): The tracking method to use. Options include 'orb', 'sift', 'ecc', 'sparseOptFlow', 'none'.
@@ -88,13 +88,12 @@ class GMC:
88
88
  self.prevDescriptors = None
89
89
  self.initializedFirstFrame = False
90
90
 
91
- def apply(self, raw_frame: np.ndarray, detections: list = None) -> np.ndarray:
92
- """
93
- Apply object detection on a raw frame using the specified method.
91
+ def apply(self, raw_frame: np.ndarray, detections: list | None = None) -> np.ndarray:
92
+ """Apply object detection on a raw frame using the specified method.
94
93
 
95
94
  Args:
96
95
  raw_frame (np.ndarray): The raw frame to be processed, with shape (H, W, C).
97
- detections (List | None): List of detections to be used in the processing.
96
+ detections (list, optional): List of detections to be used in the processing.
98
97
 
99
98
  Returns:
100
99
  (np.ndarray): Transformation matrix with shape (2, 3).
@@ -116,8 +115,7 @@ class GMC:
116
115
  return np.eye(2, 3)
117
116
 
118
117
  def apply_ecc(self, raw_frame: np.ndarray) -> np.ndarray:
119
- """
120
- Apply the ECC (Enhanced Correlation Coefficient) algorithm to a raw frame for motion compensation.
118
+ """Apply the ECC (Enhanced Correlation Coefficient) algorithm to a raw frame for motion compensation.
121
119
 
122
120
  Args:
123
121
  raw_frame (np.ndarray): The raw frame to be processed, with shape (H, W, C).
@@ -136,23 +134,18 @@ class GMC:
136
134
  frame = cv2.cvtColor(raw_frame, cv2.COLOR_BGR2GRAY) if c == 3 else raw_frame
137
135
  H = np.eye(2, 3, dtype=np.float32)
138
136
 
139
- # Downscale image
137
+ # Downscale image for computational efficiency
140
138
  if self.downscale > 1.0:
141
139
  frame = cv2.GaussianBlur(frame, (3, 3), 1.5)
142
140
  frame = cv2.resize(frame, (width // self.downscale, height // self.downscale))
143
141
 
144
- # Handle first frame
142
+ # Handle first frame initialization
145
143
  if not self.initializedFirstFrame:
146
- # Initialize data
147
144
  self.prevFrame = frame.copy()
148
-
149
- # Initialization done
150
145
  self.initializedFirstFrame = True
151
-
152
146
  return H
153
147
 
154
- # Run the ECC algorithm. The results are stored in warp_matrix.
155
- # (cc, H) = cv2.findTransformECC(self.prevFrame, frame, H, self.warp_mode, self.criteria)
148
+ # Run the ECC algorithm to find transformation matrix
156
149
  try:
157
150
  (_, H) = cv2.findTransformECC(self.prevFrame, frame, H, self.warp_mode, self.criteria, None, 1)
158
151
  except Exception as e:
@@ -160,13 +153,12 @@ class GMC:
160
153
 
161
154
  return H
162
155
 
163
- def apply_features(self, raw_frame: np.ndarray, detections: list = None) -> np.ndarray:
164
- """
165
- Apply feature-based methods like ORB or SIFT to a raw frame.
156
+ def apply_features(self, raw_frame: np.ndarray, detections: list | None = None) -> np.ndarray:
157
+ """Apply feature-based methods like ORB or SIFT to a raw frame.
166
158
 
167
159
  Args:
168
160
  raw_frame (np.ndarray): The raw frame to be processed, with shape (H, W, C).
169
- detections (List | None): List of detections to be used in the processing.
161
+ detections (list, optional): List of detections to be used in the processing.
170
162
 
171
163
  Returns:
172
164
  (np.ndarray): Transformation matrix with shape (2, 3).
@@ -182,55 +174,50 @@ class GMC:
182
174
  frame = cv2.cvtColor(raw_frame, cv2.COLOR_BGR2GRAY) if c == 3 else raw_frame
183
175
  H = np.eye(2, 3)
184
176
 
185
- # Downscale image
177
+ # Downscale image for computational efficiency
186
178
  if self.downscale > 1.0:
187
179
  frame = cv2.resize(frame, (width // self.downscale, height // self.downscale))
188
180
  width = width // self.downscale
189
181
  height = height // self.downscale
190
182
 
191
- # Find the keypoints
183
+ # Create mask for keypoint detection, excluding border regions
192
184
  mask = np.zeros_like(frame)
193
185
  mask[int(0.02 * height) : int(0.98 * height), int(0.02 * width) : int(0.98 * width)] = 255
186
+
187
+ # Exclude detection regions from mask to avoid tracking detected objects
194
188
  if detections is not None:
195
189
  for det in detections:
196
190
  tlbr = (det[:4] / self.downscale).astype(np.int_)
197
191
  mask[tlbr[1] : tlbr[3], tlbr[0] : tlbr[2]] = 0
198
192
 
193
+ # Find keypoints and compute descriptors
199
194
  keypoints = self.detector.detect(frame, mask)
200
-
201
- # Compute the descriptors
202
195
  keypoints, descriptors = self.extractor.compute(frame, keypoints)
203
196
 
204
- # Handle first frame
197
+ # Handle first frame initialization
205
198
  if not self.initializedFirstFrame:
206
- # Initialize data
207
199
  self.prevFrame = frame.copy()
208
200
  self.prevKeyPoints = copy.copy(keypoints)
209
201
  self.prevDescriptors = copy.copy(descriptors)
210
-
211
- # Initialization done
212
202
  self.initializedFirstFrame = True
213
-
214
203
  return H
215
204
 
216
- # Match descriptors
205
+ # Match descriptors between previous and current frame
217
206
  knnMatches = self.matcher.knnMatch(self.prevDescriptors, descriptors, 2)
218
207
 
219
- # Filter matches based on smallest spatial distance
208
+ # Filter matches based on spatial distance constraints
220
209
  matches = []
221
210
  spatialDistances = []
222
-
223
211
  maxSpatialDistance = 0.25 * np.array([width, height])
224
212
 
225
213
  # Handle empty matches case
226
214
  if len(knnMatches) == 0:
227
- # Store to next iteration
228
215
  self.prevFrame = frame.copy()
229
216
  self.prevKeyPoints = copy.copy(keypoints)
230
217
  self.prevDescriptors = copy.copy(descriptors)
231
-
232
218
  return H
233
219
 
220
+ # Apply Lowe's ratio test and spatial distance filtering
234
221
  for m, n in knnMatches:
235
222
  if m.distance < 0.9 * n.distance:
236
223
  prevKeyPointLocation = self.prevKeyPoints[m.queryIdx].pt
@@ -247,11 +234,12 @@ class GMC:
247
234
  spatialDistances.append(spatialDistance)
248
235
  matches.append(m)
249
236
 
237
+ # Filter outliers using statistical analysis
250
238
  meanSpatialDistances = np.mean(spatialDistances, 0)
251
239
  stdSpatialDistances = np.std(spatialDistances, 0)
252
-
253
240
  inliers = (spatialDistances - meanSpatialDistances) < 2.5 * stdSpatialDistances
254
241
 
242
+ # Extract good matches and corresponding points
255
243
  goodMatches = []
256
244
  prevPoints = []
257
245
  currPoints = []
@@ -264,39 +252,18 @@ class GMC:
264
252
  prevPoints = np.array(prevPoints)
265
253
  currPoints = np.array(currPoints)
266
254
 
267
- # Draw the keypoint matches on the output image
268
- # if False:
269
- # import matplotlib.pyplot as plt
270
- # matches_img = np.hstack((self.prevFrame, frame))
271
- # matches_img = cv2.cvtColor(matches_img, cv2.COLOR_GRAY2BGR)
272
- # W = self.prevFrame.shape[1]
273
- # for m in goodMatches:
274
- # prev_pt = np.array(self.prevKeyPoints[m.queryIdx].pt, dtype=np.int_)
275
- # curr_pt = np.array(keypoints[m.trainIdx].pt, dtype=np.int_)
276
- # curr_pt[0] += W
277
- # color = np.random.randint(0, 255, 3)
278
- # color = (int(color[0]), int(color[1]), int(color[2]))
279
- #
280
- # matches_img = cv2.line(matches_img, prev_pt, curr_pt, tuple(color), 1, cv2.LINE_AA)
281
- # matches_img = cv2.circle(matches_img, prev_pt, 2, tuple(color), -1)
282
- # matches_img = cv2.circle(matches_img, curr_pt, 2, tuple(color), -1)
283
- #
284
- # plt.figure()
285
- # plt.imshow(matches_img)
286
- # plt.show()
287
-
288
- # Find rigid matrix
255
+ # Estimate transformation matrix using RANSAC
289
256
  if prevPoints.shape[0] > 4:
290
257
  H, inliers = cv2.estimateAffinePartial2D(prevPoints, currPoints, cv2.RANSAC)
291
258
 
292
- # Handle downscale
259
+ # Scale translation components back to original resolution
293
260
  if self.downscale > 1.0:
294
261
  H[0, 2] *= self.downscale
295
262
  H[1, 2] *= self.downscale
296
263
  else:
297
264
  LOGGER.warning("not enough matching points")
298
265
 
299
- # Store to next iteration
266
+ # Store current frame data for next iteration
300
267
  self.prevFrame = frame.copy()
301
268
  self.prevKeyPoints = copy.copy(keypoints)
302
269
  self.prevDescriptors = copy.copy(descriptors)
@@ -304,8 +271,7 @@ class GMC:
304
271
  return H
305
272
 
306
273
  def apply_sparseoptflow(self, raw_frame: np.ndarray) -> np.ndarray:
307
- """
308
- Apply Sparse Optical Flow method to a raw frame.
274
+ """Apply Sparse Optical Flow method to a raw frame.
309
275
 
310
276
  Args:
311
277
  raw_frame (np.ndarray): The raw frame to be processed, with shape (H, W, C).
@@ -324,24 +290,24 @@ class GMC:
324
290
  frame = cv2.cvtColor(raw_frame, cv2.COLOR_BGR2GRAY) if c == 3 else raw_frame
325
291
  H = np.eye(2, 3)
326
292
 
327
- # Downscale image
293
+ # Downscale image for computational efficiency
328
294
  if self.downscale > 1.0:
329
295
  frame = cv2.resize(frame, (width // self.downscale, height // self.downscale))
330
296
 
331
- # Find the keypoints
297
+ # Find good features to track
332
298
  keypoints = cv2.goodFeaturesToTrack(frame, mask=None, **self.feature_params)
333
299
 
334
- # Handle first frame
300
+ # Handle first frame initialization
335
301
  if not self.initializedFirstFrame or self.prevKeyPoints is None:
336
302
  self.prevFrame = frame.copy()
337
303
  self.prevKeyPoints = copy.copy(keypoints)
338
304
  self.initializedFirstFrame = True
339
305
  return H
340
306
 
341
- # Find correspondences
307
+ # Calculate optical flow using Lucas-Kanade method
342
308
  matchedKeypoints, status, _ = cv2.calcOpticalFlowPyrLK(self.prevFrame, frame, self.prevKeyPoints, None)
343
309
 
344
- # Leave good correspondences only
310
+ # Extract successfully tracked points
345
311
  prevPoints = []
346
312
  currPoints = []
347
313
 
@@ -353,16 +319,18 @@ class GMC:
353
319
  prevPoints = np.array(prevPoints)
354
320
  currPoints = np.array(currPoints)
355
321
 
356
- # Find rigid matrix
322
+ # Estimate transformation matrix using RANSAC
357
323
  if (prevPoints.shape[0] > 4) and (prevPoints.shape[0] == currPoints.shape[0]):
358
324
  H, _ = cv2.estimateAffinePartial2D(prevPoints, currPoints, cv2.RANSAC)
359
325
 
326
+ # Scale translation components back to original resolution
360
327
  if self.downscale > 1.0:
361
328
  H[0, 2] *= self.downscale
362
329
  H[1, 2] *= self.downscale
363
330
  else:
364
331
  LOGGER.warning("not enough matching points")
365
332
 
333
+ # Store current frame data for next iteration
366
334
  self.prevFrame = frame.copy()
367
335
  self.prevKeyPoints = copy.copy(keypoints)
368
336
 
@@ -5,11 +5,10 @@ import scipy.linalg
5
5
 
6
6
 
7
7
  class KalmanFilterXYAH:
8
- """
9
- A KalmanFilterXYAH class for tracking bounding boxes in image space using a Kalman filter.
8
+ """A KalmanFilterXYAH class for tracking bounding boxes in image space using a Kalman filter.
10
9
 
11
- Implements a simple Kalman filter for tracking bounding boxes in image space. The 8-dimensional state space
12
- (x, y, a, h, vx, vy, va, vh) contains the bounding box center position (x, y), aspect ratio a, height h, and their
10
+ Implements a simple Kalman filter for tracking bounding boxes in image space. The 8-dimensional state space (x, y,
11
+ a, h, vx, vy, va, vh) contains the bounding box center position (x, y), aspect ratio a, height h, and their
13
12
  respective velocities. Object motion follows a constant velocity model, and bounding box location (x, y, a, h) is
14
13
  taken as a direct observation of the state space (linear observation model).
15
14
 
@@ -20,12 +19,12 @@ class KalmanFilterXYAH:
20
19
  _std_weight_velocity (float): Standard deviation weight for velocity.
21
20
 
22
21
  Methods:
23
- initiate: Creates a track from an unassociated measurement.
24
- predict: Runs the Kalman filter prediction step.
25
- project: Projects the state distribution to measurement space.
26
- multi_predict: Runs the Kalman filter prediction step (vectorized version).
27
- update: Runs the Kalman filter correction step.
28
- gating_distance: Computes the gating distance between state distribution and measurements.
22
+ initiate: Create a track from an unassociated measurement.
23
+ predict: Run the Kalman filter prediction step.
24
+ project: Project the state distribution to measurement space.
25
+ multi_predict: Run the Kalman filter prediction step (vectorized version).
26
+ update: Run the Kalman filter correction step.
27
+ gating_distance: Compute the gating distance between state distribution and measurements.
29
28
 
30
29
  Examples:
31
30
  Initialize the Kalman filter and create a track from a measurement
@@ -37,8 +36,7 @@ class KalmanFilterXYAH:
37
36
  """
38
37
 
39
38
  def __init__(self):
40
- """
41
- Initialize Kalman filter model matrices with motion and observation uncertainty weights.
39
+ """Initialize Kalman filter model matrices with motion and observation uncertainty weights.
42
40
 
43
41
  The Kalman filter is initialized with an 8-dimensional state space (x, y, a, h, vx, vy, va, vh), where (x, y)
44
42
  represents the bounding box center position, 'a' is the aspect ratio, 'h' is the height, and their respective
@@ -62,16 +60,16 @@ class KalmanFilterXYAH:
62
60
  self._std_weight_velocity = 1.0 / 160
63
61
 
64
62
  def initiate(self, measurement: np.ndarray):
65
- """
66
- Create a track from an unassociated measurement.
63
+ """Create a track from an unassociated measurement.
67
64
 
68
65
  Args:
69
66
  measurement (np.ndarray): Bounding box coordinates (x, y, a, h) with center position (x, y), aspect ratio a,
70
67
  and height h.
71
68
 
72
69
  Returns:
73
- (np.ndarray): Mean vector (8-dimensional) of the new track. Unobserved velocities are initialized to 0 mean.
74
- (np.ndarray): Covariance matrix (8x8 dimensional) of the new track.
70
+ mean (np.ndarray): Mean vector (8-dimensional) of the new track. Unobserved velocities are initialized to 0
71
+ mean.
72
+ covariance (np.ndarray): Covariance matrix (8x8 dimensional) of the new track.
75
73
 
76
74
  Examples:
77
75
  >>> kf = KalmanFilterXYAH()
@@ -96,16 +94,16 @@ class KalmanFilterXYAH:
96
94
  return mean, covariance
97
95
 
98
96
  def predict(self, mean: np.ndarray, covariance: np.ndarray):
99
- """
100
- Run Kalman filter prediction step.
97
+ """Run Kalman filter prediction step.
101
98
 
102
99
  Args:
103
100
  mean (np.ndarray): The 8-dimensional mean vector of the object state at the previous time step.
104
- covariance (np.ndarray): The 8x8-dimensional covariance matrix of the object state at the previous time step.
101
+ covariance (np.ndarray): The 8x8-dimensional covariance matrix of the object state at the previous time
102
+ step.
105
103
 
106
104
  Returns:
107
- (np.ndarray): Mean vector of the predicted state. Unobserved velocities are initialized to 0 mean.
108
- (np.ndarray): Covariance matrix of the predicted state.
105
+ mean (np.ndarray): Mean vector of the predicted state. Unobserved velocities are initialized to 0 mean.
106
+ covariance (np.ndarray): Covariance matrix of the predicted state.
109
107
 
110
108
  Examples:
111
109
  >>> kf = KalmanFilterXYAH()
@@ -133,16 +131,15 @@ class KalmanFilterXYAH:
133
131
  return mean, covariance
134
132
 
135
133
  def project(self, mean: np.ndarray, covariance: np.ndarray):
136
- """
137
- Project state distribution to measurement space.
134
+ """Project state distribution to measurement space.
138
135
 
139
136
  Args:
140
137
  mean (np.ndarray): The state's mean vector (8 dimensional array).
141
138
  covariance (np.ndarray): The state's covariance matrix (8x8 dimensional).
142
139
 
143
140
  Returns:
144
- (np.ndarray): Projected mean of the given state estimate.
145
- (np.ndarray): Projected covariance matrix of the given state estimate.
141
+ mean (np.ndarray): Projected mean of the given state estimate.
142
+ covariance (np.ndarray): Projected covariance matrix of the given state estimate.
146
143
 
147
144
  Examples:
148
145
  >>> kf = KalmanFilterXYAH()
@@ -163,16 +160,15 @@ class KalmanFilterXYAH:
163
160
  return mean, covariance + innovation_cov
164
161
 
165
162
  def multi_predict(self, mean: np.ndarray, covariance: np.ndarray):
166
- """
167
- Run Kalman filter prediction step for multiple object states (Vectorized version).
163
+ """Run Kalman filter prediction step for multiple object states (Vectorized version).
168
164
 
169
165
  Args:
170
166
  mean (np.ndarray): The Nx8 dimensional mean matrix of the object states at the previous time step.
171
167
  covariance (np.ndarray): The Nx8x8 covariance matrix of the object states at the previous time step.
172
168
 
173
169
  Returns:
174
- (np.ndarray): Mean matrix of the predicted states with shape (N, 8).
175
- (np.ndarray): Covariance matrix of the predicted states with shape (N, 8, 8).
170
+ mean (np.ndarray): Mean matrix of the predicted states with shape (N, 8).
171
+ covariance (np.ndarray): Covariance matrix of the predicted states with shape (N, 8, 8).
176
172
 
177
173
  Examples:
178
174
  >>> mean = np.random.rand(10, 8) # 10 object states
@@ -203,8 +199,7 @@ class KalmanFilterXYAH:
203
199
  return mean, covariance
204
200
 
205
201
  def update(self, mean: np.ndarray, covariance: np.ndarray, measurement: np.ndarray):
206
- """
207
- Run Kalman filter correction step.
202
+ """Run Kalman filter correction step.
208
203
 
209
204
  Args:
210
205
  mean (np.ndarray): The predicted state's mean vector (8 dimensional).
@@ -213,8 +208,8 @@ class KalmanFilterXYAH:
213
208
  position, a the aspect ratio, and h the height of the bounding box.
214
209
 
215
210
  Returns:
216
- (np.ndarray): Measurement-corrected state mean.
217
- (np.ndarray): Measurement-corrected state covariance.
211
+ new_mean (np.ndarray): Measurement-corrected state mean.
212
+ new_covariance (np.ndarray): Measurement-corrected state covariance.
218
213
 
219
214
  Examples:
220
215
  >>> kf = KalmanFilterXYAH()
@@ -243,8 +238,7 @@ class KalmanFilterXYAH:
243
238
  only_position: bool = False,
244
239
  metric: str = "maha",
245
240
  ) -> np.ndarray:
246
- """
247
- Compute gating distance between state distribution and measurements.
241
+ """Compute gating distance between state distribution and measurements.
248
242
 
249
243
  A suitable distance threshold can be obtained from `chi2inv95`. If `only_position` is False, the chi-square
250
244
  distribution has 4 degrees of freedom, otherwise 2.
@@ -252,11 +246,12 @@ class KalmanFilterXYAH:
252
246
  Args:
253
247
  mean (np.ndarray): Mean vector over the state distribution (8 dimensional).
254
248
  covariance (np.ndarray): Covariance of the state distribution (8x8 dimensional).
255
- measurements (np.ndarray): An (N, 4) matrix of N measurements, each in format (x, y, a, h) where (x, y) is the
256
- bounding box center position, a the aspect ratio, and h the height.
257
- only_position (bool): If True, distance computation is done with respect to box center position only.
258
- metric (str): The metric to use for calculating the distance. Options are 'gaussian' for the squared
259
- Euclidean distance and 'maha' for the squared Mahalanobis distance.
249
+ measurements (np.ndarray): An (N, 4) matrix of N measurements, each in format (x, y, a, h) where (x, y) is
250
+ the bounding box center position, a the aspect ratio, and h the height.
251
+ only_position (bool, optional): If True, distance computation is done with respect to box center position
252
+ only.
253
+ metric (str, optional): The metric to use for calculating the distance. Options are 'gaussian' for the
254
+ squared Euclidean distance and 'maha' for the squared Mahalanobis distance.
260
255
 
261
256
  Returns:
262
257
  (np.ndarray): Returns an array of length N, where the i-th element contains the squared distance between
@@ -287,12 +282,11 @@ class KalmanFilterXYAH:
287
282
 
288
283
 
289
284
  class KalmanFilterXYWH(KalmanFilterXYAH):
290
- """
291
- A KalmanFilterXYWH class for tracking bounding boxes in image space using a Kalman filter.
285
+ """A KalmanFilterXYWH class for tracking bounding boxes in image space using a Kalman filter.
292
286
 
293
- Implements a Kalman filter for tracking bounding boxes with state space (x, y, w, h, vx, vy, vw, vh), where
294
- (x, y) is the center position, w is the width, h is the height, and vx, vy, vw, vh are their respective velocities.
295
- The object motion follows a constant velocity model, and the bounding box location (x, y, w, h) is taken as a direct
287
+ Implements a Kalman filter for tracking bounding boxes with state space (x, y, w, h, vx, vy, vw, vh), where (x, y)
288
+ is the center position, w is the width, h is the height, and vx, vy, vw, vh are their respective velocities. The
289
+ object motion follows a constant velocity model, and the bounding box location (x, y, w, h) is taken as a direct
296
290
  observation of the state space (linear observation model).
297
291
 
298
292
  Attributes:
@@ -302,11 +296,11 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
302
296
  _std_weight_velocity (float): Standard deviation weight for velocity.
303
297
 
304
298
  Methods:
305
- initiate: Creates a track from an unassociated measurement.
306
- predict: Runs the Kalman filter prediction step.
307
- project: Projects the state distribution to measurement space.
308
- multi_predict: Runs the Kalman filter prediction step in a vectorized manner.
309
- update: Runs the Kalman filter correction step.
299
+ initiate: Create a track from an unassociated measurement.
300
+ predict: Run the Kalman filter prediction step.
301
+ project: Project the state distribution to measurement space.
302
+ multi_predict: Run the Kalman filter prediction step in a vectorized manner.
303
+ update: Run the Kalman filter correction step.
310
304
 
311
305
  Examples:
312
306
  Create a Kalman filter and initialize a track
@@ -318,15 +312,16 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
318
312
  """
319
313
 
320
314
  def initiate(self, measurement: np.ndarray):
321
- """
322
- Create track from unassociated measurement.
315
+ """Create track from unassociated measurement.
323
316
 
324
317
  Args:
325
- measurement (np.ndarray): Bounding box coordinates (x, y, w, h) with center position (x, y), width, and height.
318
+ measurement (np.ndarray): Bounding box coordinates (x, y, w, h) with center position (x, y), width, and
319
+ height.
326
320
 
327
321
  Returns:
328
- (np.ndarray): Mean vector (8 dimensional) of the new track. Unobserved velocities are initialized to 0 mean.
329
- (np.ndarray): Covariance matrix (8x8 dimensional) of the new track.
322
+ mean (np.ndarray): Mean vector (8 dimensional) of the new track. Unobserved velocities are initialized to 0
323
+ mean.
324
+ covariance (np.ndarray): Covariance matrix (8x8 dimensional) of the new track.
330
325
 
331
326
  Examples:
332
327
  >>> kf = KalmanFilterXYWH()
@@ -361,17 +356,17 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
361
356
  covariance = np.diag(np.square(std))
362
357
  return mean, covariance
363
358
 
364
- def predict(self, mean, covariance):
365
- """
366
- Run Kalman filter prediction step.
359
+ def predict(self, mean: np.ndarray, covariance: np.ndarray):
360
+ """Run Kalman filter prediction step.
367
361
 
368
362
  Args:
369
363
  mean (np.ndarray): The 8-dimensional mean vector of the object state at the previous time step.
370
- covariance (np.ndarray): The 8x8-dimensional covariance matrix of the object state at the previous time step.
364
+ covariance (np.ndarray): The 8x8-dimensional covariance matrix of the object state at the previous time
365
+ step.
371
366
 
372
367
  Returns:
373
- (np.ndarray): Mean vector of the predicted state. Unobserved velocities are initialized to 0 mean.
374
- (np.ndarray): Covariance matrix of the predicted state.
368
+ mean (np.ndarray): Mean vector of the predicted state. Unobserved velocities are initialized to 0 mean.
369
+ covariance (np.ndarray): Covariance matrix of the predicted state.
375
370
 
376
371
  Examples:
377
372
  >>> kf = KalmanFilterXYWH()
@@ -398,17 +393,16 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
398
393
 
399
394
  return mean, covariance
400
395
 
401
- def project(self, mean, covariance):
402
- """
403
- Project state distribution to measurement space.
396
+ def project(self, mean: np.ndarray, covariance: np.ndarray):
397
+ """Project state distribution to measurement space.
404
398
 
405
399
  Args:
406
400
  mean (np.ndarray): The state's mean vector (8 dimensional array).
407
401
  covariance (np.ndarray): The state's covariance matrix (8x8 dimensional).
408
402
 
409
403
  Returns:
410
- (np.ndarray): Projected mean of the given state estimate.
411
- (np.ndarray): Projected covariance matrix of the given state estimate.
404
+ mean (np.ndarray): Projected mean of the given state estimate.
405
+ covariance (np.ndarray): Projected covariance matrix of the given state estimate.
412
406
 
413
407
  Examples:
414
408
  >>> kf = KalmanFilterXYWH()
@@ -428,17 +422,16 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
428
422
  covariance = np.linalg.multi_dot((self._update_mat, covariance, self._update_mat.T))
429
423
  return mean, covariance + innovation_cov
430
424
 
431
- def multi_predict(self, mean, covariance):
432
- """
433
- Run Kalman filter prediction step (Vectorized version).
425
+ def multi_predict(self, mean: np.ndarray, covariance: np.ndarray):
426
+ """Run Kalman filter prediction step (Vectorized version).
434
427
 
435
428
  Args:
436
429
  mean (np.ndarray): The Nx8 dimensional mean matrix of the object states at the previous time step.
437
430
  covariance (np.ndarray): The Nx8x8 covariance matrix of the object states at the previous time step.
438
431
 
439
432
  Returns:
440
- (np.ndarray): Mean matrix of the predicted states with shape (N, 8).
441
- (np.ndarray): Covariance matrix of the predicted states with shape (N, 8, 8).
433
+ mean (np.ndarray): Mean matrix of the predicted states with shape (N, 8).
434
+ covariance (np.ndarray): Covariance matrix of the predicted states with shape (N, 8, 8).
442
435
 
443
436
  Examples:
444
437
  >>> mean = np.random.rand(5, 8) # 5 objects with 8-dimensional state vectors
@@ -469,9 +462,8 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
469
462
 
470
463
  return mean, covariance
471
464
 
472
- def update(self, mean, covariance, measurement):
473
- """
474
- Run Kalman filter correction step.
465
+ def update(self, mean: np.ndarray, covariance: np.ndarray, measurement: np.ndarray):
466
+ """Run Kalman filter correction step.
475
467
 
476
468
  Args:
477
469
  mean (np.ndarray): The predicted state's mean vector (8 dimensional).
@@ -480,8 +472,8 @@ class KalmanFilterXYWH(KalmanFilterXYAH):
480
472
  position, w the width, and h the height of the bounding box.
481
473
 
482
474
  Returns:
483
- (np.ndarray): Measurement-corrected state mean.
484
- (np.ndarray): Measurement-corrected state covariance.
475
+ new_mean (np.ndarray): Measurement-corrected state mean.
476
+ new_covariance (np.ndarray): Measurement-corrected state covariance.
485
477
 
486
478
  Examples:
487
479
  >>> kf = KalmanFilterXYWH()
@@ -17,9 +17,8 @@ except (ImportError, AssertionError, AttributeError):
17
17
  import lap
18
18
 
19
19
 
20
- def linear_assignment(cost_matrix: np.ndarray, thresh: float, use_lap: bool = True) -> tuple:
21
- """
22
- Perform linear assignment using either the scipy or lap.lapjv method.
20
+ def linear_assignment(cost_matrix: np.ndarray, thresh: float, use_lap: bool = True):
21
+ """Perform linear assignment using either the scipy or lap.lapjv method.
23
22
 
24
23
  Args:
25
24
  cost_matrix (np.ndarray): The matrix containing cost values for assignments, with shape (N, M).
@@ -62,12 +61,11 @@ def linear_assignment(cost_matrix: np.ndarray, thresh: float, use_lap: bool = Tr
62
61
 
63
62
 
64
63
  def iou_distance(atracks: list, btracks: list) -> np.ndarray:
65
- """
66
- Compute cost based on Intersection over Union (IoU) between tracks.
64
+ """Compute cost based on Intersection over Union (IoU) between tracks.
67
65
 
68
66
  Args:
69
- atracks (List[STrack] | List[np.ndarray]): List of tracks 'a' or bounding boxes.
70
- btracks (List[STrack] | List[np.ndarray]): List of tracks 'b' or bounding boxes.
67
+ atracks (list[STrack] | list[np.ndarray]): List of tracks 'a' or bounding boxes.
68
+ btracks (list[STrack] | list[np.ndarray]): List of tracks 'b' or bounding boxes.
71
69
 
72
70
  Returns:
73
71
  (np.ndarray): Cost matrix computed based on IoU with shape (len(atracks), len(btracks)).
@@ -78,7 +76,7 @@ def iou_distance(atracks: list, btracks: list) -> np.ndarray:
78
76
  >>> btracks = [np.array([5, 5, 15, 15]), np.array([25, 25, 35, 35])]
79
77
  >>> cost_matrix = iou_distance(atracks, btracks)
80
78
  """
81
- if atracks and isinstance(atracks[0], np.ndarray) or btracks and isinstance(btracks[0], np.ndarray):
79
+ if (atracks and isinstance(atracks[0], np.ndarray)) or (btracks and isinstance(btracks[0], np.ndarray)):
82
80
  atlbrs = atracks
83
81
  btlbrs = btracks
84
82
  else:
@@ -102,17 +100,16 @@ def iou_distance(atracks: list, btracks: list) -> np.ndarray:
102
100
 
103
101
 
104
102
  def embedding_distance(tracks: list, detections: list, metric: str = "cosine") -> np.ndarray:
105
- """
106
- Compute distance between tracks and detections based on embeddings.
103
+ """Compute distance between tracks and detections based on embeddings.
107
104
 
108
105
  Args:
109
- tracks (List[STrack]): List of tracks, where each track contains embedding features.
110
- detections (List[BaseTrack]): List of detections, where each detection contains embedding features.
106
+ tracks (list[STrack]): List of tracks, where each track contains embedding features.
107
+ detections (list[BaseTrack]): List of detections, where each detection contains embedding features.
111
108
  metric (str): Metric for distance computation. Supported metrics include 'cosine', 'euclidean', etc.
112
109
 
113
110
  Returns:
114
- (np.ndarray): Cost matrix computed based on embeddings with shape (N, M), where N is the number of tracks
115
- and M is the number of detections.
111
+ (np.ndarray): Cost matrix computed based on embeddings with shape (N, M), where N is the number of tracks and M
112
+ is the number of detections.
116
113
 
117
114
  Examples:
118
115
  Compute the embedding distance between tracks and detections using cosine metric
@@ -132,12 +129,11 @@ def embedding_distance(tracks: list, detections: list, metric: str = "cosine") -
132
129
 
133
130
 
134
131
  def fuse_score(cost_matrix: np.ndarray, detections: list) -> np.ndarray:
135
- """
136
- Fuse cost matrix with detection scores to produce a single similarity matrix.
132
+ """Fuse cost matrix with detection scores to produce a single similarity matrix.
137
133
 
138
134
  Args:
139
135
  cost_matrix (np.ndarray): The matrix containing cost values for assignments, with shape (N, M).
140
- detections (List[BaseTrack]): List of detections, each containing a score attribute.
136
+ detections (list[BaseTrack]): List of detections, each containing a score attribute.
141
137
 
142
138
  Returns:
143
139
  (np.ndarray): Fused similarity matrix with shape (N, M).