mblt-vision-python 0.0.0__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 (404) hide show
  1. mblt_vision/__init__.py +86 -0
  2. mblt_vision/_api.py +53 -0
  3. mblt_vision/_compat.py +227 -0
  4. mblt_vision/_model_paths.py +137 -0
  5. mblt_vision/_tasks.py +30 -0
  6. mblt_vision/benchmark/__init__.py +1 -0
  7. mblt_vision/benchmark/argparse_utils.py +106 -0
  8. mblt_vision/benchmark/chart_utils.py +146 -0
  9. mblt_vision/benchmark/io_utils.py +64 -0
  10. mblt_vision/benchmark/summary_utils.py +770 -0
  11. mblt_vision/cli/__init__.py +5 -0
  12. mblt_vision/cli/__main__.py +5 -0
  13. mblt_vision/cli/_vision.py +337 -0
  14. mblt_vision/cli/compile.py +117 -0
  15. mblt_vision/cli/main.py +35 -0
  16. mblt_vision/cli/predict.py +64 -0
  17. mblt_vision/cli/val.py +562 -0
  18. mblt_vision/compile/__init__.py +21 -0
  19. mblt_vision/compile/vision.py +1120 -0
  20. mblt_vision/datasets/__init__.py +15 -0
  21. mblt_vision/datasets/ade20k.yaml +164 -0
  22. mblt_vision/datasets/cityscapes.yaml +54 -0
  23. mblt_vision/datasets/coco.yaml +178 -0
  24. mblt_vision/datasets/dotav1.yaml +28 -0
  25. mblt_vision/datasets/imagenet.yaml +1019 -0
  26. mblt_vision/datasets/imagenet_synsets.txt +1000 -0
  27. mblt_vision/datasets/nyu-depth.yaml +7 -0
  28. mblt_vision/datasets/registry.py +158 -0
  29. mblt_vision/datasets/widerface.yaml +9 -0
  30. mblt_vision/depth_estimation/__init__.py +19 -0
  31. mblt_vision/face_detection/__init__.py +43 -0
  32. mblt_vision/image_classification/__init__.py +311 -0
  33. mblt_vision/instance_segmentation/__init__.py +65 -0
  34. mblt_vision/models/AlexNet.yaml +23 -0
  35. mblt_vision/models/CAFormer_B36.yaml +22 -0
  36. mblt_vision/models/CAFormer_M36.yaml +22 -0
  37. mblt_vision/models/CAFormer_S18.yaml +22 -0
  38. mblt_vision/models/CAFormer_S36.yaml +22 -0
  39. mblt_vision/models/CoAtNet_0_RW_224.yaml +22 -0
  40. mblt_vision/models/CoAtNet_1_RW_224.yaml +22 -0
  41. mblt_vision/models/CoAtNet_2_RW_224.yaml +22 -0
  42. mblt_vision/models/ConvFormer_B36.yaml +22 -0
  43. mblt_vision/models/ConvFormer_M36.yaml +22 -0
  44. mblt_vision/models/ConvFormer_S18.yaml +22 -0
  45. mblt_vision/models/ConvFormer_S36.yaml +22 -0
  46. mblt_vision/models/ConvNext_Base.yaml +23 -0
  47. mblt_vision/models/ConvNext_Large.yaml +23 -0
  48. mblt_vision/models/ConvNext_Small.yaml +23 -0
  49. mblt_vision/models/ConvNext_Tiny.yaml +23 -0
  50. mblt_vision/models/DeiT3_Base_Patch16_224.yaml +22 -0
  51. mblt_vision/models/DeiT3_Base_Patch16_384.yaml +22 -0
  52. mblt_vision/models/DeiT3_Large_Patch16_224.yaml +22 -0
  53. mblt_vision/models/DeiT3_Large_Patch16_384.yaml +22 -0
  54. mblt_vision/models/DeiT3_Medium_Patch16_224.yaml +22 -0
  55. mblt_vision/models/DeiT3_Small_Patch16_224.yaml +22 -0
  56. mblt_vision/models/DeiT3_Small_Patch16_384.yaml +22 -0
  57. mblt_vision/models/DeiT_Base_Patch16_224.yaml +22 -0
  58. mblt_vision/models/DeiT_Base_Patch16_384.yaml +22 -0
  59. mblt_vision/models/DeiT_Small_Patch16_224.yaml +22 -0
  60. mblt_vision/models/DeiT_Tiny_Patch16_224.yaml +22 -0
  61. mblt_vision/models/DenseNet121.yaml +23 -0
  62. mblt_vision/models/DenseNet161.yaml +23 -0
  63. mblt_vision/models/DenseNet169.yaml +23 -0
  64. mblt_vision/models/DenseNet201.yaml +23 -0
  65. mblt_vision/models/EfficientFormer_L1.yaml +22 -0
  66. mblt_vision/models/EfficientFormer_L3.yaml +22 -0
  67. mblt_vision/models/EfficientFormer_L7.yaml +22 -0
  68. mblt_vision/models/EfficientNet_B0.yaml +23 -0
  69. mblt_vision/models/EfficientNet_B1.yaml +32 -0
  70. mblt_vision/models/EfficientNet_B2.yaml +23 -0
  71. mblt_vision/models/EfficientNet_B3.yaml +23 -0
  72. mblt_vision/models/EfficientNet_B4.yaml +23 -0
  73. mblt_vision/models/EfficientNet_B5.yaml +23 -0
  74. mblt_vision/models/EfficientNet_B6.yaml +23 -0
  75. mblt_vision/models/EfficientNet_B7.yaml +23 -0
  76. mblt_vision/models/EfficientNet_V2_L.yaml +23 -0
  77. mblt_vision/models/EfficientNet_V2_M.yaml +23 -0
  78. mblt_vision/models/EfficientNet_V2_S.yaml +23 -0
  79. mblt_vision/models/FlexiVit_Base.yaml +22 -0
  80. mblt_vision/models/FlexiVit_Large.yaml +22 -0
  81. mblt_vision/models/FlexiVit_Small.yaml +22 -0
  82. mblt_vision/models/GELANc-seg.yaml +29 -0
  83. mblt_vision/models/GELANc.yaml +28 -0
  84. mblt_vision/models/GELANe.yaml +28 -0
  85. mblt_vision/models/GELANm.yaml +28 -0
  86. mblt_vision/models/GELANs.yaml +28 -0
  87. mblt_vision/models/GoogLeNet.yaml +23 -0
  88. mblt_vision/models/Inception_V3.yaml +23 -0
  89. mblt_vision/models/LeViT_Conv_128.yaml +22 -0
  90. mblt_vision/models/LeViT_Conv_128S.yaml +22 -0
  91. mblt_vision/models/LeViT_Conv_192.yaml +22 -0
  92. mblt_vision/models/LeViT_Conv_256.yaml +22 -0
  93. mblt_vision/models/LeViT_Conv_384.yaml +22 -0
  94. mblt_vision/models/MNASNet0_5.yaml +23 -0
  95. mblt_vision/models/MNASNet0_75.yaml +23 -0
  96. mblt_vision/models/MNASNet1_0.yaml +23 -0
  97. mblt_vision/models/MNASNet1_3.yaml +23 -0
  98. mblt_vision/models/MobileNet_V2.yaml +32 -0
  99. mblt_vision/models/MobileNet_V3_Large.yaml +32 -0
  100. mblt_vision/models/MobileNet_V3_Small.yaml +23 -0
  101. mblt_vision/models/RegNet_X_16GF.yaml +32 -0
  102. mblt_vision/models/RegNet_X_1_6GF.yaml +32 -0
  103. mblt_vision/models/RegNet_X_32GF.yaml +32 -0
  104. mblt_vision/models/RegNet_X_3_2GF.yaml +32 -0
  105. mblt_vision/models/RegNet_X_400MF.yaml +32 -0
  106. mblt_vision/models/RegNet_X_800MF.yaml +32 -0
  107. mblt_vision/models/RegNet_X_8GF.yaml +32 -0
  108. mblt_vision/models/RegNet_Y_16GF.yaml +76 -0
  109. mblt_vision/models/RegNet_Y_1_6GF.yaml +32 -0
  110. mblt_vision/models/RegNet_Y_32GF.yaml +76 -0
  111. mblt_vision/models/RegNet_Y_3_2GF.yaml +32 -0
  112. mblt_vision/models/RegNet_Y_400MF.yaml +32 -0
  113. mblt_vision/models/RegNet_Y_800MF.yaml +32 -0
  114. mblt_vision/models/RegNet_Y_8GF.yaml +32 -0
  115. mblt_vision/models/RepViT_M0_9.yaml +22 -0
  116. mblt_vision/models/RepViT_M1.yaml +22 -0
  117. mblt_vision/models/RepViT_M1_0.yaml +22 -0
  118. mblt_vision/models/RepViT_M1_1.yaml +22 -0
  119. mblt_vision/models/RepViT_M1_5.yaml +22 -0
  120. mblt_vision/models/RepViT_M2.yaml +22 -0
  121. mblt_vision/models/RepViT_M2_3.yaml +22 -0
  122. mblt_vision/models/RepViT_M3.yaml +22 -0
  123. mblt_vision/models/ResNeXt101_32X8D.yaml +32 -0
  124. mblt_vision/models/ResNeXt101_64X4D.yaml +23 -0
  125. mblt_vision/models/ResNeXt50_32X4D.yaml +32 -0
  126. mblt_vision/models/ResNet101.yaml +32 -0
  127. mblt_vision/models/ResNet152.yaml +32 -0
  128. mblt_vision/models/ResNet18.yaml +23 -0
  129. mblt_vision/models/ResNet34.yaml +23 -0
  130. mblt_vision/models/ResNet50.yaml +32 -0
  131. mblt_vision/models/ShuffleNet_V2_X0_5.yaml +23 -0
  132. mblt_vision/models/ShuffleNet_V2_X1_0.yaml +23 -0
  133. mblt_vision/models/ShuffleNet_V2_X1_5.yaml +23 -0
  134. mblt_vision/models/ShuffleNet_V2_X2_0.yaml +23 -0
  135. mblt_vision/models/SqueezeNet1_0.yaml +23 -0
  136. mblt_vision/models/SqueezeNet1_1.yaml +23 -0
  137. mblt_vision/models/Swin_B.yaml +23 -0
  138. mblt_vision/models/Swin_S.yaml +23 -0
  139. mblt_vision/models/Swin_T.yaml +23 -0
  140. mblt_vision/models/VGG11.yaml +23 -0
  141. mblt_vision/models/VGG11_BN.yaml +23 -0
  142. mblt_vision/models/VGG13.yaml +23 -0
  143. mblt_vision/models/VGG13_BN.yaml +23 -0
  144. mblt_vision/models/VGG16.yaml +23 -0
  145. mblt_vision/models/VGG16_BN.yaml +23 -0
  146. mblt_vision/models/VGG19.yaml +23 -0
  147. mblt_vision/models/VGG19_BN.yaml +23 -0
  148. mblt_vision/models/ViT_B_16.yaml +67 -0
  149. mblt_vision/models/ViT_B_32.yaml +23 -0
  150. mblt_vision/models/ViT_Base_Patch16_224.yaml +22 -0
  151. mblt_vision/models/ViT_Base_Patch16_384.yaml +22 -0
  152. mblt_vision/models/ViT_Base_Patch32_224.yaml +22 -0
  153. mblt_vision/models/ViT_Base_Patch32_384.yaml +22 -0
  154. mblt_vision/models/ViT_Base_Patch8_224.yaml +22 -0
  155. mblt_vision/models/ViT_L_16.yaml +67 -0
  156. mblt_vision/models/ViT_L_32.yaml +23 -0
  157. mblt_vision/models/ViT_Large_Patch16_224.yaml +22 -0
  158. mblt_vision/models/ViT_Large_Patch16_384.yaml +22 -0
  159. mblt_vision/models/ViT_Large_Patch32_384.yaml +22 -0
  160. mblt_vision/models/ViT_Small_Patch16_224.yaml +22 -0
  161. mblt_vision/models/ViT_Small_Patch16_384.yaml +22 -0
  162. mblt_vision/models/ViT_Small_Patch32_224.yaml +22 -0
  163. mblt_vision/models/ViT_Small_Patch32_384.yaml +22 -0
  164. mblt_vision/models/ViT_Tiny_Patch16_224.yaml +22 -0
  165. mblt_vision/models/ViT_Tiny_Patch16_384.yaml +22 -0
  166. mblt_vision/models/VisFormer_Small.yaml +22 -0
  167. mblt_vision/models/VisFormer_Tiny.yaml +22 -0
  168. mblt_vision/models/Wide_ResNet101_2.yaml +32 -0
  169. mblt_vision/models/Wide_ResNet50_2.yaml +32 -0
  170. mblt_vision/models/YOLO11l-cls.yaml +23 -0
  171. mblt_vision/models/YOLO11l-face.yaml +27 -0
  172. mblt_vision/models/YOLO11l-obb.yaml +28 -0
  173. mblt_vision/models/YOLO11l-pose.yaml +28 -0
  174. mblt_vision/models/YOLO11l-seg.yaml +28 -0
  175. mblt_vision/models/YOLO11l.yaml +27 -0
  176. mblt_vision/models/YOLO11m-cls.yaml +23 -0
  177. mblt_vision/models/YOLO11m-face.yaml +27 -0
  178. mblt_vision/models/YOLO11m-obb.yaml +28 -0
  179. mblt_vision/models/YOLO11m-pose.yaml +28 -0
  180. mblt_vision/models/YOLO11m-seg.yaml +28 -0
  181. mblt_vision/models/YOLO11m.yaml +27 -0
  182. mblt_vision/models/YOLO11n-cls.yaml +23 -0
  183. mblt_vision/models/YOLO11n-face.yaml +27 -0
  184. mblt_vision/models/YOLO11n-obb.yaml +28 -0
  185. mblt_vision/models/YOLO11n-pose.yaml +28 -0
  186. mblt_vision/models/YOLO11n-seg.yaml +28 -0
  187. mblt_vision/models/YOLO11n.yaml +27 -0
  188. mblt_vision/models/YOLO11s-cls.yaml +23 -0
  189. mblt_vision/models/YOLO11s-face.yaml +27 -0
  190. mblt_vision/models/YOLO11s-obb.yaml +28 -0
  191. mblt_vision/models/YOLO11s-pose.yaml +28 -0
  192. mblt_vision/models/YOLO11s-seg.yaml +28 -0
  193. mblt_vision/models/YOLO11s.yaml +27 -0
  194. mblt_vision/models/YOLO11x-cls.yaml +23 -0
  195. mblt_vision/models/YOLO11x-obb.yaml +28 -0
  196. mblt_vision/models/YOLO11x-pose.yaml +28 -0
  197. mblt_vision/models/YOLO11x-seg.yaml +28 -0
  198. mblt_vision/models/YOLO11x.yaml +27 -0
  199. mblt_vision/models/YOLO12l-face.yaml +27 -0
  200. mblt_vision/models/YOLO12l-seg.yaml +28 -0
  201. mblt_vision/models/YOLO12l.yaml +27 -0
  202. mblt_vision/models/YOLO12m-face.yaml +27 -0
  203. mblt_vision/models/YOLO12m-seg.yaml +28 -0
  204. mblt_vision/models/YOLO12m.yaml +27 -0
  205. mblt_vision/models/YOLO12n-face.yaml +27 -0
  206. mblt_vision/models/YOLO12n-seg.yaml +28 -0
  207. mblt_vision/models/YOLO12n.yaml +27 -0
  208. mblt_vision/models/YOLO12s-face.yaml +27 -0
  209. mblt_vision/models/YOLO12s-seg.yaml +28 -0
  210. mblt_vision/models/YOLO12s.yaml +27 -0
  211. mblt_vision/models/YOLO12x-seg.yaml +28 -0
  212. mblt_vision/models/YOLO12x.yaml +27 -0
  213. mblt_vision/models/YOLO26l-cls.yaml +23 -0
  214. mblt_vision/models/YOLO26l-depth.yaml +17 -0
  215. mblt_vision/models/YOLO26l-distill.yaml +27 -0
  216. mblt_vision/models/YOLO26l-obb.yaml +28 -0
  217. mblt_vision/models/YOLO26l-pose.yaml +28 -0
  218. mblt_vision/models/YOLO26l-seg.yaml +28 -0
  219. mblt_vision/models/YOLO26l-sem-ade20k.yaml +17 -0
  220. mblt_vision/models/YOLO26l-sem.yaml +17 -0
  221. mblt_vision/models/YOLO26l.yaml +27 -0
  222. mblt_vision/models/YOLO26m-cls.yaml +23 -0
  223. mblt_vision/models/YOLO26m-depth.yaml +17 -0
  224. mblt_vision/models/YOLO26m-distill.yaml +27 -0
  225. mblt_vision/models/YOLO26m-obb.yaml +28 -0
  226. mblt_vision/models/YOLO26m-pose.yaml +28 -0
  227. mblt_vision/models/YOLO26m-seg.yaml +28 -0
  228. mblt_vision/models/YOLO26m-sem-ade20k.yaml +17 -0
  229. mblt_vision/models/YOLO26m-sem.yaml +17 -0
  230. mblt_vision/models/YOLO26m.yaml +27 -0
  231. mblt_vision/models/YOLO26n-cls.yaml +23 -0
  232. mblt_vision/models/YOLO26n-depth.yaml +17 -0
  233. mblt_vision/models/YOLO26n-distill.yaml +27 -0
  234. mblt_vision/models/YOLO26n-obb.yaml +28 -0
  235. mblt_vision/models/YOLO26n-pose.yaml +28 -0
  236. mblt_vision/models/YOLO26n-seg.yaml +28 -0
  237. mblt_vision/models/YOLO26n-sem-ade20k.yaml +17 -0
  238. mblt_vision/models/YOLO26n-sem.yaml +17 -0
  239. mblt_vision/models/YOLO26n.yaml +27 -0
  240. mblt_vision/models/YOLO26s-cls.yaml +23 -0
  241. mblt_vision/models/YOLO26s-depth.yaml +17 -0
  242. mblt_vision/models/YOLO26s-distill.yaml +27 -0
  243. mblt_vision/models/YOLO26s-obb.yaml +28 -0
  244. mblt_vision/models/YOLO26s-pose.yaml +28 -0
  245. mblt_vision/models/YOLO26s-seg.yaml +28 -0
  246. mblt_vision/models/YOLO26s-sem-ade20k.yaml +17 -0
  247. mblt_vision/models/YOLO26s-sem.yaml +17 -0
  248. mblt_vision/models/YOLO26s.yaml +27 -0
  249. mblt_vision/models/YOLO26x-cls.yaml +23 -0
  250. mblt_vision/models/YOLO26x-depth.yaml +17 -0
  251. mblt_vision/models/YOLO26x-distill.yaml +27 -0
  252. mblt_vision/models/YOLO26x-obb.yaml +28 -0
  253. mblt_vision/models/YOLO26x-pose.yaml +28 -0
  254. mblt_vision/models/YOLO26x-seg.yaml +28 -0
  255. mblt_vision/models/YOLO26x-sem-ade20k.yaml +17 -0
  256. mblt_vision/models/YOLO26x-sem.yaml +17 -0
  257. mblt_vision/models/YOLO26x.yaml +27 -0
  258. mblt_vision/models/YOLOv10b.yaml +28 -0
  259. mblt_vision/models/YOLOv10l-face.yaml +28 -0
  260. mblt_vision/models/YOLOv10l.yaml +28 -0
  261. mblt_vision/models/YOLOv10m-face.yaml +28 -0
  262. mblt_vision/models/YOLOv10m.yaml +28 -0
  263. mblt_vision/models/YOLOv10n-face.yaml +28 -0
  264. mblt_vision/models/YOLOv10n.yaml +28 -0
  265. mblt_vision/models/YOLOv10s-face.yaml +28 -0
  266. mblt_vision/models/YOLOv10s.yaml +28 -0
  267. mblt_vision/models/YOLOv10x.yaml +28 -0
  268. mblt_vision/models/YOLOv3-spp.yaml +44 -0
  269. mblt_vision/models/YOLOv3-sppu.yaml +27 -0
  270. mblt_vision/models/YOLOv3-tiny.yaml +38 -0
  271. mblt_vision/models/YOLOv3-tinyu.yaml +27 -0
  272. mblt_vision/models/YOLOv3.yaml +44 -0
  273. mblt_vision/models/YOLOv3u.yaml +27 -0
  274. mblt_vision/models/YOLOv5l-cls.yaml +22 -0
  275. mblt_vision/models/YOLOv5l-seg.yaml +45 -0
  276. mblt_vision/models/YOLOv5l.yaml +44 -0
  277. mblt_vision/models/YOLOv5l6.yaml +50 -0
  278. mblt_vision/models/YOLOv5l6u.yaml +27 -0
  279. mblt_vision/models/YOLOv5lu.yaml +27 -0
  280. mblt_vision/models/YOLOv5m-cls.yaml +22 -0
  281. mblt_vision/models/YOLOv5m-seg.yaml +45 -0
  282. mblt_vision/models/YOLOv5m.yaml +45 -0
  283. mblt_vision/models/YOLOv5m6.yaml +50 -0
  284. mblt_vision/models/YOLOv5m6u.yaml +27 -0
  285. mblt_vision/models/YOLOv5mu.yaml +27 -0
  286. mblt_vision/models/YOLOv5n-cls.yaml +22 -0
  287. mblt_vision/models/YOLOv5n-seg.yaml +45 -0
  288. mblt_vision/models/YOLOv5n.yaml +44 -0
  289. mblt_vision/models/YOLOv5n6.yaml +50 -0
  290. mblt_vision/models/YOLOv5n6u.yaml +27 -0
  291. mblt_vision/models/YOLOv5nu.yaml +27 -0
  292. mblt_vision/models/YOLOv5s-cls.yaml +22 -0
  293. mblt_vision/models/YOLOv5s-seg.yaml +45 -0
  294. mblt_vision/models/YOLOv5s.yaml +44 -0
  295. mblt_vision/models/YOLOv5s6.yaml +50 -0
  296. mblt_vision/models/YOLOv5s6u.yaml +27 -0
  297. mblt_vision/models/YOLOv5su.yaml +27 -0
  298. mblt_vision/models/YOLOv5x-cls.yaml +22 -0
  299. mblt_vision/models/YOLOv5x-seg.yaml +45 -0
  300. mblt_vision/models/YOLOv5x.yaml +44 -0
  301. mblt_vision/models/YOLOv5x6.yaml +50 -0
  302. mblt_vision/models/YOLOv5x6u.yaml +27 -0
  303. mblt_vision/models/YOLOv5xu.yaml +27 -0
  304. mblt_vision/models/YOLOv6m-face.yaml +27 -0
  305. mblt_vision/models/YOLOv6n-face.yaml +27 -0
  306. mblt_vision/models/YOLOv7.yaml +44 -0
  307. mblt_vision/models/YOLOv7d6.yaml +50 -0
  308. mblt_vision/models/YOLOv7e6.yaml +50 -0
  309. mblt_vision/models/YOLOv7e6e.yaml +50 -0
  310. mblt_vision/models/YOLOv7w6.yaml +50 -0
  311. mblt_vision/models/YOLOv7x.yaml +44 -0
  312. mblt_vision/models/YOLOv8l-cls.yaml +23 -0
  313. mblt_vision/models/YOLOv8l-face.yaml +27 -0
  314. mblt_vision/models/YOLOv8l-obb.yaml +28 -0
  315. mblt_vision/models/YOLOv8l-pose.yaml +28 -0
  316. mblt_vision/models/YOLOv8l-seg.yaml +28 -0
  317. mblt_vision/models/YOLOv8l.yaml +27 -0
  318. mblt_vision/models/YOLOv8m-cls.yaml +23 -0
  319. mblt_vision/models/YOLOv8m-face.yaml +27 -0
  320. mblt_vision/models/YOLOv8m-obb.yaml +28 -0
  321. mblt_vision/models/YOLOv8m-pose.yaml +28 -0
  322. mblt_vision/models/YOLOv8m-seg.yaml +28 -0
  323. mblt_vision/models/YOLOv8m.yaml +27 -0
  324. mblt_vision/models/YOLOv8n-cls.yaml +23 -0
  325. mblt_vision/models/YOLOv8n-face.yaml +27 -0
  326. mblt_vision/models/YOLOv8n-obb.yaml +28 -0
  327. mblt_vision/models/YOLOv8n-pose.yaml +28 -0
  328. mblt_vision/models/YOLOv8n-seg.yaml +28 -0
  329. mblt_vision/models/YOLOv8n.yaml +27 -0
  330. mblt_vision/models/YOLOv8s-cls.yaml +23 -0
  331. mblt_vision/models/YOLOv8s-obb.yaml +28 -0
  332. mblt_vision/models/YOLOv8s-pose.yaml +28 -0
  333. mblt_vision/models/YOLOv8s-seg.yaml +28 -0
  334. mblt_vision/models/YOLOv8s.yaml +27 -0
  335. mblt_vision/models/YOLOv8x-cls.yaml +23 -0
  336. mblt_vision/models/YOLOv8x-obb.yaml +28 -0
  337. mblt_vision/models/YOLOv8x-pose-p6.yaml +28 -0
  338. mblt_vision/models/YOLOv8x-pose.yaml +28 -0
  339. mblt_vision/models/YOLOv8x-seg.yaml +28 -0
  340. mblt_vision/models/YOLOv8x.yaml +27 -0
  341. mblt_vision/models/YOLOv9c-seg.yaml +28 -0
  342. mblt_vision/models/YOLOv9c.yaml +27 -0
  343. mblt_vision/models/YOLOv9e-seg.yaml +28 -0
  344. mblt_vision/models/YOLOv9e.yaml +27 -0
  345. mblt_vision/models/YOLOv9m.yaml +27 -0
  346. mblt_vision/models/YOLOv9s.yaml +27 -0
  347. mblt_vision/models/YOLOv9t.yaml +27 -0
  348. mblt_vision/obb/__init__.py +39 -0
  349. mblt_vision/object_detection/__init__.py +153 -0
  350. mblt_vision/pose_estimation/__init__.py +41 -0
  351. mblt_vision/py.typed +1 -0
  352. mblt_vision/semantic_segmentation/__init__.py +29 -0
  353. mblt_vision/utils/__init__.py +0 -0
  354. mblt_vision/utils/datasets/__init__.py +85 -0
  355. mblt_vision/utils/datasets/ade20k.py +41 -0
  356. mblt_vision/utils/datasets/cityscapes.py +66 -0
  357. mblt_vision/utils/datasets/coco.py +243 -0
  358. mblt_vision/utils/datasets/dataloader.py +1016 -0
  359. mblt_vision/utils/datasets/dotav1.py +59 -0
  360. mblt_vision/utils/datasets/imagenet.py +29 -0
  361. mblt_vision/utils/datasets/organizer.py +2145 -0
  362. mblt_vision/utils/datasets/readiness.py +1063 -0
  363. mblt_vision/utils/evaluation/__init__.py +51 -0
  364. mblt_vision/utils/evaluation/_result.py +22 -0
  365. mblt_vision/utils/evaluation/eval_ade20k.py +302 -0
  366. mblt_vision/utils/evaluation/eval_cityscapes.py +32 -0
  367. mblt_vision/utils/evaluation/eval_coco.py +465 -0
  368. mblt_vision/utils/evaluation/eval_dota.py +878 -0
  369. mblt_vision/utils/evaluation/eval_imagenet.py +151 -0
  370. mblt_vision/utils/evaluation/eval_nyu_depth.py +189 -0
  371. mblt_vision/utils/evaluation/eval_widerface.py +440 -0
  372. mblt_vision/utils/letterbox.py +118 -0
  373. mblt_vision/utils/postprocess/__init__.py +9 -0
  374. mblt_vision/utils/postprocess/_letterbox.py +102 -0
  375. mblt_vision/utils/postprocess/base.py +743 -0
  376. mblt_vision/utils/postprocess/build_post.py +120 -0
  377. mblt_vision/utils/postprocess/cls_post.py +117 -0
  378. mblt_vision/utils/postprocess/common.py +1571 -0
  379. mblt_vision/utils/postprocess/depth_post.py +106 -0
  380. mblt_vision/utils/postprocess/semantic_seg_post.py +192 -0
  381. mblt_vision/utils/postprocess/yolo_anchor_post.py +469 -0
  382. mblt_vision/utils/postprocess/yolo_anchorless_post.py +952 -0
  383. mblt_vision/utils/postprocess/yolo_dflfree_post.py +983 -0
  384. mblt_vision/utils/postprocess/yolo_nmsfree_post.py +176 -0
  385. mblt_vision/utils/preprocess/__init__.py +27 -0
  386. mblt_vision/utils/preprocess/_validation.py +66 -0
  387. mblt_vision/utils/preprocess/base.py +157 -0
  388. mblt_vision/utils/preprocess/build_pre.py +48 -0
  389. mblt_vision/utils/preprocess/center_crop.py +75 -0
  390. mblt_vision/utils/preprocess/letterbox.py +123 -0
  391. mblt_vision/utils/preprocess/normalize.py +94 -0
  392. mblt_vision/utils/preprocess/order.py +74 -0
  393. mblt_vision/utils/preprocess/reader.py +94 -0
  394. mblt_vision/utils/preprocess/resize.py +202 -0
  395. mblt_vision/utils/preprocess/yolo_pre.py +7 -0
  396. mblt_vision/utils/results.py +725 -0
  397. mblt_vision/utils/types.py +15 -0
  398. mblt_vision/wrapper.py +1121 -0
  399. mblt_vision_python-0.0.0.dist-info/METADATA +152 -0
  400. mblt_vision_python-0.0.0.dist-info/RECORD +404 -0
  401. mblt_vision_python-0.0.0.dist-info/WHEEL +5 -0
  402. mblt_vision_python-0.0.0.dist-info/entry_points.txt +2 -0
  403. mblt_vision_python-0.0.0.dist-info/licenses/LICENSE +28 -0
  404. mblt_vision_python-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,743 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from collections.abc import Sequence
5
+ from typing import Any, cast
6
+
7
+ import numpy as np
8
+ import torch
9
+
10
+ from ..._tasks import normalize_vision_task
11
+ from ..letterbox import RatioPad
12
+ from ..preprocess._validation import normalize_image_size
13
+ from ..types import ListTensorLike, TensorLike
14
+ from .common import nmsout2eval, process_mask_upsample
15
+
16
+
17
+ class PostBase(ABC):
18
+ """Abstract base class for postprocessing."""
19
+
20
+ def __init__(self) -> None:
21
+ """Initialize PostBase."""
22
+ super().__init__()
23
+ self.device = torch.device("cpu")
24
+
25
+ @abstractmethod
26
+ def __call__(
27
+ self, x: TensorLike | ListTensorLike, *args: Any, **kwargs: Any
28
+ ) -> Any:
29
+ """Executes postprocessing on the model output.
30
+
31
+ Args:
32
+ x (TensorLike | ListTensorLike): Input tensor or list of tensors from the model.
33
+ *args (Any): Additional positional arguments depending on the specific task.
34
+ **kwargs (Any): Additional keyword arguments depending on the specific task.
35
+
36
+ Returns:
37
+ Any: Postprocessed results, format depends on the specific task.
38
+ """
39
+ pass
40
+
41
+ def to(self, device: str | torch.device) -> None:
42
+ """Move the operations to the specified device.
43
+ Args:
44
+ device (str | torch.device): Device to move the operations to.
45
+ """
46
+ if isinstance(device, str):
47
+ self.device = torch.device(device)
48
+ elif isinstance(device, torch.device):
49
+ self.device = device
50
+ else:
51
+ raise TypeError(f"Got unexpected type for device={type(device)}.")
52
+ for name, value in self.__dict__.items():
53
+ if isinstance(value, torch.Tensor):
54
+ setattr(self, name, value.to(self.device))
55
+
56
+
57
+ class YOLODetectionPostBase(PostBase):
58
+ """Base class for YOLO postprocessing."""
59
+
60
+ NC_BY_DATASET_TASK: dict[tuple[str, str], int] = {
61
+ ("coco", "object_detection"): 80,
62
+ ("coco", "instance_segmentation"): 80,
63
+ ("coco", "pose_estimation"): 1,
64
+ ("dotav1", "obb"): 15,
65
+ ("widerface", "face_detection"): 1,
66
+ }
67
+ DEFAULT_NC_BY_TASK: dict[str, int] = {
68
+ "object_detection": 80,
69
+ "instance_segmentation": 80,
70
+ "pose_estimation": 1,
71
+ "obb": 15,
72
+ "face_detection": 1,
73
+ }
74
+
75
+ def __init__(
76
+ self, pre_cfg: dict[str, Any], post_cfg: dict[str, Any], **kwargs
77
+ ) -> None:
78
+ """Initialize the common YOLO detection postprocessor.
79
+
80
+ Args:
81
+ pre_cfg (dict): Preprocessing configuration.
82
+ post_cfg (dict): Postprocessing configuration.
83
+ **kwargs: Optional runtime overrides for postprocess behavior.
84
+
85
+ Raises:
86
+ TypeError: If unsupported keyword overrides are provided.
87
+ """
88
+ super().__init__()
89
+ letterbox_cfg = pre_cfg.get("LetterBox")
90
+ if letterbox_cfg is None:
91
+ raise ValueError("LetterBox configuration should be provided in pre_cfg")
92
+ img_size = letterbox_cfg["img_size"]
93
+ self.imh: int
94
+ self.imw: int
95
+ self.imh, self.imw = normalize_image_size(
96
+ img_size, name="pre_cfg.LetterBox.img_size"
97
+ )
98
+ task = post_cfg.get("task")
99
+ if task is None:
100
+ raise ValueError("task should be provided in post_cfg")
101
+ self.task = normalize_vision_task(task)
102
+ task_key = self.task
103
+ dataset = post_cfg.get("dataset")
104
+ self.dataset = dataset.lower() if isinstance(dataset, str) else None
105
+ dataset_nc = (
106
+ self.NC_BY_DATASET_TASK.get((self.dataset, task_key))
107
+ if self.dataset is not None
108
+ else None
109
+ )
110
+ configured_nc = kwargs.pop("nc", post_cfg.get("nc"))
111
+ if (
112
+ configured_nc is not None
113
+ and dataset_nc is not None
114
+ and int(configured_nc) != dataset_nc
115
+ ):
116
+ raise ValueError(
117
+ f"nc={configured_nc} conflicts with dataset '{self.dataset}' and task '{self.task}', "
118
+ f"which require nc={dataset_nc}."
119
+ )
120
+ default_nc = (
121
+ dataset_nc
122
+ if dataset_nc is not None
123
+ else self.DEFAULT_NC_BY_TASK.get(task_key)
124
+ )
125
+ nc = configured_nc if configured_nc is not None else default_nc
126
+ if nc is None:
127
+ raise ValueError(
128
+ f"nc should be provided in post_cfg or kwargs for task '{self.task}'."
129
+ )
130
+ self.nc: int = int(nc)
131
+ self.anchors: list[Any] | torch.Tensor | None = post_cfg.get(
132
+ "anchors", None
133
+ ) # anchor coordinates
134
+ self.stride: list[int] | torch.Tensor
135
+ self.nl: int
136
+ self.na: int
137
+ self.conf_thres: float
138
+ self.iou_thres: float
139
+ self.inv_conf_thres: float
140
+
141
+ self.e2e = bool(kwargs.pop("e2e", post_cfg.get("e2e", True)))
142
+ if kwargs:
143
+ unexpected = ", ".join(sorted(kwargs))
144
+ raise TypeError(f"Unexpected YOLO postprocess kwargs: {unexpected}")
145
+
146
+ if self.anchors is None:
147
+ nl = post_cfg.get("nl")
148
+ if nl is None:
149
+ raise ValueError("nl should be provided in post_cfg")
150
+ self.nl = nl
151
+ if self.nl == 2:
152
+ self.stride = [2 ** (4 + i) for i in range(self.nl)]
153
+ else:
154
+ self.stride = [2 ** (3 + i) for i in range(self.nl)]
155
+ self.make_anchors()
156
+ else:
157
+ if not isinstance(self.anchors, list):
158
+ raise TypeError(
159
+ f"anchors must be a list, got {type(self.anchors).__name__}."
160
+ )
161
+ self.nl = len(self.anchors)
162
+ self.na = len(self.anchors[0]) // 2
163
+ self.n_extra: int = post_cfg.get("n_extra", 0)
164
+ self.conf_thres = float(post_cfg.get("conf_thres", 0.25))
165
+ self.iou_thres = float(post_cfg.get("iou_thres", 0.7))
166
+ self.set_threshold()
167
+
168
+ def anchors_as_list(self) -> list[Any]:
169
+ """Return anchors as the configured anchor list."""
170
+ if not isinstance(self.anchors, list):
171
+ raise TypeError(
172
+ "anchors should be a list for anchor-based YOLO postprocessing."
173
+ )
174
+ return self.anchors
175
+
176
+ def anchors_as_tensor(self) -> torch.Tensor:
177
+ """Return anchors as the generated anchor-point tensor."""
178
+ if not isinstance(self.anchors, torch.Tensor):
179
+ raise TypeError(
180
+ "anchors should be a tensor for anchor-free YOLO postprocessing."
181
+ )
182
+ return cast(torch.Tensor, self.anchors)
183
+
184
+ def stride_as_tensor(self) -> torch.Tensor:
185
+ """Return strides as the generated stride tensor."""
186
+ if not isinstance(self.stride, torch.Tensor):
187
+ raise TypeError(
188
+ "stride should be a tensor for anchor-free YOLO postprocessing."
189
+ )
190
+ return cast(torch.Tensor, self.stride)
191
+
192
+ def __call__(
193
+ self,
194
+ x: TensorLike | ListTensorLike,
195
+ conf_thres: float | None = None,
196
+ iou_thres: float | None = None,
197
+ multi_label: bool = False,
198
+ ) -> list[Any]:
199
+ """Executes YOLO postprocessing.
200
+
201
+ Includes rearranging, decoding, and NMS.
202
+
203
+ Args:
204
+ x (TensorLike | ListTensorLike): Raw model outputs.
205
+ conf_thres (float | None): Confidence threshold for detection.
206
+ iou_thres (float | None): IoU threshold for NMS.
207
+ multi_label: Whether to emit one candidate for every class above the
208
+ confidence threshold. Validation uses this to match Ultralytics.
209
+
210
+ Returns:
211
+ list: List of detections per image.
212
+ """
213
+ self.set_threshold(conf_thres, iou_thres)
214
+ final_detections, proto_outs = self.extract_final_outputs(x)
215
+ if final_detections is not None:
216
+ if proto_outs is not None:
217
+ return self.masking(final_detections, proto_outs)
218
+ return final_detections
219
+ checked_input = self.check_input(x)
220
+
221
+ if not self.e2e:
222
+ return self.non_e2e(checked_input)
223
+
224
+ predictions, proto_outs = self._pre_process(checked_input)
225
+
226
+ nms_output = (
227
+ self.nms_multilabel(predictions) if multi_label else self.nms(predictions)
228
+ )
229
+
230
+ if proto_outs is not None:
231
+ return self.masking(nms_output, proto_outs)
232
+ return nms_output
233
+
234
+ def non_e2e(self, x: list[torch.Tensor]) -> Any:
235
+ """Return the export-style postprocess output when end-to-end mode is disabled.
236
+
237
+ Args:
238
+ x: Checked raw model outputs.
239
+
240
+ Returns:
241
+ Export-style tensors whose batch dimensions remain intact.
242
+ """
243
+ if len(x) == 1:
244
+ return self.conversion(x)
245
+ return self.rearrange(x)
246
+
247
+ def _pre_process(
248
+ self,
249
+ x: list[torch.Tensor],
250
+ ) -> tuple[Any, torch.Tensor | list[torch.Tensor] | None]:
251
+ """Protected method to preprocess inputs into (predictions, prototypes).
252
+
253
+ Args:
254
+ x: List of input tensors.
255
+
256
+ Returns:
257
+ Tuple of (predictions, prototypes). Prototypes may be None.
258
+ """
259
+ if len(x) == 1:
260
+ converted = self.conversion(x)
261
+ if not isinstance(converted, torch.Tensor):
262
+ raise TypeError(
263
+ "conversion should return a tensor for single-output YOLO postprocessing."
264
+ )
265
+ return self.filter_conversion(converted), None
266
+ rearranged = self.rearrange(x)
267
+ return self.decode(rearranged), None
268
+
269
+ def nmsout2eval(
270
+ self,
271
+ nms_out: Any,
272
+ img1_shape: tuple[int, int],
273
+ img0_shape: tuple[int, int] | list[tuple[int, int]],
274
+ ratio_pad: RatioPad | list[RatioPad | None] | None = None,
275
+ ) -> tuple[Any, ...]:
276
+ """Converts NMS output to evaluation format (labels, boxes, scores).
277
+
278
+ Args:
279
+ nms_out: NMS output (tensor or list of tensors).
280
+ img1_shape: Resized image shape (height, width).
281
+ img0_shape: Original image shape(s).
282
+
283
+ Returns:
284
+ Tuple: task-specific results.
285
+ - Detection: (labels_list, boxes_list, scores_list)
286
+ - Segmentation/Pose: (labels_list, boxes_list, scores_list, extra_list)
287
+ """
288
+
289
+ return nmsout2eval(nms_out, img1_shape, img0_shape, ratio_pads=ratio_pad)
290
+
291
+ def extract_final_outputs(
292
+ self,
293
+ x: TensorLike | ListTensorLike,
294
+ ) -> tuple[list[torch.Tensor] | None, torch.Tensor | None]:
295
+ """Extract already-decoded ONNX-style detections when present.
296
+
297
+ Args:
298
+ x: Raw postprocess input.
299
+
300
+ Returns:
301
+ A tuple of ``(detections, prototypes)`` when the input already contains
302
+ final detections, otherwise ``(None, None)``.
303
+ """
304
+
305
+ final_det_dim = 6 + self.n_extra
306
+
307
+ if isinstance(x, Sequence):
308
+ if not x:
309
+ return None, None
310
+
311
+ normalized_detections: np.ndarray | torch.Tensor | None = None
312
+ normalized_proto: torch.Tensor | None = None
313
+ invalid_proto_error: ValueError | None = None
314
+ for output in x:
315
+ if not isinstance(output, (np.ndarray, torch.Tensor)):
316
+ continue
317
+ if normalized_detections is None:
318
+ normalized_detections = self._normalize_final_detection_tensor(
319
+ output, final_det_dim
320
+ )
321
+ if normalized_detections is not None:
322
+ continue
323
+ if normalized_proto is None:
324
+ try:
325
+ normalized_proto = self._normalize_proto_batch(output)
326
+ except ValueError as exc:
327
+ if self.task == "instance_segmentation" and output.ndim == 4:
328
+ # Defer this until detections are found so unrelated
329
+ # four-dimensional outputs do not prevent raw-head
330
+ # decoding. Once this is a decoded segmentation output,
331
+ # every candidate prototype must be valid regardless of
332
+ # its position in the backend output sequence.
333
+ invalid_proto_error = exc
334
+ continue
335
+
336
+ if normalized_detections is not None:
337
+ if invalid_proto_error is not None:
338
+ raise invalid_proto_error
339
+ if self.task == "instance_segmentation" and normalized_proto is None:
340
+ raise ValueError(
341
+ "Decoded instance-segmentation outputs require a mask prototype tensor."
342
+ )
343
+ return self._final_detection_batches(
344
+ normalized_detections
345
+ ), normalized_proto
346
+ return None, None
347
+
348
+ normalized_x = self._normalize_final_detection_tensor(x, final_det_dim)
349
+ if normalized_x is not None:
350
+ if self.task == "instance_segmentation":
351
+ raise ValueError(
352
+ "Decoded instance-segmentation outputs require a mask prototype tensor."
353
+ )
354
+ return self._final_detection_batches(normalized_x), None
355
+
356
+ return None, None
357
+
358
+ def _normalize_final_detection_tensor(
359
+ self,
360
+ x: TensorLike,
361
+ final_det_dim: int,
362
+ ) -> np.ndarray | torch.Tensor | None:
363
+ """Return a batched final-detection tensor when ``x`` already contains decoded rows."""
364
+
365
+ while x.ndim == 4 and 1 in (x.shape[0], x.shape[1]):
366
+ if x.shape[1] == 1:
367
+ x = x[:, 0]
368
+ elif x.shape[0] == 1:
369
+ x = x[0]
370
+ if x.ndim == 2 and x.shape[-1] == final_det_dim:
371
+ x = x[None]
372
+ if x.ndim == 3 and x.shape[-1] == final_det_dim:
373
+ return x
374
+ if x.ndim == 3 and x.shape[1] == final_det_dim:
375
+ if isinstance(x, np.ndarray):
376
+ return np.swapaxes(x, 1, 2)
377
+ return x.transpose(1, 2)
378
+
379
+ return None
380
+
381
+ def _final_detection_batches(
382
+ self, x: np.ndarray | torch.Tensor
383
+ ) -> list[torch.Tensor]:
384
+ """Convert batched final detections to the internal per-image tensor list."""
385
+
386
+ if isinstance(x, np.ndarray):
387
+ tensor = torch.from_numpy(x).to(self.device)
388
+ else:
389
+ tensor = x.to(self.device)
390
+ batches: list[torch.Tensor] = []
391
+ for batch in tensor:
392
+ valid_rows = torch.isfinite(batch).all(dim=1)
393
+ if not bool(valid_rows.all()):
394
+ invalid_rows = (
395
+ torch.nonzero(~valid_rows, as_tuple=False)
396
+ .flatten()
397
+ .detach()
398
+ .cpu()
399
+ .tolist()
400
+ )
401
+ raise ValueError(
402
+ "Decoded detection rows must contain only finite values; "
403
+ f"invalid rows: {invalid_rows}."
404
+ )
405
+ labels = batch[:, 5]
406
+ scores = batch[:, 4]
407
+ if not bool(((scores >= 0) & (scores <= 1)).all()):
408
+ invalid_scores = (
409
+ scores[(scores < 0) | (scores > 1)].detach().cpu().tolist()
410
+ )
411
+ raise ValueError(
412
+ "Decoded detection confidence values must be in [0, 1]; "
413
+ f"got {invalid_scores}."
414
+ )
415
+ valid_labels = (
416
+ torch.isfinite(labels)
417
+ & (labels == labels.round())
418
+ & (labels >= 0)
419
+ & (labels < self.nc)
420
+ )
421
+ if not bool(valid_labels.all()):
422
+ invalid_labels = labels[~valid_labels].detach().cpu().tolist()
423
+ raise ValueError(
424
+ "Decoded detection class IDs must be finite integral values in "
425
+ f"[0, {self.nc}); got {invalid_labels}."
426
+ )
427
+ retained = batch[batch[:, 4] > self.conf_thres]
428
+ if getattr(self, "task", "object_detection") == "obb":
429
+ valid_geometry = (retained[:, 2] > 0) & (retained[:, 3] > 0)
430
+ geometry_description = "positive width and height"
431
+ else:
432
+ valid_geometry = (retained[:, 2] > retained[:, 0]) & (
433
+ retained[:, 3] > retained[:, 1]
434
+ )
435
+ geometry_description = "positive xyxy area"
436
+ if not bool(valid_geometry.all()):
437
+ raise ValueError(
438
+ "Decoded detection boxes must have "
439
+ f"{geometry_description} after confidence filtering."
440
+ )
441
+ if getattr(self, "task", "object_detection") == "pose_estimation":
442
+ keypoint_confidences = retained[:, 8::3]
443
+ if not bool(
444
+ ((keypoint_confidences >= 0) & (keypoint_confidences <= 1)).all()
445
+ ):
446
+ raise ValueError(
447
+ "Decoded pose keypoint confidence values must be in [0, 1]."
448
+ )
449
+ batches.append(retained)
450
+ return batches
451
+
452
+ def _normalize_proto_batch(
453
+ self, proto_outs: np.ndarray | torch.Tensor
454
+ ) -> torch.Tensor:
455
+ """Normalize prototype masks to ``(B, H, W, C)`` layout."""
456
+
457
+ if isinstance(proto_outs, np.ndarray):
458
+ proto = torch.from_numpy(proto_outs).to(self.device)
459
+ else:
460
+ proto = proto_outs.to(self.device)
461
+
462
+ if proto.ndim != 4:
463
+ raise ValueError(
464
+ f"Expected 4D prototype tensor, got shape {tuple(proto.shape)}."
465
+ )
466
+ if not bool(torch.isfinite(proto).all()):
467
+ raise ValueError("Mask prototype tensor must contain only finite values.")
468
+ if proto.shape[-1] == self.n_extra:
469
+ return proto
470
+ if proto.shape[1] == self.n_extra:
471
+ return proto.permute(0, 2, 3, 1)
472
+ raise ValueError(f"Unsupported prototype tensor shape {tuple(proto.shape)}.")
473
+
474
+ def make_anchors(self, offset: float = 0.5) -> None:
475
+ """
476
+ Generate anchor points and stride tensors based on image size and strides.
477
+ Args:
478
+ offset (float, optional): Offset for anchor points. Defaults to 0.5.
479
+ """
480
+ anchor_points, stride_tensor = [], []
481
+ strides = [2 ** (3 + i) for i in range(self.nl)]
482
+ if self.nl == 2:
483
+ strides = [strd * 2 for strd in strides]
484
+ for strd in strides:
485
+ ny, nx = self.imh // strd, self.imw // strd
486
+ sy = torch.arange(ny, dtype=torch.float32, device=self.device) + offset
487
+ sx = torch.arange(nx, dtype=torch.float32, device=self.device) + offset
488
+ yv, xv = torch.meshgrid(sy, sx, indexing="ij")
489
+ anchor_points.append(torch.stack((xv, yv), -1).reshape(-1, 2))
490
+ stride_tensor.append(
491
+ torch.full((ny * nx, 1), strd, dtype=torch.float32, device=self.device)
492
+ )
493
+ self.anchors = torch.cat(anchor_points, dim=0).permute(1, 0)
494
+ self.stride = torch.cat(stride_tensor, dim=0).permute(1, 0)
495
+
496
+ def set_threshold(
497
+ self, conf_thres: float | None = None, iou_thres: float | None = None
498
+ ) -> None:
499
+ """Set confidence and IoU thresholds.
500
+ Args:
501
+ conf_thres (float, optional): Confidence threshold.
502
+ iou_thres (float, optional): IoU threshold.
503
+ """
504
+ conf_thres = self.conf_thres if conf_thres is None else conf_thres
505
+ iou_thres = self.iou_thres if iou_thres is None else iou_thres
506
+ if isinstance(conf_thres, bool) or not isinstance(conf_thres, (int, float)):
507
+ raise TypeError(
508
+ f"conf_thres must be numeric, got {type(conf_thres).__name__}."
509
+ )
510
+ if isinstance(iou_thres, bool) or not isinstance(iou_thres, (int, float)):
511
+ raise TypeError(
512
+ f"iou_thres must be numeric, got {type(iou_thres).__name__}."
513
+ )
514
+ if not 0 < conf_thres < 1:
515
+ raise ValueError(f"conf_thres must be in (0, 1), got {conf_thres}.")
516
+ if not 0 < iou_thres < 1:
517
+ raise ValueError(f"iou_thres must be in (0, 1), got {iou_thres}.")
518
+ self.conf_thres = float(conf_thres)
519
+ self.iou_thres = float(iou_thres)
520
+ self.inv_conf_thres = -np.log(1 / conf_thres - 1)
521
+
522
+ def check_input(self, x: TensorLike | ListTensorLike) -> list[torch.Tensor]:
523
+ """Check and prepare input tensors.
524
+ Args:
525
+ x (TensorLike | ListTensorLike): Input tensor or list of tensors.
526
+ Returns:
527
+ list[torch.Tensor]: List of tensors on the correct device.
528
+ """
529
+ if isinstance(x, np.ndarray):
530
+ tensors = [torch.from_numpy(x).to(self.device)]
531
+ elif isinstance(x, torch.Tensor):
532
+ tensor_input = cast(torch.Tensor, x)
533
+ tensors = [tensor_input.to(self.device)]
534
+ else:
535
+ if not isinstance(x, Sequence):
536
+ raise TypeError(f"Got unexpected type for x={type(x)}.")
537
+ if all(isinstance(xi, np.ndarray) for xi in x):
538
+ tensors = [torch.from_numpy(xi).to(self.device) for xi in x]
539
+ elif all(isinstance(xi, torch.Tensor) for xi in x):
540
+ torch_inputs = cast(Sequence[torch.Tensor], x)
541
+ tensors = [xi.to(self.device) for xi in torch_inputs]
542
+ else:
543
+ raise TypeError(f"Got unexpected element type for x[0]={type(x[0])}.")
544
+ if any(not bool(torch.isfinite(tensor).all()) for tensor in tensors):
545
+ raise ValueError(
546
+ "Detection output tensors must contain only finite values."
547
+ )
548
+ return self.check_dim(tensors)
549
+
550
+ def check_dim(self, x: list[torch.Tensor]) -> list[torch.Tensor]:
551
+ """Check tensor dimensions.
552
+ Args:
553
+ x (list[torch.Tensor]): List of tensors.
554
+ Returns:
555
+ list[torch.Tensor]: List of tensors with corrected dimensions.
556
+ """
557
+ y = []
558
+ for xi in x:
559
+ if xi.ndim == 3:
560
+ xi = xi.unsqueeze(0)
561
+ elif xi.ndim in (4, 5):
562
+ pass
563
+ else:
564
+ raise ValueError(f"Got unexpected dim for xi={xi.ndim}.")
565
+ y.append(xi)
566
+ return y
567
+
568
+ def normalize_split_head(
569
+ self, x: torch.Tensor, expected_channels: set[int]
570
+ ) -> torch.Tensor:
571
+ """Normalize a split detection head to ``(B, C, H, W)`` layout.
572
+
573
+ This accepts the channel-last tensors produced by ONNX export flows as
574
+ well as the channel-first tensors commonly returned by MXQ/NPU inference.
575
+
576
+ Args:
577
+ x: Raw split-head tensor.
578
+ expected_channels: Valid channel sizes for the current head group.
579
+
580
+ Returns:
581
+ The normalized tensor in ``(B, C, H, W)`` format.
582
+
583
+ Raises:
584
+ ValueError: If the tensor shape cannot be interpreted.
585
+ """
586
+ while x.ndim > 4:
587
+ singleton_dims = [idx for idx, size in enumerate(x.shape) if size == 1]
588
+ if not singleton_dims:
589
+ raise ValueError(
590
+ f"Expected up to 4D split-head tensor, got shape {tuple(x.shape)}."
591
+ )
592
+ x = x.squeeze(singleton_dims[0])
593
+ if x.ndim == 3:
594
+ x = x.unsqueeze(0)
595
+ if x.ndim != 4:
596
+ raise ValueError(
597
+ f"Expected 3D or 4D split-head tensor, got shape {tuple(x.shape)}."
598
+ )
599
+
600
+ if x.shape[1] in expected_channels and x.shape[-1] not in expected_channels:
601
+ return x
602
+ if x.shape[-1] in expected_channels and x.shape[1] not in expected_channels:
603
+ return x.permute(0, 3, 1, 2)
604
+ if x.shape[1] in expected_channels and x.shape[-1] in expected_channels:
605
+ return x
606
+
607
+ raise ValueError(
608
+ f"Could not infer split-head layout for shape {tuple(x.shape)} with expected channels {expected_channels}."
609
+ )
610
+
611
+ @abstractmethod
612
+ def rearrange(self, x: list[torch.Tensor]) -> Any:
613
+ """Rearranges raw model outputs into a task-specific intermediate form.
614
+
615
+ Args:
616
+ x: Raw output tensors from the model.
617
+
618
+ Returns:
619
+ A task-specific intermediate representation used by ``decode``.
620
+ """
621
+
622
+ @abstractmethod
623
+ def decode(self, x: Any) -> Any:
624
+ """Decodes rearranged outputs into a family-specific batched representation.
625
+
626
+ Args:
627
+ x: Rearranged output tensors.
628
+
629
+ Returns:
630
+ Decoded detections in the canonical representation for that YOLO family.
631
+ """
632
+
633
+ def conversion(
634
+ self, x: list[torch.Tensor]
635
+ ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
636
+ """Converts raw outputs into a task-specific intermediate form.
637
+
638
+ Args:
639
+ x: Input tensors.
640
+
641
+ Returns:
642
+ A converted detection tensor, or a ``(detections, prototypes)`` tuple
643
+ for segmentation-style subclasses.
644
+ """
645
+ if len(x) != 1:
646
+ raise ValueError(
647
+ f"Expected exactly one converted model output, got {len(x)}."
648
+ )
649
+ return x[0]
650
+
651
+ @abstractmethod
652
+ def filter_conversion(self, x: torch.Tensor) -> list[torch.Tensor]:
653
+ """Filters converted outputs into per-image detections before NMS.
654
+
655
+ Args:
656
+ x: Converted output tensor.
657
+
658
+ Returns:
659
+ Filtered detections for each image in the batch.
660
+ """
661
+
662
+ @abstractmethod
663
+ def nms(self, x: Any) -> list[torch.Tensor]:
664
+ """Performs non-maximum suppression on decoded detections.
665
+
666
+ Args:
667
+ x: Decoded detections for each image.
668
+
669
+ Returns:
670
+ Detections after NMS for each image in the batch.
671
+ """
672
+
673
+ def nms_multilabel(self, x: Any) -> list[torch.Tensor]:
674
+ """Perform validation NMS with all above-threshold class candidates.
675
+
676
+ Args:
677
+ x: Decoded detections for each image.
678
+
679
+ Returns:
680
+ Detections after NMS for each image in the batch.
681
+ """
682
+ return self.nms(x)
683
+
684
+ def validate_split_head_counts(self, **head_groups: Sequence[object]) -> None:
685
+ """Require every raw split-output group to provide every detection head."""
686
+
687
+ expected_count = self.nl
688
+ counts = {name: len(heads) for name, heads in head_groups.items()}
689
+ if any(count != expected_count for count in counts.values()):
690
+ found_counts = ", ".join(
691
+ f"{name}={count}" for name, count in counts.items()
692
+ )
693
+ raise ValueError(
694
+ "Incomplete split-head outputs: "
695
+ f"expected {expected_count} heads per group, got {found_counts}."
696
+ )
697
+
698
+ def masking(
699
+ self, x: list[torch.Tensor], proto_outs: torch.Tensor | list[torch.Tensor]
700
+ ) -> list[list[torch.Tensor]]:
701
+ """Apply prototype masks to detection results.
702
+
703
+ Args:
704
+ x: Detection results.
705
+ proto_outs: Prototype outputs for masks.
706
+
707
+ Returns:
708
+ list: Detection results with masks.
709
+ """
710
+ if len(x) != len(proto_outs):
711
+ raise ValueError(
712
+ "Detection and prototype batch sizes must match for instance "
713
+ f"segmentation, got {len(x)} detections and {len(proto_outs)} prototypes."
714
+ )
715
+ masks = []
716
+ for pred, proto in zip(x, proto_outs):
717
+ if proto.ndim != 3:
718
+ raise ValueError(
719
+ f"Expected 3D prototype tensor, got shape {tuple(proto.shape)}."
720
+ )
721
+ if proto.shape[-1] == self.n_extra:
722
+ proto = proto.permute(2, 0, 1)
723
+ elif proto.shape[0] != self.n_extra:
724
+ raise ValueError(
725
+ f"Unsupported prototype tensor shape {tuple(proto.shape)}."
726
+ )
727
+ if len(pred) == 0:
728
+ masks.append(
729
+ torch.zeros(
730
+ (0, self.imh, self.imw), dtype=torch.float32, device=self.device
731
+ )
732
+ )
733
+ continue
734
+ masks.append(
735
+ process_mask_upsample(
736
+ proto, pred[:, 6:], pred[:, :4], [self.imh, self.imw]
737
+ )
738
+ )
739
+ return [[xi, mask] for xi, mask in zip(x, masks)]
740
+
741
+
742
+ # Name retained from the first standalone draft.
743
+ YOLOPostBase = YOLODetectionPostBase