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,725 @@
1
+ """
2
+ Results processing and plotting.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Sequence
8
+ from pathlib import Path
9
+ from typing import cast
10
+
11
+ import cv2
12
+ import numpy as np
13
+ import torch
14
+ from PIL import Image
15
+
16
+ from .._tasks import normalize_vision_task
17
+ from .datasets import (
18
+ get_ade20k_palette,
19
+ get_cityscapes_palette,
20
+ get_coco_det_palette,
21
+ get_coco_keypoint_palette,
22
+ get_coco_label,
23
+ get_coco_limb_palette,
24
+ get_coco_pose_skeleton,
25
+ get_dotav1_label,
26
+ get_dotav1_palette,
27
+ get_imagenet_label,
28
+ )
29
+ from .letterbox import LetterBoxGeometry
30
+ from mblt_vision.utils.postprocess.common import (
31
+ crop_mask,
32
+ scale_boxes,
33
+ scale_coords,
34
+ scale_masks,
35
+ scale_rboxes,
36
+ xywhr2xyxyxyxy,
37
+ )
38
+ from .preprocess._validation import normalize_uint8_rgb_array
39
+ from .types import ListTensorLike, NestedListTensorLike, TensorLike
40
+
41
+ LW = 2 # line width
42
+ RADIUS = 5 # circle radius
43
+ ALPHA = 0.3 # alpha for overlay
44
+ DENSE_OVERLAY_ALPHA = 0.6
45
+
46
+
47
+ class Results:
48
+ """Handle, process, and plot model inference results."""
49
+
50
+ def __init__(
51
+ self,
52
+ pre_cfg: dict,
53
+ post_cfg: dict,
54
+ output: TensorLike | ListTensorLike | NestedListTensorLike,
55
+ **kwargs,
56
+ ) -> None:
57
+ """
58
+ Initializes the Results object.
59
+ Args:
60
+ pre_cfg (dict): Preprocessing configuration.
61
+ post_cfg (dict): Postprocessing configuration.
62
+ output (TensorLike | ListTensorLike | NestedListTensorLike): Raw model output.
63
+ **kwargs: Additional arguments.
64
+ """
65
+ self.pre_cfg = pre_cfg
66
+ self.post_cfg = post_cfg
67
+ self.task = normalize_vision_task(post_cfg["task"])
68
+ self.conf_thres = kwargs.get("conf_thres", 0.25)
69
+ self.acc: torch.Tensor | np.ndarray | None = None
70
+ self.box_cls: torch.Tensor | np.ndarray | None = None
71
+ self.mask: torch.Tensor | np.ndarray | None = None
72
+ self.depth: torch.Tensor | np.ndarray | list[TensorLike] | None = None
73
+ self.semantic_mask: torch.Tensor | np.ndarray | list[TensorLike] | None = None
74
+ self.output: TensorLike | ListTensorLike | NestedListTensorLike | None = None
75
+ self.labels: torch.Tensor | None = None
76
+ self.scores: torch.Tensor | None = None
77
+ self.boxes: torch.Tensor | None = None
78
+ self.rboxes: torch.Tensor | None = None
79
+ self.kpts: torch.Tensor | None = None
80
+ self.set_output(output)
81
+
82
+ def _read_image(
83
+ self, source_path: str | Path | np.ndarray | Image.Image
84
+ ) -> np.ndarray:
85
+ """
86
+ Internal method to read an image from various input types and convert to BGR format.
87
+ Args:
88
+ source_path (str | np.ndarray | Image.Image): Path to image or image object.
89
+ Returns:
90
+ np.ndarray: Image in BGR format (cv2 style).
91
+ """
92
+ source_img = None
93
+ if isinstance(source_path, Image.Image): # PIL image open
94
+ source_img = source_path.convert("RGB")
95
+ source_img = np.array(source_img)
96
+ source_img = cv2.cvtColor(source_img, cv2.COLOR_RGB2BGR)
97
+ elif isinstance(source_path, np.ndarray):
98
+ source_img = np.array(source_path)
99
+ if source_img.ndim != 3 or source_img.shape[2] != 3:
100
+ raise ValueError(
101
+ f"Image arrays must have HWC shape with three channels, got {source_img.shape}."
102
+ )
103
+ source_img = normalize_uint8_rgb_array(source_img, operation="Results.plot")
104
+ source_img = cv2.cvtColor(source_img, cv2.COLOR_RGB2BGR)
105
+ elif isinstance(source_path, (str, Path)):
106
+ image_path = Path(source_path)
107
+ if not image_path.is_file():
108
+ raise FileNotFoundError(f"Image file not found: {image_path}")
109
+ source_img = cv2.imread(str(image_path), cv2.IMREAD_COLOR)
110
+ else:
111
+ raise TypeError(
112
+ f"Unsupported image source type: {type(source_path).__name__}."
113
+ )
114
+ if source_img is None:
115
+ raise ValueError(f"Failed to decode image from {source_path!r}.")
116
+ return source_img
117
+
118
+ @staticmethod
119
+ def _save_image(save_path: str | Path, image: np.ndarray) -> None:
120
+ """Save an image and report encoder or filesystem failures."""
121
+
122
+ path = Path(save_path)
123
+ if path.parent != Path("."):
124
+ path.parent.mkdir(parents=True, exist_ok=True)
125
+ if not cv2.imwrite(str(path), image):
126
+ raise OSError(f"Failed to write result image: {path}")
127
+
128
+ def set_output(
129
+ self, output: TensorLike | ListTensorLike | NestedListTensorLike
130
+ ) -> None:
131
+ """
132
+ Sets variables from the raw model output based on the task.
133
+ Args:
134
+ output (TensorLike | ListTensorLike | NestedListTensorLike): Raw model output.
135
+ Raises:
136
+ NotImplementedError: If the task is not supported.
137
+ """
138
+ self.acc = None
139
+ self.box_cls = None
140
+ self.mask = None
141
+ self.depth = None
142
+ self.semantic_mask = None
143
+ if self.task == "image_classification":
144
+ if not isinstance(output, (np.ndarray, torch.Tensor)):
145
+ raise TypeError(
146
+ f"Expected tensor output for task {self.task}, got {type(output).__name__}."
147
+ )
148
+ self.acc = cast(TensorLike, output)
149
+ elif self.task in {
150
+ "object_detection",
151
+ "face_detection",
152
+ "pose_estimation",
153
+ "obb",
154
+ }:
155
+ if not isinstance(output, Sequence):
156
+ raise TypeError(
157
+ f"Expected list output for task {self.task}, got {type(output).__name__}."
158
+ )
159
+ if len(output) == 0:
160
+ raise ValueError(
161
+ f"Expected a non-empty output list for task {self.task}."
162
+ )
163
+ if not isinstance(output[0], (np.ndarray, torch.Tensor)):
164
+ raise TypeError(
165
+ f"Expected a tensor as the first output for task {self.task}, got {type(output[0]).__name__}."
166
+ )
167
+ self.box_cls = cast(TensorLike, output[0])
168
+ elif self.task == "instance_segmentation":
169
+ if not isinstance(output, Sequence):
170
+ raise TypeError(
171
+ f"Expected nested list output for task {self.task}, got {type(output).__name__}."
172
+ )
173
+ if len(output) == 0:
174
+ raise ValueError(
175
+ f"Expected a non-empty output list for task {self.task}."
176
+ )
177
+ if not isinstance(output[0], Sequence):
178
+ raise TypeError(
179
+ f"Expected a nested output sequence for task {self.task}, got {type(output[0]).__name__}."
180
+ )
181
+ if len(output[0]) < 2:
182
+ raise ValueError(
183
+ "Instance segmentation output must contain detections and masks."
184
+ )
185
+ seg_output = cast(ListTensorLike, output[0])
186
+ if not all(
187
+ isinstance(item, (np.ndarray, torch.Tensor)) for item in seg_output[:2]
188
+ ):
189
+ raise TypeError(
190
+ "Instance segmentation detections and masks must be tensors."
191
+ )
192
+ self.box_cls = cast(TensorLike, seg_output[0])
193
+ self.mask = cast(TensorLike, seg_output[1])
194
+ elif self.task == "depth_estimation":
195
+ if isinstance(output, Sequence) and not isinstance(
196
+ output, (np.ndarray, torch.Tensor)
197
+ ):
198
+ if len(output) == 0:
199
+ raise ValueError("Expected at least one depth-map tensor.")
200
+ if not all(
201
+ isinstance(item, (np.ndarray, torch.Tensor)) for item in output
202
+ ):
203
+ raise TypeError(
204
+ f"Expected depth-map tensors for task {self.task}, got {type(output).__name__}."
205
+ )
206
+ self.depth = [cast(TensorLike, item) for item in output]
207
+ elif isinstance(output, (np.ndarray, torch.Tensor)):
208
+ self.depth = output
209
+ else:
210
+ raise TypeError(
211
+ f"Expected tensor depth output for task {self.task}, got {type(output)}."
212
+ )
213
+ elif self.task == "semantic_segmentation":
214
+ if isinstance(output, Sequence) and not isinstance(
215
+ output, (np.ndarray, torch.Tensor)
216
+ ):
217
+ if len(output) == 0:
218
+ raise ValueError("Expected at least one semantic-map tensor.")
219
+ if not all(
220
+ isinstance(item, (np.ndarray, torch.Tensor)) for item in output
221
+ ):
222
+ raise TypeError(
223
+ f"Expected semantic-map tensors for task {self.task}, got {type(output).__name__}."
224
+ )
225
+ self.semantic_mask = [cast(TensorLike, item) for item in output]
226
+ elif isinstance(output, (np.ndarray, torch.Tensor)):
227
+ self.semantic_mask = output
228
+ else:
229
+ raise TypeError(
230
+ f"Expected tensor semantic output for task {self.task}, got {type(output)}."
231
+ )
232
+ else:
233
+ raise NotImplementedError(
234
+ f"Task {self.task} is not supported for plotting results."
235
+ )
236
+ self.output = output # store raw output
237
+
238
+ def plot(
239
+ self,
240
+ source_path: str | Path | np.ndarray | Image.Image,
241
+ save_path: str | Path | None = None,
242
+ **kwargs,
243
+ ) -> np.ndarray | None:
244
+ """Plot inference results on the source image.
245
+
246
+ Args:
247
+ source_path: Image path or object to plot on.
248
+ save_path: Optional output image path.
249
+ **kwargs: Additional task-specific plotting options (e.g., topk for classification).
250
+
251
+ Returns:
252
+ Image with results visualized in BGR format, or ``None`` for classification without an output path.
253
+
254
+ Raises:
255
+ NotImplementedError: If the task is not supported for plotting.
256
+ """
257
+ if self.task == "image_classification":
258
+ return self._plot_image_classification(source_path, save_path, **kwargs)
259
+ elif self.task in {"object_detection", "face_detection"}:
260
+ return self._plot_object_detection(source_path, save_path, **kwargs)
261
+ elif self.task == "instance_segmentation":
262
+ return self._plot_instance_segmentation(source_path, save_path, **kwargs)
263
+ elif self.task == "depth_estimation":
264
+ return self._plot_depth_estimation(source_path, save_path, **kwargs)
265
+ elif self.task == "semantic_segmentation":
266
+ return self._plot_semantic_segmentation(source_path, save_path, **kwargs)
267
+ elif self.task == "pose_estimation":
268
+ return self._plot_pose_estimation(source_path, save_path, **kwargs)
269
+ elif self.task == "obb":
270
+ return self._plot_obb(source_path, save_path, **kwargs)
271
+ else:
272
+ raise NotImplementedError(
273
+ f"Task {self.task} is not supported for plotting results."
274
+ )
275
+
276
+ def _plot_depth_estimation(
277
+ self,
278
+ source_path: str | Path | np.ndarray | Image.Image,
279
+ save_path: str | Path | None = None,
280
+ **kwargs,
281
+ ) -> np.ndarray:
282
+ """Colorize the first depth map with near objects in red and blend it over the original image."""
283
+
284
+ del kwargs
285
+ if self.depth is None:
286
+ raise ValueError("No depth output found.")
287
+ depth_value = self.depth[0] if isinstance(self.depth, list) else self.depth
288
+ depth = (
289
+ depth_value.detach().cpu().numpy()
290
+ if isinstance(depth_value, torch.Tensor)
291
+ else depth_value
292
+ )
293
+ if depth.ndim == 3:
294
+ depth = depth[0]
295
+ if depth.ndim != 2:
296
+ raise ValueError(
297
+ f"Expected a 2D depth map or [B, H, W], got {depth.shape}."
298
+ )
299
+ image = self._read_image(source_path)
300
+ image_shape = (int(image.shape[0]), int(image.shape[1]))
301
+ if tuple(depth.shape) != image_shape:
302
+ depth = self._restore_depth_map(depth, image_shape)
303
+ valid = np.isfinite(depth) & (depth > 0)
304
+ if not valid.any():
305
+ raise ValueError("Depth output contains no positive finite values.")
306
+ disparity = np.zeros(depth.shape, dtype=np.float32)
307
+ disparity[valid] = 1.0 / depth[valid]
308
+ lower, upper = np.percentile(disparity[valid], (2, 98))
309
+ if upper <= lower:
310
+ upper = lower + 1e-6
311
+ normalized = np.zeros(depth.shape, dtype=np.uint8)
312
+ normalized[valid] = np.clip(
313
+ (disparity[valid] - lower) * 255 / (upper - lower), 0, 255
314
+ ).astype(np.uint8)
315
+ overlay = cv2.applyColorMap(normalized, cv2.COLORMAP_JET)
316
+ overlay[~valid] = 0
317
+ result = cv2.addWeighted(
318
+ image, 1.0 - DENSE_OVERLAY_ALPHA, overlay, DENSE_OVERLAY_ALPHA, 0
319
+ )
320
+ if save_path is not None:
321
+ self._save_image(save_path, result)
322
+ return result
323
+
324
+ def _plot_semantic_segmentation(
325
+ self,
326
+ source_path: str | Path | np.ndarray | Image.Image,
327
+ save_path: str | Path | None = None,
328
+ **kwargs,
329
+ ) -> np.ndarray:
330
+ """Colorize a semantic class map and blend it over the original image."""
331
+
332
+ del kwargs
333
+ if self.semantic_mask is None:
334
+ raise ValueError("No semantic output found.")
335
+ semantic_value = (
336
+ self.semantic_mask[0]
337
+ if isinstance(self.semantic_mask, list)
338
+ else self.semantic_mask
339
+ )
340
+ class_map = (
341
+ semantic_value.detach().cpu().numpy()
342
+ if isinstance(semantic_value, torch.Tensor)
343
+ else semantic_value
344
+ )
345
+ if class_map.ndim == 3:
346
+ class_map = class_map[0]
347
+ if class_map.ndim != 2:
348
+ raise ValueError(
349
+ f"Expected a 2D semantic map or [B, H, W], got {class_map.shape}."
350
+ )
351
+ image = self._read_image(source_path)
352
+ image_shape = (int(image.shape[0]), int(image.shape[1]))
353
+ if tuple(class_map.shape) != image_shape:
354
+ class_map = self._restore_semantic_map(class_map, image_shape)
355
+ dataset_value = self.post_cfg.get("dataset")
356
+ dataset = (
357
+ dataset_value.lower() if isinstance(dataset_value, str) else dataset_value
358
+ )
359
+ if dataset == "ade20k":
360
+ default_nc = 150
361
+ palette_getter = get_ade20k_palette
362
+ elif dataset == "cityscapes":
363
+ default_nc = 19
364
+ palette_getter = get_cityscapes_palette
365
+ else:
366
+ raise ValueError(
367
+ f"Unsupported semantic segmentation dataset palette: {dataset!r}."
368
+ )
369
+ nc = int(self.post_cfg.get("nc", default_nc))
370
+ valid = class_map != 255
371
+ if valid.any() and (
372
+ int(class_map[valid].min()) < 0 or int(class_map[valid].max()) >= nc
373
+ ):
374
+ raise ValueError(
375
+ f"Semantic class-map values must be in [0, {nc - 1}] or 255."
376
+ )
377
+ palette = np.array(
378
+ [palette_getter(index) for index in range(nc)], dtype=np.uint8
379
+ )
380
+ overlay = np.zeros_like(image)
381
+ overlay[valid] = palette[class_map[valid].astype(np.int64)]
382
+ blended = cv2.addWeighted(
383
+ image, 1.0 - DENSE_OVERLAY_ALPHA, overlay, DENSE_OVERLAY_ALPHA, 0
384
+ )
385
+ result = image.copy()
386
+ result[valid] = blended[valid]
387
+ if save_path is not None:
388
+ self._save_image(save_path, result)
389
+ return result
390
+
391
+ def _restore_semantic_map(
392
+ self, class_map: np.ndarray, image_shape: tuple[int, int]
393
+ ) -> np.ndarray:
394
+ """Undo the configured letterbox transform using nearest-neighbor interpolation."""
395
+
396
+ return self._restore_dense_map(
397
+ class_map, image_shape, cv2.INTER_NEAREST, "Semantic"
398
+ )
399
+
400
+ def _restore_depth_map(
401
+ self, depth: np.ndarray, image_shape: tuple[int, int]
402
+ ) -> np.ndarray:
403
+ """Undo the configured letterbox transform and resize a depth map to an image."""
404
+
405
+ return self._restore_dense_map(depth, image_shape, cv2.INTER_LINEAR, "Depth")
406
+
407
+ def _restore_dense_map(
408
+ self,
409
+ output: np.ndarray,
410
+ image_shape: tuple[int, int],
411
+ interpolation: int,
412
+ task_name: str,
413
+ ) -> np.ndarray:
414
+ """Undo configured letterboxing for a dense two-dimensional output."""
415
+
416
+ letterbox_cfg = self.pre_cfg.get("LetterBox", {})
417
+ input_shape = letterbox_cfg.get("img_size")
418
+ if not isinstance(input_shape, list) or len(input_shape) != 2:
419
+ return cv2.resize(
420
+ output, (image_shape[1], image_shape[0]), interpolation=interpolation
421
+ )
422
+ geometry = LetterBoxGeometry.from_shapes(
423
+ (int(input_shape[0]), int(input_shape[1])), image_shape
424
+ )
425
+ output_shape = (int(output.shape[0]), int(output.shape[1]))
426
+ top, bottom, left, right = geometry.crop_bounds(output_shape)
427
+ cropped = output[top:bottom, left:right]
428
+ if cropped.size == 0:
429
+ raise ValueError(
430
+ f"{task_name} letterbox restoration produced an empty crop."
431
+ )
432
+ return cv2.resize(
433
+ cropped, (image_shape[1], image_shape[0]), interpolation=interpolation
434
+ )
435
+
436
+ def _plot_image_classification(
437
+ self,
438
+ source_path: str | Path | np.ndarray | Image.Image | None = None,
439
+ save_path: str | Path | None = None,
440
+ topk: int = 5,
441
+ **kwargs,
442
+ ) -> np.ndarray | None:
443
+ if self.acc is None:
444
+ raise ValueError("No accuracy output found.")
445
+ if isinstance(topk, bool) or not isinstance(topk, int):
446
+ raise TypeError(f"topk must be an integer, got {type(topk).__name__}.")
447
+ if topk <= 0:
448
+ raise ValueError(f"topk must be positive, got {topk}.")
449
+ if isinstance(self.acc, np.ndarray):
450
+ self.acc = torch.tensor(self.acc)
451
+ scores = self.acc.squeeze()
452
+ if scores.ndim != 1:
453
+ raise ValueError(
454
+ f"Classification plotting expects one class-score vector, got shape {tuple(self.acc.shape)}."
455
+ )
456
+ topk = min(topk, int(scores.numel()))
457
+ topk_probs, topk_indices = torch.topk(scores, topk)
458
+ topk_probs = np.atleast_1d(topk_probs.squeeze().detach().cpu().numpy())
459
+ topk_indices = np.atleast_1d(topk_indices.squeeze().detach().cpu().numpy())
460
+ # load labels
461
+ labels = [get_imagenet_label(i) for i in topk_indices]
462
+ comments = []
463
+ for i in range(topk):
464
+ comments.append(f"{labels[i]}: {topk_probs[i] * 100:.2f}%")
465
+ print(f"Label: {labels[i]}, Probability: {topk_probs[i] * 100:.2f}%")
466
+ if source_path is not None and save_path is not None:
467
+ comments_str = "\n".join(comments)
468
+ img = self._read_image(source_path)
469
+ avg_color = img.mean(axis=(0, 1))
470
+ txt_color = (
471
+ int(255 - avg_color[0]),
472
+ int(255 - avg_color[1]),
473
+ int(255 - avg_color[2]),
474
+ )
475
+ for i, line in enumerate(comments_str.splitlines()):
476
+ (_, h), _ = cv2.getTextSize(
477
+ text=line,
478
+ fontFace=cv2.FONT_HERSHEY_SIMPLEX,
479
+ fontScale=0.5,
480
+ thickness=1,
481
+ )
482
+ img = cv2.putText(
483
+ img,
484
+ line,
485
+ (15, 15 + int(1.5 * i * h)), # line spacing
486
+ fontFace=cv2.FONT_HERSHEY_SIMPLEX,
487
+ fontScale=0.5,
488
+ color=txt_color,
489
+ thickness=1,
490
+ lineType=cv2.LINE_AA,
491
+ )
492
+ self._save_image(save_path, img)
493
+ return img
494
+ else:
495
+ return None
496
+
497
+ def _plot_object_detection(
498
+ self,
499
+ source_path: str | Path | np.ndarray | Image.Image,
500
+ save_path: str | Path | None = None,
501
+ **kwargs,
502
+ ) -> np.ndarray:
503
+ box_cls = self._box_cls_tensor()
504
+ expected_columns = 6 + self.post_cfg.get("n_extra", 0)
505
+ if box_cls.ndim != 2 or box_cls.shape[1] != expected_columns:
506
+ raise ValueError(
507
+ f"Object detection output must have shape [N, {expected_columns}], got {tuple(box_cls.shape)}."
508
+ )
509
+ img = self._read_image(source_path)
510
+ img1_shape = cast(tuple[int, int], self.pre_cfg["LetterBox"]["img_size"])
511
+ img0_shape: tuple[int, int] = (img.shape[0], img.shape[1])
512
+ self.labels = box_cls[:, 5].to(torch.int64)
513
+ self.scores = box_cls[:, 4]
514
+ self.boxes = scale_boxes(
515
+ img1_shape,
516
+ box_cls[:, :4].clone(),
517
+ img0_shape,
518
+ )
519
+ boxes = self.boxes
520
+ scores = self.scores
521
+ labels = self.labels
522
+ contours: dict[int, list[np.ndarray]] = {}
523
+ for box, score, label in zip(boxes, scores, labels):
524
+ label_idx = int(label.item())
525
+ palette = self._get_detection_palette(label_idx)
526
+ img = cv2.putText(
527
+ img,
528
+ f"{self._get_detection_label(label_idx)} {int(100 * score)}%",
529
+ (int(box[0]), int(box[1]) - 10),
530
+ cv2.FONT_HERSHEY_SIMPLEX,
531
+ 0.5,
532
+ palette,
533
+ 1,
534
+ cv2.LINE_AA,
535
+ )
536
+ contours.setdefault(label_idx, []).append(
537
+ np.array(
538
+ [
539
+ [int(box[0]), int(box[1])],
540
+ [int(box[2]), int(box[1])],
541
+ [int(box[2]), int(box[3])],
542
+ [int(box[0]), int(box[3])],
543
+ ]
544
+ )
545
+ )
546
+ for label, contour in contours.items():
547
+ if len(contour) > 0:
548
+ cv2.drawContours(
549
+ img,
550
+ contour,
551
+ -1,
552
+ self._get_detection_palette(label),
553
+ LW,
554
+ )
555
+ if save_path is not None:
556
+ self._save_image(save_path, img)
557
+ return img
558
+
559
+ def _plot_instance_segmentation(
560
+ self,
561
+ source_path: str | Path | np.ndarray | Image.Image,
562
+ save_path: str | Path | None = None,
563
+ **kwargs,
564
+ ) -> np.ndarray:
565
+ img = self._plot_object_detection(source_path, None, **kwargs)
566
+ if self.mask is None:
567
+ raise RuntimeError("Instance segmentation output has no mask tensor.")
568
+ if self.boxes is None:
569
+ raise RuntimeError("Instance segmentation boxes were not initialized.")
570
+ if self.labels is None:
571
+ raise RuntimeError("Instance segmentation labels were not initialized.")
572
+ mask = self._mask_tensor()
573
+ img0_shape: tuple[int, int] = (img.shape[0], img.shape[1])
574
+ masks = (
575
+ crop_mask(scale_masks(mask, img0_shape), self.boxes)
576
+ .gt_(0.0)
577
+ .permute(1, 2, 0)
578
+ .to(torch.float32)
579
+ .cpu()
580
+ .numpy()
581
+ )
582
+ overlay = np.zeros((masks.shape[0], masks.shape[1], 3))
583
+ for i, label in enumerate(self.labels):
584
+ label_idx = int(label.item())
585
+ overlay = np.maximum(
586
+ overlay,
587
+ masks[:, :, i][:, :, np.newaxis]
588
+ * np.array(get_coco_det_palette(label_idx)).reshape(1, 1, 3),
589
+ )
590
+ total_mask = overlay.max(axis=2, keepdims=True)
591
+ inv_mask = 1 - ALPHA * total_mask / 255
592
+ img = (img * inv_mask + overlay * ALPHA).astype(np.uint8)
593
+ if save_path is not None:
594
+ self._save_image(save_path, img)
595
+ return img
596
+
597
+ def _plot_pose_estimation(
598
+ self,
599
+ source_path: str | Path | np.ndarray | Image.Image,
600
+ save_path: str | Path | None = None,
601
+ **kwargs,
602
+ ) -> np.ndarray:
603
+ img = self._plot_object_detection(source_path, None, **kwargs)
604
+ box_cls = self._box_cls_tensor()
605
+ img0_shape: tuple[int, int] = (img.shape[0], img.shape[1])
606
+ self.kpts = scale_coords(
607
+ self.pre_cfg["LetterBox"]["img_size"],
608
+ box_cls[:, 6:].reshape(-1, 17, 3).clone(),
609
+ img0_shape,
610
+ )
611
+ kpts = self.kpts
612
+ if kpts is None:
613
+ raise ValueError("No keypoints output found.")
614
+ for kpt in kpts:
615
+ for i, (x, y, v) in enumerate(kpt):
616
+ color_k = get_coco_keypoint_palette(i)
617
+ if float(v) < self.conf_thres:
618
+ continue
619
+ cv2.circle(
620
+ img,
621
+ (int(x), int(y)),
622
+ RADIUS,
623
+ color_k,
624
+ -1,
625
+ lineType=cv2.LINE_AA,
626
+ )
627
+ for j, sk in enumerate(get_coco_pose_skeleton()):
628
+ conf1 = float(kpt[sk[0] - 1, 2])
629
+ conf2 = float(kpt[sk[1] - 1, 2])
630
+ if conf1 < self.conf_thres or conf2 < self.conf_thres:
631
+ continue
632
+ pos1 = (int(kpt[sk[0] - 1, 0]), int(kpt[sk[0] - 1, 1]))
633
+ pos2 = (int(kpt[sk[1] - 1, 0]), int(kpt[sk[1] - 1, 1]))
634
+ cv2.line(
635
+ img,
636
+ pos1,
637
+ pos2,
638
+ get_coco_limb_palette(j),
639
+ thickness=int(np.ceil(LW / 2)),
640
+ lineType=cv2.LINE_AA,
641
+ )
642
+ if save_path is not None:
643
+ self._save_image(save_path, img)
644
+ return img
645
+
646
+ def _plot_obb(
647
+ self,
648
+ source_path: str | Path | np.ndarray | Image.Image,
649
+ save_path: str | Path | None = None,
650
+ **kwargs,
651
+ ) -> np.ndarray:
652
+ """Plot OBB detections on an image.
653
+
654
+ Args:
655
+ source_path: Path or image object.
656
+ save_path: Optional path to save the plotted image.
657
+ **kwargs: Additional plotting arguments.
658
+
659
+ Returns:
660
+ The plotted BGR image.
661
+ """
662
+ del kwargs
663
+ box_cls = self._box_cls_tensor()
664
+ if box_cls.ndim != 2 or box_cls.shape[1] != 7:
665
+ raise ValueError(
666
+ f"OBB output must have shape [N, 7], got {tuple(box_cls.shape)}."
667
+ )
668
+ img = self._read_image(source_path)
669
+ img0_shape: tuple[int, int] = (img.shape[0], img.shape[1])
670
+ self.labels = box_cls[:, 5].to(torch.int64)
671
+ self.scores = box_cls[:, 4]
672
+ self.rboxes = scale_rboxes(
673
+ self.pre_cfg["LetterBox"]["img_size"],
674
+ torch.cat([box_cls[:, :4], box_cls[:, 6:7]], dim=-1),
675
+ img0_shape,
676
+ )
677
+ polygons = xywhr2xyxyxyxy(self.rboxes).to(torch.int32).cpu().numpy()
678
+ for polygon, score, label in zip(polygons, self.scores, self.labels):
679
+ label_idx = int(label.item())
680
+ color = get_dotav1_palette(label_idx)
681
+ text_anchor = polygon.min(axis=0)
682
+ img = cv2.putText(
683
+ img,
684
+ f"{get_dotav1_label(label_idx)} {int(100 * score)}%",
685
+ (int(text_anchor[0]), int(text_anchor[1]) - 10),
686
+ cv2.FONT_HERSHEY_SIMPLEX,
687
+ 0.5,
688
+ color,
689
+ 1,
690
+ cv2.LINE_AA,
691
+ )
692
+ cv2.drawContours(img, [polygon.reshape(-1, 1, 2)], -1, color, LW)
693
+ if save_path is not None:
694
+ self._save_image(save_path, img)
695
+ return img
696
+
697
+ def _box_cls_tensor(self) -> torch.Tensor:
698
+ """Returns detection output as a torch tensor."""
699
+ if self.box_cls is None:
700
+ raise ValueError("No box_cls output found.")
701
+ if isinstance(self.box_cls, np.ndarray):
702
+ return torch.from_numpy(self.box_cls)
703
+ return self.box_cls
704
+
705
+ def _get_detection_label(self, label_idx: int) -> str:
706
+ """Return the display label for detection-style tasks."""
707
+ if self.task == "face_detection":
708
+ if label_idx != 0:
709
+ raise ValueError(f"Unexpected face_detection class index: {label_idx}.")
710
+ return "face"
711
+ return get_coco_label(label_idx)
712
+
713
+ def _get_detection_palette(self, label_idx: int) -> tuple[int, int, int]:
714
+ """Return the display color for detection-style tasks."""
715
+ if self.task == "face_detection":
716
+ return get_coco_det_palette(0)
717
+ return get_coco_det_palette(label_idx)
718
+
719
+ def _mask_tensor(self) -> torch.Tensor:
720
+ """Returns segmentation mask output as a torch tensor."""
721
+ if self.mask is None:
722
+ raise ValueError("No mask output found.")
723
+ if isinstance(self.mask, np.ndarray):
724
+ return torch.from_numpy(self.mask)
725
+ return self.mask