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,176 @@
1
+ """
2
+ YOLO NMS-free postprocessing.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any, cast
8
+
9
+ import torch
10
+
11
+ from .common import dist2bbox, dual_topk
12
+ from .yolo_anchorless_post import YOLOAnchorlessDetectionPost, _AnchorlessNMSInput
13
+
14
+
15
+ class YOLONMSFreeDetectionPost(YOLOAnchorlessDetectionPost):
16
+ """Postprocessing for YOLO NMS-free models."""
17
+
18
+ max_det = 300
19
+
20
+ def non_e2e(self, x: list[torch.Tensor]) -> torch.Tensor:
21
+ """Return the export-style output tensor for NMS-free YOLO models."""
22
+ if len(x) == 2:
23
+ converted = cast(torch.Tensor, self.conversion(x))
24
+ return self._stack_topk_outputs(self.filter_conversion(converted))
25
+
26
+ rearranged = cast(torch.Tensor, self.rearrange(x))
27
+ return self.decode_batch(rearranged)
28
+
29
+ def _stack_topk_outputs(self, outputs: list[torch.Tensor]) -> torch.Tensor:
30
+ """Pad or trim per-image detections to a fixed batch tensor."""
31
+ padded_outputs = []
32
+ for output in outputs:
33
+ output = output[: self.max_det]
34
+ if output.shape[0] < self.max_det:
35
+ pad = torch.zeros(
36
+ (self.max_det - output.shape[0], 6),
37
+ dtype=output.dtype,
38
+ device=output.device,
39
+ )
40
+ output = torch.cat([output, pad], dim=0)
41
+ padded_outputs.append(output)
42
+ return torch.stack(padded_outputs, dim=0)
43
+
44
+ def decode_batch(self, x: torch.Tensor) -> torch.Tensor:
45
+ """Decode every anchor, then apply batched top-k selection for export-style output."""
46
+ box, scores = torch.split(x, [self.reg_max * 4, self.nc], dim=1)
47
+ anchors = self.anchors_as_tensor().unsqueeze(0)
48
+ stride = self.stride_as_tensor().unsqueeze(0)
49
+ dbox = dist2bbox(self.dfl(box), anchors, xywh=False, dim=1) * stride
50
+ decoded = torch.cat([dbox, scores], dim=1).transpose(1, 2)
51
+ return self._stack_topk_outputs(
52
+ [
53
+ dual_topk(
54
+ image,
55
+ self.nc,
56
+ self.n_extra,
57
+ max_det=self.max_det,
58
+ conf_thres=self.conf_thres,
59
+ score_is_logits=True,
60
+ )
61
+ for image in decoded
62
+ ]
63
+ )
64
+
65
+ def _pre_process(self, x: list[torch.Tensor]) -> tuple[Any, torch.Tensor | None]:
66
+ """Preprocesses inputs for NMS-free models.
67
+
68
+ Args:
69
+ x (list[torch.Tensor]): Raw model outputs.
70
+
71
+ Returns:
72
+ tuple: (processed_detections, None).
73
+ """
74
+ if len(x) == 2:
75
+ converted = cast(torch.Tensor, self.conversion(x))
76
+ return self.filter_conversion(converted), None
77
+ rearranged = cast(torch.Tensor, self.rearrange(x))
78
+ return self.decode(rearranged), None
79
+
80
+ def conversion(
81
+ self, x: list[torch.Tensor]
82
+ ) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor]:
83
+ """Convert input tensors.
84
+ Args:
85
+ x (list[torch.Tensor]): Input tensors.
86
+ Returns:
87
+ torch.Tensor: Converted tensor.
88
+ """
89
+ # sort by element number
90
+ x = sorted(x, key=lambda x: x.size(), reverse=self.nc < 4)
91
+ return torch.cat(x, dim=-1).squeeze(1) # [b, 8400, 84]
92
+
93
+ def filter_conversion(self, x: torch.Tensor) -> list[torch.Tensor]:
94
+ """Filters out low-confidence detections from a single output tensor.
95
+
96
+ Args:
97
+ x (torch.Tensor): Model output tensor.
98
+
99
+ Returns:
100
+ list[torch.Tensor]: Decoded and filtered outputs for each image.
101
+ """
102
+ x_list = torch.split(x, 1, dim=0) # [(1, 8400, 84), (1, 8400, 84), ...]
103
+
104
+ return [
105
+ dual_topk(xi.squeeze(0), self.nc, self.n_extra, conf_thres=self.conf_thres)
106
+ for xi in x_list
107
+ ]
108
+
109
+ def process_box_cls(self, box_cls: torch.Tensor) -> torch.Tensor:
110
+ """Processes detection results for a single image.
111
+
112
+ Args:
113
+ box_cls: Raw detections for one image.
114
+
115
+ Returns:
116
+ Decoded and top-k filtered detections.
117
+ """
118
+ ic = torch.amax(box_cls[-self.nc :, :], dim=0) > self.inv_conf_thres
119
+ box_cls = box_cls[:, ic] # (144, *)
120
+ if box_cls.numel() == 0:
121
+ return box_cls.new_zeros((0, 6))
122
+ anchors = self.anchors_as_tensor()
123
+ stride = self.stride_as_tensor()
124
+ box, scores = torch.split(
125
+ box_cls[None], [self.reg_max * 4, self.nc], dim=1
126
+ ) # (1, 64, *), (1, 80, *)
127
+ dbox = (
128
+ dist2bbox(
129
+ self.dfl(box),
130
+ anchors[:, ic],
131
+ xywh=False,
132
+ dim=1,
133
+ )
134
+ * stride[:, ic]
135
+ )
136
+ pre_topk = (
137
+ torch.cat([dbox, scores], dim=1).squeeze(0).transpose(0, 1)
138
+ ) # (*, 84)
139
+ return dual_topk(
140
+ pre_topk,
141
+ self.nc,
142
+ self.n_extra,
143
+ conf_thres=self.conf_thres,
144
+ score_is_logits=True,
145
+ )
146
+
147
+ def nms(
148
+ self,
149
+ x: _AnchorlessNMSInput | torch.Tensor | list[torch.Tensor],
150
+ max_det: int = 300,
151
+ max_nms: int = 30000,
152
+ max_wh: int = 7680,
153
+ multi_label: bool = False,
154
+ ) -> list[torch.Tensor]:
155
+ """Perform Non-Maximum Suppression (no-op for NMS-free models).
156
+
157
+ Args:
158
+ x: Decoded detections, optionally with source-layout provenance.
159
+ max_det (int, optional): Maximum number of detections to keep. Defaults to 300.
160
+ max_nms (int, optional): Maximum candidates for NMS. Defaults to 30000.
161
+ max_wh (int, optional): Maximum box width/height. Defaults to 7680.
162
+ multi_label: Ignored because NMS-free outputs already select one
163
+ class per candidate.
164
+
165
+ Returns:
166
+ list[torch.Tensor]: Per-image detections with padded zero rows removed.
167
+ """
168
+ del max_det, max_nms, max_wh, multi_label
169
+ if isinstance(x, _AnchorlessNMSInput):
170
+ x = x.detections
171
+ if isinstance(x, list):
172
+ return x
173
+ return [xi[xi[:, 4] > 0] for xi in x]
174
+
175
+
176
+ YOLONMSFreePost = YOLONMSFreeDetectionPost
@@ -0,0 +1,27 @@
1
+ """
2
+ Preprocessing utilities for vision models.
3
+ """
4
+
5
+ from .base import PreBase, PreOps
6
+ from .build_pre import build_preprocess
7
+ from .center_crop import CenterCrop
8
+ from .letterbox import LetterBox, letterbox_semantic_mask
9
+ from .normalize import Normalize
10
+ from .order import SetOrder
11
+ from .reader import Reader
12
+ from .resize import Resize
13
+ from .yolo_pre import YoloPre
14
+
15
+ __all__ = [
16
+ "CenterCrop",
17
+ "LetterBox",
18
+ "Normalize",
19
+ "PreBase",
20
+ "PreOps",
21
+ "Reader",
22
+ "Resize",
23
+ "SetOrder",
24
+ "YoloPre",
25
+ "build_preprocess",
26
+ "letterbox_semantic_mask",
27
+ ]
@@ -0,0 +1,66 @@
1
+ """Validation helpers shared by image preprocessing operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+
7
+ import numpy as np
8
+
9
+
10
+ def normalize_uint8_rgb_array(image: np.ndarray, *, operation: str) -> np.ndarray:
11
+ """Return byte RGB data after validating or scaling a floating-point image.
12
+
13
+ ``[0, 1]`` floating-point input is treated as normalized RGB and scaled to
14
+ ``[0, 255]``. Other floating-point input must already lie in ``[0, 255]``.
15
+ """
16
+
17
+ if image.dtype == np.uint8:
18
+ return image
19
+ if not np.issubdtype(image.dtype, np.floating):
20
+ raise TypeError(
21
+ f"{operation} accepts uint8 arrays or floating-point arrays with RGB "
22
+ f"values in [0, 1] or [0, 255]; got {image.dtype}."
23
+ )
24
+ if not np.isfinite(image).all():
25
+ raise ValueError(
26
+ f"{operation} requires floating-point image arrays to contain only "
27
+ "finite RGB values."
28
+ )
29
+
30
+ min_value = float(image.min())
31
+ max_value = float(image.max())
32
+ if min_value < 0.0 or max_value > 255.0:
33
+ raise ValueError(
34
+ f"{operation} accepts floating-point RGB values only in [0, 1] or "
35
+ f"[0, 255]; got range [{min_value}, {max_value}]."
36
+ )
37
+ if max_value <= 1.0:
38
+ image = image * 255.0
39
+ return np.rint(image).astype(np.uint8)
40
+
41
+
42
+ def normalize_image_size(size: int | Sequence[int], *, name: str = "size") -> list[int]:
43
+ """Normalize a positive scalar or two-dimensional image size to ``[height, width]``."""
44
+
45
+ if isinstance(size, bool):
46
+ raise TypeError(
47
+ f"{name} must be a positive integer or a two-item integer sequence, got bool."
48
+ )
49
+ if isinstance(size, int):
50
+ if size <= 0:
51
+ raise ValueError(f"{name} must be positive, got {size}.")
52
+ return [size, size]
53
+ if isinstance(size, Sequence) and not isinstance(size, (str, bytes)):
54
+ if len(size) != 2:
55
+ raise ValueError(f"{name} must contain exactly two items, got {size!r}.")
56
+ if not all(
57
+ isinstance(value, int) and not isinstance(value, bool) for value in size
58
+ ):
59
+ raise TypeError(f"{name} items must be integers, got {size!r}.")
60
+ normalized = [int(size[0]), int(size[1])]
61
+ if any(value <= 0 for value in normalized):
62
+ raise ValueError(f"{name} items must be positive, got {size!r}.")
63
+ return normalized
64
+ raise TypeError(
65
+ f"{name} must be a positive integer or a two-item integer sequence, got {type(size).__name__}."
66
+ )
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any
5
+
6
+ import torch
7
+
8
+
9
+ def _spatial_shape(value: Any) -> tuple[int, int] | None:
10
+ """Return the height and width of image-like preprocessing input."""
11
+
12
+ shape = getattr(value, "shape", None)
13
+ if shape is None or len(shape) < 2:
14
+ return None
15
+ if len(shape) == 2:
16
+ return int(shape[0]), int(shape[1])
17
+ if len(shape) == 3 and int(shape[-1]) in {1, 3, 4}:
18
+ return int(shape[0]), int(shape[1])
19
+ return int(shape[-2]), int(shape[-1])
20
+
21
+
22
+ class PreOps(ABC):
23
+ """Abstract base class for individual preprocessing operations.
24
+
25
+ Attributes:
26
+ device: The torch device where tensors should be placed.
27
+ """
28
+
29
+ def __init__(self) -> None:
30
+ """Initializes the preprocessing operation."""
31
+ super().__init__()
32
+ self.device = torch.device("cpu")
33
+
34
+ @abstractmethod
35
+ def __call__(
36
+ self,
37
+ x: Any,
38
+ ) -> Any:
39
+ """Executes the preprocess operation.
40
+
41
+ Args:
42
+ x: Input data to be processed.
43
+
44
+ Returns:
45
+ Processed data.
46
+ """
47
+
48
+ def to(
49
+ self,
50
+ device: str | torch.device,
51
+ ) -> None:
52
+ """Move the operation to the specified device.
53
+
54
+ Args:
55
+ device: Device to move the operation to.
56
+ """
57
+ if isinstance(device, str):
58
+ self.device = torch.device(device)
59
+ elif isinstance(device, torch.device):
60
+ self.device = device
61
+ else:
62
+ raise TypeError(f"Got unexpected type for device={type(device)}.")
63
+ for name, value in self.__dict__.items():
64
+ if isinstance(value, torch.Tensor):
65
+ setattr(self, name, value.to(self.device))
66
+
67
+
68
+ class PreBase:
69
+ """Base class for orchestrating a series of preprocessing operations.
70
+
71
+ Attributes:
72
+ Ops: List of ordered PreOps instances to be applied.
73
+ device: The torch device being used.
74
+ """
75
+
76
+ def __init__(
77
+ self,
78
+ Ops: list[PreOps],
79
+ ) -> None:
80
+ """Initializes the PreBase class with a list of operations.
81
+
82
+ Args:
83
+ Ops: List of ordered PreOps instances to be applied.
84
+ """
85
+ self.Ops = Ops
86
+ self._check_ops()
87
+ self.device = torch.device("cpu")
88
+
89
+ def _check_ops(self) -> None:
90
+ """Check if the operations are valid."""
91
+ for op in self.Ops:
92
+ if not isinstance(op, PreOps):
93
+ raise TypeError(f"Got unsupported type={type(op)}.")
94
+
95
+ def __call__(
96
+ self,
97
+ x: Any,
98
+ ) -> Any:
99
+ """Applies the sequence of preprocessing operations to the input.
100
+
101
+ Args:
102
+ x: Initial input data.
103
+
104
+ Returns:
105
+ Fully processed data.
106
+ """
107
+ for op in self.Ops:
108
+ x = op(x)
109
+ return x
110
+
111
+ def with_metadata(
112
+ self,
113
+ x: Any,
114
+ ) -> tuple[Any, dict[str, Any]]:
115
+ """Apply preprocessing and return metadata produced by preprocessing operations.
116
+
117
+ Args:
118
+ x: Initial input data.
119
+
120
+ Returns:
121
+ A tuple of the processed data and collected metadata.
122
+ """
123
+ metadata: dict[str, Any] = {}
124
+ img0_shape = _spatial_shape(x)
125
+ if img0_shape is not None:
126
+ metadata["img0_shape"] = img0_shape
127
+ for op in self.Ops:
128
+ x = op(x)
129
+ if "img0_shape" not in metadata:
130
+ img0_shape = _spatial_shape(x)
131
+ if img0_shape is not None:
132
+ metadata["img0_shape"] = img0_shape
133
+ ratio_pad = getattr(op, "ratio_pad", None)
134
+ if ratio_pad is not None:
135
+ metadata["ratio_pad"] = ratio_pad
136
+ return x, metadata
137
+
138
+ def to(
139
+ self,
140
+ device: str | torch.device,
141
+ ) -> None:
142
+ """Move the operations to the specified device.
143
+
144
+ Args:
145
+ device: Device to move the operations to.
146
+ """
147
+ if isinstance(device, str):
148
+ self.device = torch.device(device)
149
+ elif isinstance(device, torch.device):
150
+ self.device = device
151
+ else:
152
+ raise TypeError(f"Got unexpected type for device={type(device)}.")
153
+ for name, value in self.__dict__.items():
154
+ if isinstance(value, torch.Tensor):
155
+ setattr(self, name, value.to(self.device))
156
+ for op in self.Ops:
157
+ op.to(self.device)
@@ -0,0 +1,48 @@
1
+ """
2
+ Preprocessing builder.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from collections.abc import Mapping
8
+ from typing import Any
9
+
10
+ from .base import PreBase
11
+ from .center_crop import CenterCrop
12
+ from .letterbox import LetterBox
13
+ from .normalize import Normalize
14
+ from .order import SetOrder
15
+ from .reader import Reader
16
+ from .resize import Resize
17
+
18
+
19
+ def build_preprocess(
20
+ pre_cfg: Mapping[str, Mapping[str, Any]],
21
+ ) -> PreBase:
22
+ """Builds a preprocessing pipeline based on the configuration.
23
+
24
+ Args:
25
+ pre_cfg: Preprocessing configuration mapping operations to attributes.
26
+
27
+ Returns:
28
+ An orchestrator for the sequence of preprocessing steps.
29
+ """
30
+ res = []
31
+ for pre_type, pre_attr in pre_cfg.items():
32
+ pre_type_lower = pre_type.lower()
33
+ if pre_type_lower == Reader.__name__.lower():
34
+ res.append(Reader(**pre_attr))
35
+ elif pre_type_lower == Resize.__name__.lower():
36
+ res.append(Resize(**pre_attr))
37
+ elif pre_type_lower == CenterCrop.__name__.lower():
38
+ res.append(CenterCrop(**pre_attr))
39
+ elif pre_type_lower == SetOrder.__name__.lower():
40
+ res.append(SetOrder(**pre_attr))
41
+ elif pre_type_lower == LetterBox.__name__.lower():
42
+ res.append(LetterBox(**pre_attr))
43
+ elif pre_type_lower == Normalize.__name__.lower():
44
+ res.append(Normalize(**pre_attr))
45
+ else:
46
+ raise ValueError(f"Got unsupported pre_type={pre_type}.")
47
+
48
+ return PreBase(res)
@@ -0,0 +1,75 @@
1
+ """
2
+ Center crop preprocessing.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import cv2
8
+ import numpy as np
9
+ import torch
10
+ from PIL import Image
11
+
12
+ from ..types import TensorLike
13
+ from ._validation import normalize_image_size
14
+ from .base import PreOps
15
+
16
+
17
+ class CenterCrop(PreOps):
18
+ """
19
+ Center crop the image to a specified size.
20
+ """
21
+
22
+ def __init__(self, size: int | list[int] | tuple[int, int]) -> None:
23
+ """Initializes the CenterCrop operation.
24
+
25
+ Args:
26
+ size (int | list[int]): Target size [h, w]. If int, size is [size, size].
27
+ """
28
+ super().__init__()
29
+ self.size = normalize_image_size(size)
30
+
31
+ def __call__(self, x: TensorLike | Image.Image) -> np.ndarray:
32
+ """Applies center crop to the image.
33
+
34
+ Args:
35
+ x (np.ndarray | torch.Tensor | Image.Image): Input image.
36
+
37
+ Returns:
38
+ np.ndarray: Center-cropped image in HWC format.
39
+ """
40
+ if isinstance(x, torch.Tensor):
41
+ image = x.detach().cpu().numpy()
42
+ elif isinstance(x, Image.Image):
43
+ image = np.array(x)
44
+ elif isinstance(x, np.ndarray):
45
+ image = x
46
+ else:
47
+ raise TypeError(
48
+ f"CenterCrop expects a NumPy array, tensor, or PIL image, got {type(x).__name__}."
49
+ )
50
+ if image.ndim != 3:
51
+ raise ValueError(
52
+ f"CenterCrop expects a three-dimensional image, got shape {image.shape}."
53
+ )
54
+ H, W = image.shape[:2]
55
+ if (self.size[0] == H) and (self.size[1] == W):
56
+ return image
57
+ elif (self.size[1] > W) or (self.size[0] > H):
58
+ image = cv2.copyMakeBorder(
59
+ image,
60
+ (self.size[0] - H) // 2 if self.size[0] > H else 0,
61
+ (self.size[0] - H + 1) // 2 if self.size[0] > H else 0,
62
+ (self.size[1] - W) // 2 if self.size[1] > W else 0,
63
+ (self.size[1] - W + 1) // 2 if self.size[1] > W else 0,
64
+ cv2.BORDER_CONSTANT,
65
+ value=(0.0,),
66
+ )
67
+ H, W = image.shape[:2]
68
+ crop_top = round((H - self.size[0]) / 2.0)
69
+ crop_left = round((W - self.size[1]) / 2.0)
70
+ image = image[
71
+ crop_top : crop_top + self.size[0],
72
+ crop_left : crop_left + self.size[1],
73
+ :,
74
+ ]
75
+ return image.astype(np.uint8)
@@ -0,0 +1,123 @@
1
+ from __future__ import annotations
2
+
3
+ import cv2
4
+ import numpy as np
5
+ import torch
6
+
7
+ from ..letterbox import LetterBoxGeometry, RatioPad
8
+ from ..types import TensorLike
9
+ from ._validation import normalize_image_size, normalize_uint8_rgb_array
10
+ from .base import PreOps
11
+
12
+
13
+ def _apply_letterbox(
14
+ image: np.ndarray,
15
+ img_size: list[int],
16
+ interpolation: int,
17
+ padding_value: int | tuple[int, int, int],
18
+ ) -> tuple[np.ndarray, RatioPad]:
19
+ """Resize and pad an array while preserving its aspect ratio.
20
+
21
+ Args:
22
+ image: Image or two-dimensional semantic mask.
23
+ img_size: Target size as ``[height, width]``.
24
+ interpolation: OpenCV interpolation mode.
25
+ padding_value: Constant border value.
26
+
27
+ Returns:
28
+ The letterboxed array and its resize/padding metadata.
29
+ """
30
+
31
+ input_shape = (int(img_size[0]), int(img_size[1]))
32
+ original_shape = (int(image.shape[0]), int(image.shape[1]))
33
+ geometry = LetterBoxGeometry.from_shapes(input_shape, original_shape)
34
+ resized_height, resized_width = geometry.resized_shape
35
+ if image.shape[:2] != geometry.resized_shape:
36
+ image = cv2.resize(
37
+ image, (resized_width, resized_height), interpolation=interpolation
38
+ )
39
+ top, bottom, left, right = geometry.borders
40
+ image = cv2.copyMakeBorder(
41
+ image,
42
+ top,
43
+ bottom,
44
+ left,
45
+ right,
46
+ cv2.BORDER_CONSTANT,
47
+ value=padding_value,
48
+ )
49
+ return image, geometry.ratio_pad
50
+
51
+
52
+ def letterbox_semantic_mask(
53
+ mask: np.ndarray,
54
+ img_size: list[int],
55
+ ignore_label: int = 255,
56
+ ) -> tuple[np.ndarray, RatioPad]:
57
+ """Letterbox a semantic mask without interpolating class IDs.
58
+
59
+ Args:
60
+ mask: Two-dimensional semantic class map.
61
+ img_size: Target size as ``[height, width]``.
62
+ ignore_label: Class value used for padded pixels.
63
+
64
+ Returns:
65
+ The letterboxed mask and its resize/padding metadata.
66
+
67
+ Raises:
68
+ ValueError: If the mask is not two-dimensional.
69
+ """
70
+
71
+ if mask.ndim != 2:
72
+ raise ValueError(
73
+ f"Semantic masks must be two-dimensional, got shape {mask.shape}."
74
+ )
75
+ return _apply_letterbox(mask, img_size, cv2.INTER_NEAREST, ignore_label)
76
+
77
+
78
+ class LetterBox(PreOps):
79
+ """Preprocessing for YOLO models, implementing letterbox resizing.
80
+
81
+ Resizes the image while maintaining aspect ratio, adding padding to meet
82
+ target dimensions. Floating-point RGB inputs in ``[0, 1]`` are scaled to
83
+ byte RGB; other floating-point values must be finite and in ``[0, 255]``.
84
+ Based on Ultralytics implementation.
85
+
86
+ Ref: https://github.com/ultralytics/ultralytics/blob/main/ultralytics/data/augment.py#L1535
87
+ """
88
+
89
+ def __init__(self, img_size: list[int]) -> None:
90
+ """Initializes LetterBox with target image size.
91
+
92
+ Args:
93
+ img_size (list[int]): Target image size [h, w].
94
+ """
95
+ super().__init__()
96
+ self.img_size = normalize_image_size(img_size, name="img_size")
97
+ self.ratio_pad: tuple[tuple[float, float], tuple[float, float]] | None = None
98
+
99
+ def __call__(self, x: TensorLike) -> torch.Tensor:
100
+ """Executes YOLO preprocessing (letterbox resizing).
101
+
102
+ Args:
103
+ x (TensorLike): Input image.
104
+
105
+ Returns:
106
+ torch.Tensor: Preprocessed image in HWC format on the selected device.
107
+ """
108
+ if isinstance(x, torch.Tensor):
109
+ x = x.detach().cpu().numpy()
110
+ elif not isinstance(x, np.ndarray):
111
+ raise TypeError(
112
+ f"LetterBox expects a NumPy array or tensor, got {type(x).__name__}."
113
+ )
114
+ if x.ndim != 3:
115
+ raise ValueError(f"LetterBox expects an HWC image, got shape {x.shape}.")
116
+ x = normalize_uint8_rgb_array(x, operation="LetterBox")
117
+ img, self.ratio_pad = _apply_letterbox(
118
+ x,
119
+ self.img_size,
120
+ cv2.INTER_LINEAR,
121
+ (114, 114, 114),
122
+ )
123
+ return torch.from_numpy(img).to(self.device).byte()