ultralytics 8.2.19__tar.gz → 8.2.21__tar.gz

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 (223) hide show
  1. {ultralytics-8.2.19 → ultralytics-8.2.21}/PKG-INFO +1 -1
  2. {ultralytics-8.2.19 → ultralytics-8.2.21}/pyproject.toml +1 -1
  3. ultralytics-8.2.21/tests/__init__.py +22 -0
  4. ultralytics-8.2.21/tests/conftest.py +71 -0
  5. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_exports.py +15 -15
  6. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/__init__.py +1 -1
  7. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/exporter.py +34 -34
  8. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/results.py +1 -1
  9. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/__init__.py +2 -0
  10. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/ai_gym.py +3 -3
  11. ultralytics-8.2.21/ultralytics/solutions/analytics.py +197 -0
  12. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/checks.py +4 -3
  13. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/PKG-INFO +1 -1
  14. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/SOURCES.txt +10 -0
  15. {ultralytics-8.2.19 → ultralytics-8.2.21}/LICENSE +0 -0
  16. {ultralytics-8.2.19 → ultralytics-8.2.21}/README.md +0 -0
  17. {ultralytics-8.2.19 → ultralytics-8.2.21}/setup.cfg +0 -0
  18. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_cli.py +0 -0
  19. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_cuda.py +0 -0
  20. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_engine.py +0 -0
  21. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_explorer.py +0 -0
  22. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_integrations.py +0 -0
  23. {ultralytics-8.2.19 → ultralytics-8.2.21}/tests/test_python.py +0 -0
  24. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/assets/bus.jpg +0 -0
  25. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/assets/zidane.jpg +0 -0
  26. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/__init__.py +0 -0
  27. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/Argoverse.yaml +0 -0
  28. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/DOTAv1.5.yaml +0 -0
  29. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/DOTAv1.yaml +0 -0
  30. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/GlobalWheat2020.yaml +0 -0
  31. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/ImageNet.yaml +0 -0
  32. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/Objects365.yaml +0 -0
  33. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/SKU-110K.yaml +0 -0
  34. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/VOC.yaml +0 -0
  35. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/VisDrone.yaml +0 -0
  36. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/african-wildlife.yaml +0 -0
  37. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/brain-tumor.yaml +0 -0
  38. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/carparts-seg.yaml +0 -0
  39. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco-pose.yaml +0 -0
  40. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco.yaml +0 -0
  41. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco128-seg.yaml +0 -0
  42. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco128.yaml +0 -0
  43. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco8-pose.yaml +0 -0
  44. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco8-seg.yaml +0 -0
  45. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/coco8.yaml +0 -0
  46. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/crack-seg.yaml +0 -0
  47. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/dota8.yaml +0 -0
  48. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/lvis.yaml +0 -0
  49. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/open-images-v7.yaml +0 -0
  50. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/package-seg.yaml +0 -0
  51. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/signature.yaml +0 -0
  52. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/tiger-pose.yaml +0 -0
  53. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/datasets/xView.yaml +0 -0
  54. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/default.yaml +0 -0
  55. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/rt-detr/rtdetr-l.yaml +0 -0
  56. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/rt-detr/rtdetr-resnet101.yaml +0 -0
  57. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/rt-detr/rtdetr-resnet50.yaml +0 -0
  58. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/rt-detr/rtdetr-x.yaml +0 -0
  59. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v3/yolov3-spp.yaml +0 -0
  60. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v3/yolov3-tiny.yaml +0 -0
  61. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v3/yolov3.yaml +0 -0
  62. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v5/yolov5-p6.yaml +0 -0
  63. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v5/yolov5.yaml +0 -0
  64. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v6/yolov6.yaml +0 -0
  65. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-cls-resnet101.yaml +0 -0
  66. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-cls-resnet50.yaml +0 -0
  67. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-cls.yaml +0 -0
  68. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-ghost-p2.yaml +0 -0
  69. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-ghost-p6.yaml +0 -0
  70. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-ghost.yaml +0 -0
  71. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-obb.yaml +0 -0
  72. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-p2.yaml +0 -0
  73. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-p6.yaml +0 -0
  74. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-pose-p6.yaml +0 -0
  75. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-pose.yaml +0 -0
  76. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-rtdetr.yaml +0 -0
  77. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-seg-p6.yaml +0 -0
  78. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-seg.yaml +0 -0
  79. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-world.yaml +0 -0
  80. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8-worldv2.yaml +0 -0
  81. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v8/yolov8.yaml +0 -0
  82. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v9/yolov9c-seg.yaml +0 -0
  83. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v9/yolov9c.yaml +0 -0
  84. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v9/yolov9e-seg.yaml +0 -0
  85. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/models/v9/yolov9e.yaml +0 -0
  86. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/trackers/botsort.yaml +0 -0
  87. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/cfg/trackers/bytetrack.yaml +0 -0
  88. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/__init__.py +0 -0
  89. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/annotator.py +0 -0
  90. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/augment.py +0 -0
  91. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/base.py +0 -0
  92. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/build.py +0 -0
  93. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/converter.py +0 -0
  94. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/dataset.py +0 -0
  95. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/explorer/__init__.py +0 -0
  96. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/explorer/explorer.py +0 -0
  97. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/explorer/gui/__init__.py +0 -0
  98. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/explorer/gui/dash.py +0 -0
  99. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/explorer/utils.py +0 -0
  100. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/loaders.py +0 -0
  101. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/split_dota.py +0 -0
  102. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/data/utils.py +0 -0
  103. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/__init__.py +0 -0
  104. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/model.py +0 -0
  105. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/predictor.py +0 -0
  106. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/trainer.py +0 -0
  107. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/tuner.py +0 -0
  108. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/engine/validator.py +0 -0
  109. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/hub/__init__.py +0 -0
  110. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/hub/auth.py +0 -0
  111. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/hub/session.py +0 -0
  112. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/hub/utils.py +0 -0
  113. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/__init__.py +0 -0
  114. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/__init__.py +0 -0
  115. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/model.py +0 -0
  116. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/predict.py +0 -0
  117. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/prompt.py +0 -0
  118. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/utils.py +0 -0
  119. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/fastsam/val.py +0 -0
  120. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/nas/__init__.py +0 -0
  121. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/nas/model.py +0 -0
  122. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/nas/predict.py +0 -0
  123. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/nas/val.py +0 -0
  124. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/rtdetr/__init__.py +0 -0
  125. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/rtdetr/model.py +0 -0
  126. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/rtdetr/predict.py +0 -0
  127. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/rtdetr/train.py +0 -0
  128. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/rtdetr/val.py +0 -0
  129. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/__init__.py +0 -0
  130. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/amg.py +0 -0
  131. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/build.py +0 -0
  132. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/model.py +0 -0
  133. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/__init__.py +0 -0
  134. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/decoders.py +0 -0
  135. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/encoders.py +0 -0
  136. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/sam.py +0 -0
  137. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/tiny_encoder.py +0 -0
  138. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/modules/transformer.py +0 -0
  139. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/sam/predict.py +0 -0
  140. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/utils/__init__.py +0 -0
  141. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/utils/loss.py +0 -0
  142. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/utils/ops.py +0 -0
  143. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/__init__.py +0 -0
  144. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/classify/__init__.py +0 -0
  145. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/classify/predict.py +0 -0
  146. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/classify/train.py +0 -0
  147. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/classify/val.py +0 -0
  148. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/detect/__init__.py +0 -0
  149. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/detect/predict.py +0 -0
  150. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/detect/train.py +0 -0
  151. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/detect/val.py +0 -0
  152. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/model.py +0 -0
  153. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/obb/__init__.py +0 -0
  154. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/obb/predict.py +0 -0
  155. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/obb/train.py +0 -0
  156. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/obb/val.py +0 -0
  157. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/pose/__init__.py +0 -0
  158. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/pose/predict.py +0 -0
  159. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/pose/train.py +0 -0
  160. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/pose/val.py +0 -0
  161. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/segment/__init__.py +0 -0
  162. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/segment/predict.py +0 -0
  163. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/segment/train.py +0 -0
  164. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/segment/val.py +0 -0
  165. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/world/__init__.py +0 -0
  166. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/world/train.py +0 -0
  167. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/models/yolo/world/train_world.py +0 -0
  168. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/__init__.py +0 -0
  169. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/autobackend.py +0 -0
  170. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/__init__.py +0 -0
  171. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/block.py +0 -0
  172. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/conv.py +0 -0
  173. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/head.py +0 -0
  174. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/transformer.py +0 -0
  175. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/modules/utils.py +0 -0
  176. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/nn/tasks.py +0 -0
  177. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/distance_calculation.py +0 -0
  178. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/heatmap.py +0 -0
  179. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/object_counter.py +0 -0
  180. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/parking_management.py +0 -0
  181. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/queue_management.py +0 -0
  182. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/solutions/speed_estimation.py +0 -0
  183. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/__init__.py +0 -0
  184. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/basetrack.py +0 -0
  185. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/bot_sort.py +0 -0
  186. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/byte_tracker.py +0 -0
  187. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/track.py +0 -0
  188. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/utils/__init__.py +0 -0
  189. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/utils/gmc.py +0 -0
  190. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/utils/kalman_filter.py +0 -0
  191. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/trackers/utils/matching.py +0 -0
  192. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/__init__.py +0 -0
  193. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/autobatch.py +0 -0
  194. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/benchmarks.py +0 -0
  195. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/__init__.py +0 -0
  196. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/base.py +0 -0
  197. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/clearml.py +0 -0
  198. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/comet.py +0 -0
  199. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/dvc.py +0 -0
  200. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/hub.py +0 -0
  201. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/mlflow.py +0 -0
  202. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/neptune.py +0 -0
  203. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/raytune.py +0 -0
  204. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/tensorboard.py +0 -0
  205. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/callbacks/wb.py +0 -0
  206. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/dist.py +0 -0
  207. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/downloads.py +0 -0
  208. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/errors.py +0 -0
  209. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/files.py +0 -0
  210. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/instance.py +0 -0
  211. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/loss.py +0 -0
  212. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/metrics.py +0 -0
  213. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/ops.py +0 -0
  214. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/patches.py +0 -0
  215. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/plotting.py +0 -0
  216. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/tal.py +0 -0
  217. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/torch_utils.py +0 -0
  218. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/triton.py +0 -0
  219. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics/utils/tuner.py +0 -0
  220. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/dependency_links.txt +0 -0
  221. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/entry_points.txt +0 -0
  222. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/requires.txt +0 -0
  223. {ultralytics-8.2.19 → ultralytics-8.2.21}/ultralytics.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ultralytics
3
- Version: 8.2.19
3
+ Version: 8.2.21
4
4
  Summary: Ultralytics YOLOv8 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
5
5
  Author: Glenn Jocher, Ayush Chaurasia, Jing Qiu
6
6
  Maintainer: Glenn Jocher, Ayush Chaurasia, Jing Qiu
@@ -139,7 +139,7 @@ ultralytics = "ultralytics.cfg:entrypoint"
139
139
  # Tools settings -------------------------------------------------------------------------------------------------------
140
140
  [tool.setuptools] # configuration specific to the `setuptools` build backend.
141
141
  packages = { find = { where = ["."], include = ["ultralytics", "ultralytics.*"] } }
142
- package-data = { "ultralytics" = ["**/*.yaml"], "ultralytics.assets" = ["*.jpg"] }
142
+ package-data = { "ultralytics" = ["**/*.yaml", "../tests/*.py"], "ultralytics.assets" = ["*.jpg"] }
143
143
 
144
144
  [tool.setuptools.dynamic]
145
145
  version = { attr = "ultralytics.__version__" }
@@ -0,0 +1,22 @@
1
+ # Ultralytics YOLO 🚀, AGPL-3.0 license
2
+
3
+ from ultralytics.utils import ASSETS, ROOT, WEIGHTS_DIR, checks, is_dir_writeable
4
+
5
+ # Constants used in tests
6
+ MODEL = WEIGHTS_DIR / "path with spaces" / "yolov8n.pt" # test spaces in path
7
+ CFG = "yolov8n.yaml"
8
+ SOURCE = ASSETS / "bus.jpg"
9
+ TMP = (ROOT / "../tests/tmp").resolve() # temp directory for test files
10
+ IS_TMP_WRITEABLE = is_dir_writeable(TMP)
11
+ CUDA_IS_AVAILABLE = checks.cuda_is_available()
12
+ CUDA_DEVICE_COUNT = checks.cuda_device_count()
13
+
14
+ __all__ = (
15
+ "MODEL",
16
+ "CFG",
17
+ "SOURCE",
18
+ "TMP",
19
+ "IS_TMP_WRITEABLE",
20
+ "CUDA_IS_AVAILABLE",
21
+ "CUDA_DEVICE_COUNT",
22
+ )
@@ -0,0 +1,71 @@
1
+ # Ultralytics YOLO 🚀, AGPL-3.0 license
2
+
3
+ import shutil
4
+ from pathlib import Path
5
+
6
+ from tests import TMP
7
+
8
+
9
+ def pytest_addoption(parser):
10
+ """
11
+ Add custom command-line options to pytest.
12
+
13
+ Args:
14
+ parser (pytest.config.Parser): The pytest parser object.
15
+ """
16
+ parser.addoption("--slow", action="store_true", default=False, help="Run slow tests")
17
+
18
+
19
+ def pytest_collection_modifyitems(config, items):
20
+ """
21
+ Modify the list of test items to remove tests marked as slow if the --slow option is not provided.
22
+
23
+ Args:
24
+ config (pytest.config.Config): The pytest config object.
25
+ items (list): List of test items to be executed.
26
+ """
27
+ if not config.getoption("--slow"):
28
+ # Remove the item entirely from the list of test items if it's marked as 'slow'
29
+ items[:] = [item for item in items if "slow" not in item.keywords]
30
+
31
+
32
+ def pytest_sessionstart(session):
33
+ """
34
+ Initialize session configurations for pytest.
35
+
36
+ This function is automatically called by pytest after the 'Session' object has been created but before performing
37
+ test collection. It sets the initial seeds and prepares the temporary directory for the test session.
38
+
39
+ Args:
40
+ session (pytest.Session): The pytest session object.
41
+ """
42
+ from ultralytics.utils.torch_utils import init_seeds
43
+
44
+ init_seeds()
45
+ shutil.rmtree(TMP, ignore_errors=True) # delete any existing tests/tmp directory
46
+ TMP.mkdir(parents=True, exist_ok=True) # create a new empty directory
47
+
48
+
49
+ def pytest_terminal_summary(terminalreporter, exitstatus, config):
50
+ """
51
+ Cleanup operations after pytest session.
52
+
53
+ This function is automatically called by pytest at the end of the entire test session. It removes certain files
54
+ and directories used during testing.
55
+
56
+ Args:
57
+ terminalreporter (pytest.terminal.TerminalReporter): The terminal reporter object.
58
+ exitstatus (int): The exit status of the test run.
59
+ config (pytest.config.Config): The pytest config object.
60
+ """
61
+ from ultralytics.utils import WEIGHTS_DIR
62
+
63
+ # Remove files
64
+ models = [path for x in ["*.onnx", "*.torchscript"] for path in WEIGHTS_DIR.rglob(x)]
65
+ for file in ["bus.jpg", "yolov8n.onnx", "yolov8n.torchscript"] + models:
66
+ Path(file).unlink(missing_ok=True)
67
+
68
+ # Remove directories
69
+ models = [path for x in ["*.mlpackage", "*_openvino_model"] for path in WEIGHTS_DIR.rglob(x)]
70
+ for directory in [TMP.parents[1] / ".pytest_cache", TMP] + models:
71
+ shutil.rmtree(directory, ignore_errors=True)
@@ -23,22 +23,22 @@ from tests import MODEL, SOURCE
23
23
 
24
24
  def test_export_torchscript():
25
25
  """Test YOLO exports to TorchScript format."""
26
- f = YOLO(MODEL).export(format="torchscript", optimize=False, imgsz=32)
27
- YOLO(f)(SOURCE, imgsz=32) # exported model inference
26
+ file = YOLO(MODEL).export(format="torchscript", optimize=False, imgsz=32)
27
+ YOLO(file)(SOURCE, imgsz=32) # exported model inference
28
28
 
29
29
 
30
30
  def test_export_onnx():
31
31
  """Test YOLO exports to ONNX format."""
32
- f = YOLO(MODEL).export(format="onnx", dynamic=True, imgsz=32)
33
- YOLO(f)(SOURCE, imgsz=32) # exported model inference
32
+ file = YOLO(MODEL).export(format="onnx", dynamic=True, imgsz=32)
33
+ YOLO(file)(SOURCE, imgsz=32) # exported model inference
34
34
 
35
35
 
36
36
  @pytest.mark.skipif(checks.IS_PYTHON_3_12, reason="OpenVINO not supported in Python 3.12")
37
37
  @pytest.mark.skipif(not TORCH_1_13, reason="OpenVINO requires torch>=1.13")
38
38
  def test_export_openvino():
39
39
  """Test YOLO exports to OpenVINO format."""
40
- f = YOLO(MODEL).export(format="openvino", imgsz=32)
41
- YOLO(f)(SOURCE, imgsz=32) # exported model inference
40
+ file = YOLO(MODEL).export(format="openvino", imgsz=32)
41
+ YOLO(file)(SOURCE, imgsz=32) # exported model inference
42
42
 
43
43
 
44
44
  @pytest.mark.slow
@@ -118,7 +118,7 @@ def test_export_torchscript_matrix(task, dynamic, int8, half, batch):
118
118
  ],
119
119
  )
120
120
  def test_export_coreml_matrix(task, dynamic, int8, half, batch):
121
- """Test YOLO exports to TorchScript format."""
121
+ """Test YOLO exports to CoreML format."""
122
122
  file = YOLO(TASK2MODEL[task]).export(
123
123
  format="coreml",
124
124
  imgsz=32,
@@ -138,8 +138,8 @@ def test_export_coreml_matrix(task, dynamic, int8, half, batch):
138
138
  def test_export_coreml():
139
139
  """Test YOLO exports to CoreML format."""
140
140
  if MACOS:
141
- f = YOLO(MODEL).export(format="coreml", imgsz=32)
142
- YOLO(f)(SOURCE, imgsz=32) # model prediction only supported on macOS for nms=False models
141
+ file = YOLO(MODEL).export(format="coreml", imgsz=32)
142
+ YOLO(file)(SOURCE, imgsz=32) # model prediction only supported on macOS for nms=False models
143
143
  else:
144
144
  YOLO(MODEL).export(format="coreml", nms=True, imgsz=32)
145
145
 
@@ -152,8 +152,8 @@ def test_export_tflite():
152
152
  Note TF suffers from install conflicts on Windows and macOS.
153
153
  """
154
154
  model = YOLO(MODEL)
155
- f = model.export(format="tflite", imgsz=32)
156
- YOLO(f)(SOURCE, imgsz=32)
155
+ file = model.export(format="tflite", imgsz=32)
156
+ YOLO(file)(SOURCE, imgsz=32)
157
157
 
158
158
 
159
159
  @pytest.mark.skipif(True, reason="Test disabled")
@@ -165,8 +165,8 @@ def test_export_pb():
165
165
  Note TF suffers from install conflicts on Windows and macOS.
166
166
  """
167
167
  model = YOLO(MODEL)
168
- f = model.export(format="pb", imgsz=32)
169
- YOLO(f)(SOURCE, imgsz=32)
168
+ file = model.export(format="pb", imgsz=32)
169
+ YOLO(file)(SOURCE, imgsz=32)
170
170
 
171
171
 
172
172
  @pytest.mark.skipif(True, reason="Test disabled as Paddle protobuf and ONNX protobuf requirementsk conflict.")
@@ -182,5 +182,5 @@ def test_export_paddle():
182
182
  @pytest.mark.slow
183
183
  def test_export_ncnn():
184
184
  """Test YOLO exports to NCNN format."""
185
- f = YOLO(MODEL).export(format="ncnn", imgsz=32)
186
- YOLO(f)(SOURCE, imgsz=32) # exported model inference
185
+ file = YOLO(MODEL).export(format="ncnn", imgsz=32)
186
+ YOLO(file)(SOURCE, imgsz=32) # exported model inference
@@ -1,6 +1,6 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
- __version__ = "8.2.19"
3
+ __version__ = "8.2.21"
4
4
 
5
5
  from ultralytics.data.explorer.explorer import Explorer
6
6
  from ultralytics.models import RTDETR, SAM, YOLO, YOLOWorld
@@ -83,6 +83,7 @@ from ultralytics.utils import (
83
83
  WINDOWS,
84
84
  __version__,
85
85
  callbacks,
86
+ checks,
86
87
  colorstr,
87
88
  get_default_args,
88
89
  yaml_save,
@@ -184,6 +185,7 @@ class Exporter:
184
185
  if sum(flags) != 1:
185
186
  raise ValueError(f"Invalid export format='{fmt}'. Valid formats are {fmts}")
186
187
  jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle, ncnn = flags # export booleans
188
+ is_tf_format = any((saved_model, pb, tflite, edgetpu, tfjs))
187
189
 
188
190
  # Device
189
191
  if fmt == "engine" and self.args.device is None:
@@ -243,7 +245,7 @@ class Exporter:
243
245
  m.dynamic = self.args.dynamic
244
246
  m.export = True
245
247
  m.format = self.args.format
246
- elif isinstance(m, C2f) and not any((saved_model, pb, tflite, edgetpu, tfjs)):
248
+ elif isinstance(m, C2f) and not is_tf_format:
247
249
  # EdgeTPU does not support FlexSplitV while split provides cleaner ONNX graph
248
250
  m.forward = m.forward_split
249
251
 
@@ -303,7 +305,7 @@ class Exporter:
303
305
  f[3], _ = self.export_openvino()
304
306
  if coreml: # CoreML
305
307
  f[4], _ = self.export_coreml()
306
- if any((saved_model, pb, tflite, edgetpu, tfjs)): # TensorFlow formats
308
+ if is_tf_format: # TensorFlow formats
307
309
  self.args.int8 |= edgetpu
308
310
  f[5], keras_model = self.export_saved_model()
309
311
  if pb or tfjs: # pb prerequisite to tfjs
@@ -777,11 +779,10 @@ class Exporter:
777
779
  _ = self.cache.write_bytes(cache)
778
780
 
779
781
  # Load dataset w/ builder (for batching) and calibrate
780
- dataset = self.get_int8_calibration_dataloader(prefix)
781
782
  config.int8_calibrator = EngineCalibrator(
782
- dataset=dataset,
783
+ dataset=self.get_int8_calibration_dataloader(prefix),
783
784
  batch=2 * self.args.batch,
784
- cache=self.file.with_suffix(".cache"),
785
+ cache=str(self.file.with_suffix(".cache")),
785
786
  )
786
787
 
787
788
  elif half:
@@ -813,7 +814,7 @@ class Exporter:
813
814
  except ImportError:
814
815
  suffix = "-macos" if MACOS else "-aarch64" if ARM64 else "" if cuda else "-cpu"
815
816
  version = "" if ARM64 else "<=2.13.1"
816
- check_requirements(f"tensorflow{suffix}{version}")
817
+ check_requirements((f"tensorflow{suffix}{version}", "keras"))
817
818
  import tensorflow as tf # noqa
818
819
  if ARM64:
819
820
  check_requirements("cmake") # 'cmake' is needed to build onnxsim on aarch64
@@ -828,8 +829,8 @@ class Exporter:
828
829
  "flatbuffers>=23.5.26,<100", # update old 'flatbuffers' included inside tensorflow package
829
830
  "onnxruntime-gpu" if cuda else "onnxruntime",
830
831
  ),
831
- cmds="--extra-index-url https://pypi.ngc.nvidia.com",
832
- ) # onnx_graphsurgeon only on NVIDIA
832
+ cmds="--extra-index-url https://pypi.ngc.nvidia.com", # onnx_graphsurgeon only on NVIDIA
833
+ )
833
834
 
834
835
  LOGGER.info(f"\n{prefix} starting export with tensorflow {tf.__version__}...")
835
836
  check_version(
@@ -855,24 +856,17 @@ class Exporter:
855
856
  f_onnx, _ = self.export_onnx()
856
857
 
857
858
  # Export to TF
858
- tmp_file = f / "tmp_tflite_int8_calibration_images.npy" # int8 calibration images file
859
859
  np_data = None
860
860
  if self.args.int8:
861
+ tmp_file = f / "tmp_tflite_int8_calibration_images.npy" # int8 calibration images file
861
862
  verbosity = "info"
862
863
  if self.args.data:
863
- # Generate calibration data for integer quantization
864
- dataloader = self.get_int8_calibration_dataloader(prefix)
865
- images = []
866
- for i, batch in enumerate(dataloader):
867
- if i >= 100: # maximum number of calibration images
868
- break
869
- im = batch["img"].permute(1, 2, 0)[None] # list to nparray, CHW to BHWC
870
- images.append(im)
871
864
  f.mkdir()
865
+ images = [batch["img"].permute(0, 2, 3, 1) for batch in self.get_int8_calibration_dataloader(prefix)]
872
866
  images = torch.cat(images, 0).float()
873
867
  # mean = images.view(-1, 3).mean(0) # imagenet mean [123.675, 116.28, 103.53]
874
868
  # std = images.view(-1, 3).std(0) # imagenet std [58.395, 57.12, 57.375]
875
- np.save(str(tmp_file), images.numpy()) # BHWC
869
+ np.save(str(tmp_file), images.numpy().astype(np.float32)) # BHWC
876
870
  np_data = [["images", tmp_file, [[[[0, 0, 0]]]], [[[[255, 255, 255]]]]]]
877
871
  else:
878
872
  verbosity = "error"
@@ -1015,12 +1009,18 @@ class Exporter:
1015
1009
 
1016
1010
  def _add_tflite_metadata(self, file):
1017
1011
  """Add metadata to *.tflite models per https://www.tensorflow.org/lite/models/convert/metadata."""
1018
- from tflite_support import flatbuffers # noqa
1019
- from tflite_support import metadata as _metadata # noqa
1020
- from tflite_support import metadata_schema_py_generated as _metadata_fb # noqa
1012
+ import flatbuffers
1013
+
1014
+ if ARM64:
1015
+ from tflite_support import metadata # noqa
1016
+ from tflite_support import metadata_schema_py_generated as schema # noqa
1017
+ else:
1018
+ # TFLite Support bug https://github.com/tensorflow/tflite-support/issues/954#issuecomment-2108570845
1019
+ from tensorflow_lite_support.metadata import metadata_schema_py_generated as schema # noqa
1020
+ from tensorflow_lite_support.metadata.python import metadata # noqa
1021
1021
 
1022
1022
  # Create model info
1023
- model_meta = _metadata_fb.ModelMetadataT()
1023
+ model_meta = schema.ModelMetadataT()
1024
1024
  model_meta.name = self.metadata["description"]
1025
1025
  model_meta.version = self.metadata["version"]
1026
1026
  model_meta.author = self.metadata["author"]
@@ -1031,41 +1031,41 @@ class Exporter:
1031
1031
  with open(tmp_file, "w") as f:
1032
1032
  f.write(str(self.metadata))
1033
1033
 
1034
- label_file = _metadata_fb.AssociatedFileT()
1034
+ label_file = schema.AssociatedFileT()
1035
1035
  label_file.name = tmp_file.name
1036
- label_file.type = _metadata_fb.AssociatedFileType.TENSOR_AXIS_LABELS
1036
+ label_file.type = schema.AssociatedFileType.TENSOR_AXIS_LABELS
1037
1037
 
1038
1038
  # Create input info
1039
- input_meta = _metadata_fb.TensorMetadataT()
1039
+ input_meta = schema.TensorMetadataT()
1040
1040
  input_meta.name = "image"
1041
1041
  input_meta.description = "Input image to be detected."
1042
- input_meta.content = _metadata_fb.ContentT()
1043
- input_meta.content.contentProperties = _metadata_fb.ImagePropertiesT()
1044
- input_meta.content.contentProperties.colorSpace = _metadata_fb.ColorSpaceType.RGB
1045
- input_meta.content.contentPropertiesType = _metadata_fb.ContentProperties.ImageProperties
1042
+ input_meta.content = schema.ContentT()
1043
+ input_meta.content.contentProperties = schema.ImagePropertiesT()
1044
+ input_meta.content.contentProperties.colorSpace = schema.ColorSpaceType.RGB
1045
+ input_meta.content.contentPropertiesType = schema.ContentProperties.ImageProperties
1046
1046
 
1047
1047
  # Create output info
1048
- output1 = _metadata_fb.TensorMetadataT()
1048
+ output1 = schema.TensorMetadataT()
1049
1049
  output1.name = "output"
1050
1050
  output1.description = "Coordinates of detected objects, class labels, and confidence score"
1051
1051
  output1.associatedFiles = [label_file]
1052
1052
  if self.model.task == "segment":
1053
- output2 = _metadata_fb.TensorMetadataT()
1053
+ output2 = schema.TensorMetadataT()
1054
1054
  output2.name = "output"
1055
1055
  output2.description = "Mask protos"
1056
1056
  output2.associatedFiles = [label_file]
1057
1057
 
1058
1058
  # Create subgraph info
1059
- subgraph = _metadata_fb.SubGraphMetadataT()
1059
+ subgraph = schema.SubGraphMetadataT()
1060
1060
  subgraph.inputTensorMetadata = [input_meta]
1061
1061
  subgraph.outputTensorMetadata = [output1, output2] if self.model.task == "segment" else [output1]
1062
1062
  model_meta.subgraphMetadata = [subgraph]
1063
1063
 
1064
1064
  b = flatbuffers.Builder(0)
1065
- b.Finish(model_meta.Pack(b), _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
1065
+ b.Finish(model_meta.Pack(b), metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)
1066
1066
  metadata_buf = b.Output()
1067
1067
 
1068
- populator = _metadata.MetadataPopulator.with_model_file(str(file))
1068
+ populator = metadata.MetadataPopulator.with_model_file(str(file))
1069
1069
  populator.load_metadata_buffer(metadata_buf)
1070
1070
  populator.load_associated_files([str(tmp_file)])
1071
1071
  populator.populate()
@@ -402,8 +402,8 @@ class Results(SimpleClass):
402
402
  )
403
403
  return results
404
404
 
405
- data = self.boxes or self.obb
406
405
  is_obb = self.obb is not None
406
+ data = self.obb if is_obb else self.boxes
407
407
  h, w = self.orig_shape if normalize else (1, 1)
408
408
  for i, row in enumerate(data): # xyxy, track_id if tracking, conf, class_id
409
409
  class_id, conf = int(row.cls), round(row.conf.item(), decimals)
@@ -1,6 +1,7 @@
1
1
  # Ultralytics YOLO 🚀, AGPL-3.0 license
2
2
 
3
3
  from .ai_gym import AIGym
4
+ from .analytics import Analytics
4
5
  from .distance_calculation import DistanceCalculation
5
6
  from .heatmap import Heatmap
6
7
  from .object_counter import ObjectCounter
@@ -16,4 +17,5 @@ __all__ = (
16
17
  "ParkingManagement",
17
18
  "QueueManager",
18
19
  "SpeedEstimator",
20
+ "Analytics",
19
21
  )
@@ -73,11 +73,11 @@ class AIGym:
73
73
  self.stage = ["-" for _ in results[0]]
74
74
 
75
75
  self.keypoints = results[0].keypoints.data
76
- self.annotator = Annotator(im0, line_width=2)
76
+ self.annotator = Annotator(im0, line_width=self.tf)
77
77
 
78
78
  for ind, k in enumerate(reversed(self.keypoints)):
79
79
  # Estimate angle and draw specific points based on pose type
80
- if self.pose_type in {"pushup", "pullup", "abworkout"}:
80
+ if self.pose_type in {"pushup", "pullup", "abworkout", "squat"}:
81
81
  self.angle[ind] = self.annotator.estimate_pose_angle(
82
82
  k[int(self.kpts_to_check[0])].cpu(),
83
83
  k[int(self.kpts_to_check[1])].cpu(),
@@ -93,7 +93,7 @@ class AIGym:
93
93
  self.stage[ind] = "up"
94
94
  self.count[ind] += 1
95
95
 
96
- elif self.pose_type == "pushup":
96
+ elif self.pose_type == "pushup" or self.pose_type == "squat":
97
97
  if self.angle[ind] > self.poseup_angle:
98
98
  self.stage[ind] = "up"
99
99
  if self.angle[ind] < self.posedown_angle and self.stage[ind] == "up":
@@ -0,0 +1,197 @@
1
+ from itertools import cycle
2
+
3
+ import cv2
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
7
+ from matplotlib.figure import Figure
8
+
9
+
10
+ class Analytics:
11
+ """A class to create and update various types of charts (line, bar, pie) for visual analytics."""
12
+
13
+ def __init__(
14
+ self,
15
+ type,
16
+ writer,
17
+ im0_shape,
18
+ title="ultralytics",
19
+ x_label="x",
20
+ y_label="y",
21
+ bg_color="white",
22
+ fg_color="black",
23
+ line_color="yellow",
24
+ line_width=2,
25
+ fontsize=13,
26
+ view_img=False,
27
+ save_img=True,
28
+ ):
29
+ """
30
+ Initialize the Analytics class with various chart types.
31
+
32
+ Args:
33
+ type (str): Type of chart to initialize ('line', 'bar', or 'pie').
34
+ writer: Video writer object to save the frames.
35
+ im0_shape (tuple): Shape of the input image (width, height).
36
+ title (str): Title of the chart.
37
+ x_label (str): Label for the x-axis.
38
+ y_label (str): Label for the y-axis.
39
+ bg_color (str): Background color of the chart.
40
+ fg_color (str): Foreground (text) color of the chart.
41
+ line_color (str): Line color for line charts.
42
+ line_width (int): Width of the lines in line charts.
43
+ fontsize (int): Font size for chart text.
44
+ view_img (bool): Whether to display the image.
45
+ save_img (bool): Whether to save the image.
46
+ """
47
+
48
+ self.bg_color = bg_color
49
+ self.fg_color = fg_color
50
+ self.view_img = view_img
51
+ self.save_img = save_img
52
+ self.title = title
53
+ self.writer = writer
54
+
55
+ # Set figure size based on image shape
56
+ figsize = (im0_shape[0] / 100, im0_shape[1] / 100)
57
+
58
+ if type == "line":
59
+ # Initialize line plot
60
+ fig = Figure(facecolor=self.bg_color, figsize=figsize)
61
+ self.canvas = FigureCanvas(fig)
62
+ self.ax = fig.add_subplot(111, facecolor=self.bg_color)
63
+ (self.line,) = self.ax.plot([], [], color=line_color, linewidth=line_width)
64
+
65
+ elif type == "bar" or type == "pie":
66
+ # Initialize bar or pie plot
67
+ self.fig, self.ax = plt.subplots(figsize=figsize, facecolor=self.bg_color)
68
+ self.ax.set_facecolor(self.bg_color)
69
+ color_palette = [
70
+ (31, 119, 180),
71
+ (255, 127, 14),
72
+ (44, 160, 44),
73
+ (214, 39, 40),
74
+ (148, 103, 189),
75
+ (140, 86, 75),
76
+ (227, 119, 194),
77
+ (127, 127, 127),
78
+ (188, 189, 34),
79
+ (23, 190, 207),
80
+ ]
81
+ self.color_palette = [(r / 255, g / 255, b / 255, 1) for r, g, b in color_palette]
82
+ self.color_cycle = cycle(self.color_palette)
83
+ self.color_mapping = {}
84
+
85
+ # Ensure pie chart is circular
86
+ self.ax.axis("equal") if type == "pie" else None
87
+
88
+ # Set common axis properties
89
+ self.ax.set_title(self.title, color=self.fg_color, fontsize=fontsize)
90
+ self.ax.set_xlabel(x_label, color=self.fg_color, fontsize=fontsize - 3)
91
+ self.ax.set_ylabel(y_label, color=self.fg_color, fontsize=fontsize - 3)
92
+ self.ax.tick_params(axis="both", colors=self.fg_color)
93
+
94
+ def update_line(self, frame_number, total_counts):
95
+ """
96
+ Update the line graph with new data.
97
+
98
+ Args:
99
+ frame_number (int): The current frame number.
100
+ total_counts (int): The total counts to plot.
101
+ """
102
+
103
+ # Update line graph data
104
+ x_data = self.line.get_xdata()
105
+ y_data = self.line.get_ydata()
106
+ x_data = np.append(x_data, float(frame_number))
107
+ y_data = np.append(y_data, float(total_counts))
108
+ self.line.set_data(x_data, y_data)
109
+ self.ax.relim()
110
+ self.ax.autoscale_view()
111
+ self.canvas.draw()
112
+ im0 = np.array(self.canvas.renderer.buffer_rgba())
113
+ im0 = cv2.cvtColor(im0[:, :, :3], cv2.COLOR_RGBA2BGR)
114
+
115
+ # Display and save the updated graph
116
+ cv2.imshow(self.title, im0) if self.view_img else None
117
+ self.writer.write(im0) if self.save_img else None
118
+
119
+ def update_bar(self, count_dict):
120
+ """
121
+ Update the bar graph with new data.
122
+
123
+ Args:
124
+ count_dict (dict): Dictionary containing the count data to plot.
125
+ """
126
+
127
+ # Update bar graph data
128
+ self.ax.clear()
129
+ self.ax.set_facecolor(self.bg_color)
130
+ labels = list(count_dict.keys())
131
+ counts = list(count_dict.values())
132
+
133
+ # Map labels to colors
134
+ for label in labels:
135
+ if label not in self.color_mapping:
136
+ self.color_mapping[label] = next(self.color_cycle)
137
+
138
+ colors = [self.color_mapping[label] for label in labels]
139
+
140
+ bars = self.ax.bar(labels, counts, color=colors)
141
+ for bar, count in zip(bars, counts):
142
+ self.ax.text(
143
+ bar.get_x() + bar.get_width() / 2,
144
+ bar.get_height(),
145
+ str(count),
146
+ ha="center",
147
+ va="bottom",
148
+ color=self.fg_color,
149
+ )
150
+
151
+ # Display and save the updated graph
152
+ canvas = FigureCanvas(self.fig)
153
+ canvas.draw()
154
+ buf = canvas.buffer_rgba()
155
+ im0 = np.asarray(buf)
156
+ im0 = cv2.cvtColor(im0, cv2.COLOR_RGBA2BGR)
157
+
158
+ self.writer.write(im0) if self.save_img else None
159
+ cv2.imshow(self.title, im0) if self.view_img else None
160
+
161
+ def update_pie(self, classes_dict):
162
+ """
163
+ Update the pie chart with new data.
164
+
165
+ Args:
166
+ classes_dict (dict): Dictionary containing the class data to plot.
167
+ """
168
+
169
+ # Update pie chart data
170
+ labels = list(classes_dict.keys())
171
+ sizes = list(classes_dict.values())
172
+ total = sum(sizes)
173
+ percentages = [size / total * 100 for size in sizes]
174
+ start_angle = 90
175
+ self.ax.clear()
176
+
177
+ # Create pie chart without labels inside the slices
178
+ wedges, autotexts = self.ax.pie(sizes, autopct=None, startangle=start_angle, textprops={"color": self.fg_color})
179
+
180
+ # Construct legend labels with percentages
181
+ legend_labels = [f"{label} ({percentage:.1f}%)" for label, percentage in zip(labels, percentages)]
182
+ self.ax.legend(wedges, legend_labels, title="Classes", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1))
183
+
184
+ # Adjust layout to fit the legend
185
+ self.fig.tight_layout()
186
+ self.fig.subplots_adjust(left=0.1, right=0.75)
187
+
188
+ # Display and save the updated chart
189
+ im0 = self.fig.canvas.draw()
190
+ im0 = np.array(self.fig.canvas.renderer.buffer_rgba())
191
+ im0 = cv2.cvtColor(im0[:, :, :3], cv2.COLOR_RGBA2BGR)
192
+ self.writer.write(im0) if self.save_img else None
193
+ cv2.imshow(self.title, im0) if self.view_img else None
194
+
195
+
196
+ if __name__ == "__main__":
197
+ Analytics("line", writer=None, im0_shape=None)
@@ -23,7 +23,6 @@ from ultralytics.utils import (
23
23
  ASSETS,
24
24
  AUTOINSTALL,
25
25
  IS_COLAB,
26
- IS_DOCKER,
27
26
  IS_JUPYTER,
28
27
  IS_KAGGLE,
29
28
  IS_PIP_PACKAGE,
@@ -322,17 +321,18 @@ def check_font(font="Arial.ttf"):
322
321
  return file
323
322
 
324
323
 
325
- def check_python(minimum: str = "3.8.0") -> bool:
324
+ def check_python(minimum: str = "3.8.0", hard: bool = True) -> bool:
326
325
  """
327
326
  Check current python version against the required minimum version.
328
327
 
329
328
  Args:
330
329
  minimum (str): Required minimum version of python.
330
+ hard (bool, optional): If True, raise an AssertionError if the requirement is not met.
331
331
 
332
332
  Returns:
333
333
  (bool): Whether the installed Python version meets the minimum constraints.
334
334
  """
335
- return check_version(PYTHON_VERSION, minimum, name="Python ", hard=True)
335
+ return check_version(PYTHON_VERSION, minimum, name="Python", hard=hard)
336
336
 
337
337
 
338
338
  @TryExcept()
@@ -735,4 +735,5 @@ def cuda_is_available() -> bool:
735
735
 
736
736
 
737
737
  # Define constants
738
+ IS_PYTHON_MINIMUM_3_10 = check_python("3.10", hard=False)
738
739
  IS_PYTHON_3_12 = PYTHON_VERSION.startswith("3.12")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ultralytics
3
- Version: 8.2.19
3
+ Version: 8.2.21
4
4
  Summary: Ultralytics YOLOv8 for SOTA object detection, multi-object tracking, instance segmentation, pose estimation and image classification.
5
5
  Author: Glenn Jocher, Ayush Chaurasia, Jing Qiu
6
6
  Maintainer: Glenn Jocher, Ayush Chaurasia, Jing Qiu