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.
- mblt_vision/__init__.py +86 -0
- mblt_vision/_api.py +53 -0
- mblt_vision/_compat.py +227 -0
- mblt_vision/_model_paths.py +137 -0
- mblt_vision/_tasks.py +30 -0
- mblt_vision/benchmark/__init__.py +1 -0
- mblt_vision/benchmark/argparse_utils.py +106 -0
- mblt_vision/benchmark/chart_utils.py +146 -0
- mblt_vision/benchmark/io_utils.py +64 -0
- mblt_vision/benchmark/summary_utils.py +770 -0
- mblt_vision/cli/__init__.py +5 -0
- mblt_vision/cli/__main__.py +5 -0
- mblt_vision/cli/_vision.py +337 -0
- mblt_vision/cli/compile.py +117 -0
- mblt_vision/cli/main.py +35 -0
- mblt_vision/cli/predict.py +64 -0
- mblt_vision/cli/val.py +562 -0
- mblt_vision/compile/__init__.py +21 -0
- mblt_vision/compile/vision.py +1120 -0
- mblt_vision/datasets/__init__.py +15 -0
- mblt_vision/datasets/ade20k.yaml +164 -0
- mblt_vision/datasets/cityscapes.yaml +54 -0
- mblt_vision/datasets/coco.yaml +178 -0
- mblt_vision/datasets/dotav1.yaml +28 -0
- mblt_vision/datasets/imagenet.yaml +1019 -0
- mblt_vision/datasets/imagenet_synsets.txt +1000 -0
- mblt_vision/datasets/nyu-depth.yaml +7 -0
- mblt_vision/datasets/registry.py +158 -0
- mblt_vision/datasets/widerface.yaml +9 -0
- mblt_vision/depth_estimation/__init__.py +19 -0
- mblt_vision/face_detection/__init__.py +43 -0
- mblt_vision/image_classification/__init__.py +311 -0
- mblt_vision/instance_segmentation/__init__.py +65 -0
- mblt_vision/models/AlexNet.yaml +23 -0
- mblt_vision/models/CAFormer_B36.yaml +22 -0
- mblt_vision/models/CAFormer_M36.yaml +22 -0
- mblt_vision/models/CAFormer_S18.yaml +22 -0
- mblt_vision/models/CAFormer_S36.yaml +22 -0
- mblt_vision/models/CoAtNet_0_RW_224.yaml +22 -0
- mblt_vision/models/CoAtNet_1_RW_224.yaml +22 -0
- mblt_vision/models/CoAtNet_2_RW_224.yaml +22 -0
- mblt_vision/models/ConvFormer_B36.yaml +22 -0
- mblt_vision/models/ConvFormer_M36.yaml +22 -0
- mblt_vision/models/ConvFormer_S18.yaml +22 -0
- mblt_vision/models/ConvFormer_S36.yaml +22 -0
- mblt_vision/models/ConvNext_Base.yaml +23 -0
- mblt_vision/models/ConvNext_Large.yaml +23 -0
- mblt_vision/models/ConvNext_Small.yaml +23 -0
- mblt_vision/models/ConvNext_Tiny.yaml +23 -0
- mblt_vision/models/DeiT3_Base_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT3_Base_Patch16_384.yaml +22 -0
- mblt_vision/models/DeiT3_Large_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT3_Large_Patch16_384.yaml +22 -0
- mblt_vision/models/DeiT3_Medium_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT3_Small_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT3_Small_Patch16_384.yaml +22 -0
- mblt_vision/models/DeiT_Base_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT_Base_Patch16_384.yaml +22 -0
- mblt_vision/models/DeiT_Small_Patch16_224.yaml +22 -0
- mblt_vision/models/DeiT_Tiny_Patch16_224.yaml +22 -0
- mblt_vision/models/DenseNet121.yaml +23 -0
- mblt_vision/models/DenseNet161.yaml +23 -0
- mblt_vision/models/DenseNet169.yaml +23 -0
- mblt_vision/models/DenseNet201.yaml +23 -0
- mblt_vision/models/EfficientFormer_L1.yaml +22 -0
- mblt_vision/models/EfficientFormer_L3.yaml +22 -0
- mblt_vision/models/EfficientFormer_L7.yaml +22 -0
- mblt_vision/models/EfficientNet_B0.yaml +23 -0
- mblt_vision/models/EfficientNet_B1.yaml +32 -0
- mblt_vision/models/EfficientNet_B2.yaml +23 -0
- mblt_vision/models/EfficientNet_B3.yaml +23 -0
- mblt_vision/models/EfficientNet_B4.yaml +23 -0
- mblt_vision/models/EfficientNet_B5.yaml +23 -0
- mblt_vision/models/EfficientNet_B6.yaml +23 -0
- mblt_vision/models/EfficientNet_B7.yaml +23 -0
- mblt_vision/models/EfficientNet_V2_L.yaml +23 -0
- mblt_vision/models/EfficientNet_V2_M.yaml +23 -0
- mblt_vision/models/EfficientNet_V2_S.yaml +23 -0
- mblt_vision/models/FlexiVit_Base.yaml +22 -0
- mblt_vision/models/FlexiVit_Large.yaml +22 -0
- mblt_vision/models/FlexiVit_Small.yaml +22 -0
- mblt_vision/models/GELANc-seg.yaml +29 -0
- mblt_vision/models/GELANc.yaml +28 -0
- mblt_vision/models/GELANe.yaml +28 -0
- mblt_vision/models/GELANm.yaml +28 -0
- mblt_vision/models/GELANs.yaml +28 -0
- mblt_vision/models/GoogLeNet.yaml +23 -0
- mblt_vision/models/Inception_V3.yaml +23 -0
- mblt_vision/models/LeViT_Conv_128.yaml +22 -0
- mblt_vision/models/LeViT_Conv_128S.yaml +22 -0
- mblt_vision/models/LeViT_Conv_192.yaml +22 -0
- mblt_vision/models/LeViT_Conv_256.yaml +22 -0
- mblt_vision/models/LeViT_Conv_384.yaml +22 -0
- mblt_vision/models/MNASNet0_5.yaml +23 -0
- mblt_vision/models/MNASNet0_75.yaml +23 -0
- mblt_vision/models/MNASNet1_0.yaml +23 -0
- mblt_vision/models/MNASNet1_3.yaml +23 -0
- mblt_vision/models/MobileNet_V2.yaml +32 -0
- mblt_vision/models/MobileNet_V3_Large.yaml +32 -0
- mblt_vision/models/MobileNet_V3_Small.yaml +23 -0
- mblt_vision/models/RegNet_X_16GF.yaml +32 -0
- mblt_vision/models/RegNet_X_1_6GF.yaml +32 -0
- mblt_vision/models/RegNet_X_32GF.yaml +32 -0
- mblt_vision/models/RegNet_X_3_2GF.yaml +32 -0
- mblt_vision/models/RegNet_X_400MF.yaml +32 -0
- mblt_vision/models/RegNet_X_800MF.yaml +32 -0
- mblt_vision/models/RegNet_X_8GF.yaml +32 -0
- mblt_vision/models/RegNet_Y_16GF.yaml +76 -0
- mblt_vision/models/RegNet_Y_1_6GF.yaml +32 -0
- mblt_vision/models/RegNet_Y_32GF.yaml +76 -0
- mblt_vision/models/RegNet_Y_3_2GF.yaml +32 -0
- mblt_vision/models/RegNet_Y_400MF.yaml +32 -0
- mblt_vision/models/RegNet_Y_800MF.yaml +32 -0
- mblt_vision/models/RegNet_Y_8GF.yaml +32 -0
- mblt_vision/models/RepViT_M0_9.yaml +22 -0
- mblt_vision/models/RepViT_M1.yaml +22 -0
- mblt_vision/models/RepViT_M1_0.yaml +22 -0
- mblt_vision/models/RepViT_M1_1.yaml +22 -0
- mblt_vision/models/RepViT_M1_5.yaml +22 -0
- mblt_vision/models/RepViT_M2.yaml +22 -0
- mblt_vision/models/RepViT_M2_3.yaml +22 -0
- mblt_vision/models/RepViT_M3.yaml +22 -0
- mblt_vision/models/ResNeXt101_32X8D.yaml +32 -0
- mblt_vision/models/ResNeXt101_64X4D.yaml +23 -0
- mblt_vision/models/ResNeXt50_32X4D.yaml +32 -0
- mblt_vision/models/ResNet101.yaml +32 -0
- mblt_vision/models/ResNet152.yaml +32 -0
- mblt_vision/models/ResNet18.yaml +23 -0
- mblt_vision/models/ResNet34.yaml +23 -0
- mblt_vision/models/ResNet50.yaml +32 -0
- mblt_vision/models/ShuffleNet_V2_X0_5.yaml +23 -0
- mblt_vision/models/ShuffleNet_V2_X1_0.yaml +23 -0
- mblt_vision/models/ShuffleNet_V2_X1_5.yaml +23 -0
- mblt_vision/models/ShuffleNet_V2_X2_0.yaml +23 -0
- mblt_vision/models/SqueezeNet1_0.yaml +23 -0
- mblt_vision/models/SqueezeNet1_1.yaml +23 -0
- mblt_vision/models/Swin_B.yaml +23 -0
- mblt_vision/models/Swin_S.yaml +23 -0
- mblt_vision/models/Swin_T.yaml +23 -0
- mblt_vision/models/VGG11.yaml +23 -0
- mblt_vision/models/VGG11_BN.yaml +23 -0
- mblt_vision/models/VGG13.yaml +23 -0
- mblt_vision/models/VGG13_BN.yaml +23 -0
- mblt_vision/models/VGG16.yaml +23 -0
- mblt_vision/models/VGG16_BN.yaml +23 -0
- mblt_vision/models/VGG19.yaml +23 -0
- mblt_vision/models/VGG19_BN.yaml +23 -0
- mblt_vision/models/ViT_B_16.yaml +67 -0
- mblt_vision/models/ViT_B_32.yaml +23 -0
- mblt_vision/models/ViT_Base_Patch16_224.yaml +22 -0
- mblt_vision/models/ViT_Base_Patch16_384.yaml +22 -0
- mblt_vision/models/ViT_Base_Patch32_224.yaml +22 -0
- mblt_vision/models/ViT_Base_Patch32_384.yaml +22 -0
- mblt_vision/models/ViT_Base_Patch8_224.yaml +22 -0
- mblt_vision/models/ViT_L_16.yaml +67 -0
- mblt_vision/models/ViT_L_32.yaml +23 -0
- mblt_vision/models/ViT_Large_Patch16_224.yaml +22 -0
- mblt_vision/models/ViT_Large_Patch16_384.yaml +22 -0
- mblt_vision/models/ViT_Large_Patch32_384.yaml +22 -0
- mblt_vision/models/ViT_Small_Patch16_224.yaml +22 -0
- mblt_vision/models/ViT_Small_Patch16_384.yaml +22 -0
- mblt_vision/models/ViT_Small_Patch32_224.yaml +22 -0
- mblt_vision/models/ViT_Small_Patch32_384.yaml +22 -0
- mblt_vision/models/ViT_Tiny_Patch16_224.yaml +22 -0
- mblt_vision/models/ViT_Tiny_Patch16_384.yaml +22 -0
- mblt_vision/models/VisFormer_Small.yaml +22 -0
- mblt_vision/models/VisFormer_Tiny.yaml +22 -0
- mblt_vision/models/Wide_ResNet101_2.yaml +32 -0
- mblt_vision/models/Wide_ResNet50_2.yaml +32 -0
- mblt_vision/models/YOLO11l-cls.yaml +23 -0
- mblt_vision/models/YOLO11l-face.yaml +27 -0
- mblt_vision/models/YOLO11l-obb.yaml +28 -0
- mblt_vision/models/YOLO11l-pose.yaml +28 -0
- mblt_vision/models/YOLO11l-seg.yaml +28 -0
- mblt_vision/models/YOLO11l.yaml +27 -0
- mblt_vision/models/YOLO11m-cls.yaml +23 -0
- mblt_vision/models/YOLO11m-face.yaml +27 -0
- mblt_vision/models/YOLO11m-obb.yaml +28 -0
- mblt_vision/models/YOLO11m-pose.yaml +28 -0
- mblt_vision/models/YOLO11m-seg.yaml +28 -0
- mblt_vision/models/YOLO11m.yaml +27 -0
- mblt_vision/models/YOLO11n-cls.yaml +23 -0
- mblt_vision/models/YOLO11n-face.yaml +27 -0
- mblt_vision/models/YOLO11n-obb.yaml +28 -0
- mblt_vision/models/YOLO11n-pose.yaml +28 -0
- mblt_vision/models/YOLO11n-seg.yaml +28 -0
- mblt_vision/models/YOLO11n.yaml +27 -0
- mblt_vision/models/YOLO11s-cls.yaml +23 -0
- mblt_vision/models/YOLO11s-face.yaml +27 -0
- mblt_vision/models/YOLO11s-obb.yaml +28 -0
- mblt_vision/models/YOLO11s-pose.yaml +28 -0
- mblt_vision/models/YOLO11s-seg.yaml +28 -0
- mblt_vision/models/YOLO11s.yaml +27 -0
- mblt_vision/models/YOLO11x-cls.yaml +23 -0
- mblt_vision/models/YOLO11x-obb.yaml +28 -0
- mblt_vision/models/YOLO11x-pose.yaml +28 -0
- mblt_vision/models/YOLO11x-seg.yaml +28 -0
- mblt_vision/models/YOLO11x.yaml +27 -0
- mblt_vision/models/YOLO12l-face.yaml +27 -0
- mblt_vision/models/YOLO12l-seg.yaml +28 -0
- mblt_vision/models/YOLO12l.yaml +27 -0
- mblt_vision/models/YOLO12m-face.yaml +27 -0
- mblt_vision/models/YOLO12m-seg.yaml +28 -0
- mblt_vision/models/YOLO12m.yaml +27 -0
- mblt_vision/models/YOLO12n-face.yaml +27 -0
- mblt_vision/models/YOLO12n-seg.yaml +28 -0
- mblt_vision/models/YOLO12n.yaml +27 -0
- mblt_vision/models/YOLO12s-face.yaml +27 -0
- mblt_vision/models/YOLO12s-seg.yaml +28 -0
- mblt_vision/models/YOLO12s.yaml +27 -0
- mblt_vision/models/YOLO12x-seg.yaml +28 -0
- mblt_vision/models/YOLO12x.yaml +27 -0
- mblt_vision/models/YOLO26l-cls.yaml +23 -0
- mblt_vision/models/YOLO26l-depth.yaml +17 -0
- mblt_vision/models/YOLO26l-distill.yaml +27 -0
- mblt_vision/models/YOLO26l-obb.yaml +28 -0
- mblt_vision/models/YOLO26l-pose.yaml +28 -0
- mblt_vision/models/YOLO26l-seg.yaml +28 -0
- mblt_vision/models/YOLO26l-sem-ade20k.yaml +17 -0
- mblt_vision/models/YOLO26l-sem.yaml +17 -0
- mblt_vision/models/YOLO26l.yaml +27 -0
- mblt_vision/models/YOLO26m-cls.yaml +23 -0
- mblt_vision/models/YOLO26m-depth.yaml +17 -0
- mblt_vision/models/YOLO26m-distill.yaml +27 -0
- mblt_vision/models/YOLO26m-obb.yaml +28 -0
- mblt_vision/models/YOLO26m-pose.yaml +28 -0
- mblt_vision/models/YOLO26m-seg.yaml +28 -0
- mblt_vision/models/YOLO26m-sem-ade20k.yaml +17 -0
- mblt_vision/models/YOLO26m-sem.yaml +17 -0
- mblt_vision/models/YOLO26m.yaml +27 -0
- mblt_vision/models/YOLO26n-cls.yaml +23 -0
- mblt_vision/models/YOLO26n-depth.yaml +17 -0
- mblt_vision/models/YOLO26n-distill.yaml +27 -0
- mblt_vision/models/YOLO26n-obb.yaml +28 -0
- mblt_vision/models/YOLO26n-pose.yaml +28 -0
- mblt_vision/models/YOLO26n-seg.yaml +28 -0
- mblt_vision/models/YOLO26n-sem-ade20k.yaml +17 -0
- mblt_vision/models/YOLO26n-sem.yaml +17 -0
- mblt_vision/models/YOLO26n.yaml +27 -0
- mblt_vision/models/YOLO26s-cls.yaml +23 -0
- mblt_vision/models/YOLO26s-depth.yaml +17 -0
- mblt_vision/models/YOLO26s-distill.yaml +27 -0
- mblt_vision/models/YOLO26s-obb.yaml +28 -0
- mblt_vision/models/YOLO26s-pose.yaml +28 -0
- mblt_vision/models/YOLO26s-seg.yaml +28 -0
- mblt_vision/models/YOLO26s-sem-ade20k.yaml +17 -0
- mblt_vision/models/YOLO26s-sem.yaml +17 -0
- mblt_vision/models/YOLO26s.yaml +27 -0
- mblt_vision/models/YOLO26x-cls.yaml +23 -0
- mblt_vision/models/YOLO26x-depth.yaml +17 -0
- mblt_vision/models/YOLO26x-distill.yaml +27 -0
- mblt_vision/models/YOLO26x-obb.yaml +28 -0
- mblt_vision/models/YOLO26x-pose.yaml +28 -0
- mblt_vision/models/YOLO26x-seg.yaml +28 -0
- mblt_vision/models/YOLO26x-sem-ade20k.yaml +17 -0
- mblt_vision/models/YOLO26x-sem.yaml +17 -0
- mblt_vision/models/YOLO26x.yaml +27 -0
- mblt_vision/models/YOLOv10b.yaml +28 -0
- mblt_vision/models/YOLOv10l-face.yaml +28 -0
- mblt_vision/models/YOLOv10l.yaml +28 -0
- mblt_vision/models/YOLOv10m-face.yaml +28 -0
- mblt_vision/models/YOLOv10m.yaml +28 -0
- mblt_vision/models/YOLOv10n-face.yaml +28 -0
- mblt_vision/models/YOLOv10n.yaml +28 -0
- mblt_vision/models/YOLOv10s-face.yaml +28 -0
- mblt_vision/models/YOLOv10s.yaml +28 -0
- mblt_vision/models/YOLOv10x.yaml +28 -0
- mblt_vision/models/YOLOv3-spp.yaml +44 -0
- mblt_vision/models/YOLOv3-sppu.yaml +27 -0
- mblt_vision/models/YOLOv3-tiny.yaml +38 -0
- mblt_vision/models/YOLOv3-tinyu.yaml +27 -0
- mblt_vision/models/YOLOv3.yaml +44 -0
- mblt_vision/models/YOLOv3u.yaml +27 -0
- mblt_vision/models/YOLOv5l-cls.yaml +22 -0
- mblt_vision/models/YOLOv5l-seg.yaml +45 -0
- mblt_vision/models/YOLOv5l.yaml +44 -0
- mblt_vision/models/YOLOv5l6.yaml +50 -0
- mblt_vision/models/YOLOv5l6u.yaml +27 -0
- mblt_vision/models/YOLOv5lu.yaml +27 -0
- mblt_vision/models/YOLOv5m-cls.yaml +22 -0
- mblt_vision/models/YOLOv5m-seg.yaml +45 -0
- mblt_vision/models/YOLOv5m.yaml +45 -0
- mblt_vision/models/YOLOv5m6.yaml +50 -0
- mblt_vision/models/YOLOv5m6u.yaml +27 -0
- mblt_vision/models/YOLOv5mu.yaml +27 -0
- mblt_vision/models/YOLOv5n-cls.yaml +22 -0
- mblt_vision/models/YOLOv5n-seg.yaml +45 -0
- mblt_vision/models/YOLOv5n.yaml +44 -0
- mblt_vision/models/YOLOv5n6.yaml +50 -0
- mblt_vision/models/YOLOv5n6u.yaml +27 -0
- mblt_vision/models/YOLOv5nu.yaml +27 -0
- mblt_vision/models/YOLOv5s-cls.yaml +22 -0
- mblt_vision/models/YOLOv5s-seg.yaml +45 -0
- mblt_vision/models/YOLOv5s.yaml +44 -0
- mblt_vision/models/YOLOv5s6.yaml +50 -0
- mblt_vision/models/YOLOv5s6u.yaml +27 -0
- mblt_vision/models/YOLOv5su.yaml +27 -0
- mblt_vision/models/YOLOv5x-cls.yaml +22 -0
- mblt_vision/models/YOLOv5x-seg.yaml +45 -0
- mblt_vision/models/YOLOv5x.yaml +44 -0
- mblt_vision/models/YOLOv5x6.yaml +50 -0
- mblt_vision/models/YOLOv5x6u.yaml +27 -0
- mblt_vision/models/YOLOv5xu.yaml +27 -0
- mblt_vision/models/YOLOv6m-face.yaml +27 -0
- mblt_vision/models/YOLOv6n-face.yaml +27 -0
- mblt_vision/models/YOLOv7.yaml +44 -0
- mblt_vision/models/YOLOv7d6.yaml +50 -0
- mblt_vision/models/YOLOv7e6.yaml +50 -0
- mblt_vision/models/YOLOv7e6e.yaml +50 -0
- mblt_vision/models/YOLOv7w6.yaml +50 -0
- mblt_vision/models/YOLOv7x.yaml +44 -0
- mblt_vision/models/YOLOv8l-cls.yaml +23 -0
- mblt_vision/models/YOLOv8l-face.yaml +27 -0
- mblt_vision/models/YOLOv8l-obb.yaml +28 -0
- mblt_vision/models/YOLOv8l-pose.yaml +28 -0
- mblt_vision/models/YOLOv8l-seg.yaml +28 -0
- mblt_vision/models/YOLOv8l.yaml +27 -0
- mblt_vision/models/YOLOv8m-cls.yaml +23 -0
- mblt_vision/models/YOLOv8m-face.yaml +27 -0
- mblt_vision/models/YOLOv8m-obb.yaml +28 -0
- mblt_vision/models/YOLOv8m-pose.yaml +28 -0
- mblt_vision/models/YOLOv8m-seg.yaml +28 -0
- mblt_vision/models/YOLOv8m.yaml +27 -0
- mblt_vision/models/YOLOv8n-cls.yaml +23 -0
- mblt_vision/models/YOLOv8n-face.yaml +27 -0
- mblt_vision/models/YOLOv8n-obb.yaml +28 -0
- mblt_vision/models/YOLOv8n-pose.yaml +28 -0
- mblt_vision/models/YOLOv8n-seg.yaml +28 -0
- mblt_vision/models/YOLOv8n.yaml +27 -0
- mblt_vision/models/YOLOv8s-cls.yaml +23 -0
- mblt_vision/models/YOLOv8s-obb.yaml +28 -0
- mblt_vision/models/YOLOv8s-pose.yaml +28 -0
- mblt_vision/models/YOLOv8s-seg.yaml +28 -0
- mblt_vision/models/YOLOv8s.yaml +27 -0
- mblt_vision/models/YOLOv8x-cls.yaml +23 -0
- mblt_vision/models/YOLOv8x-obb.yaml +28 -0
- mblt_vision/models/YOLOv8x-pose-p6.yaml +28 -0
- mblt_vision/models/YOLOv8x-pose.yaml +28 -0
- mblt_vision/models/YOLOv8x-seg.yaml +28 -0
- mblt_vision/models/YOLOv8x.yaml +27 -0
- mblt_vision/models/YOLOv9c-seg.yaml +28 -0
- mblt_vision/models/YOLOv9c.yaml +27 -0
- mblt_vision/models/YOLOv9e-seg.yaml +28 -0
- mblt_vision/models/YOLOv9e.yaml +27 -0
- mblt_vision/models/YOLOv9m.yaml +27 -0
- mblt_vision/models/YOLOv9s.yaml +27 -0
- mblt_vision/models/YOLOv9t.yaml +27 -0
- mblt_vision/obb/__init__.py +39 -0
- mblt_vision/object_detection/__init__.py +153 -0
- mblt_vision/pose_estimation/__init__.py +41 -0
- mblt_vision/py.typed +1 -0
- mblt_vision/semantic_segmentation/__init__.py +29 -0
- mblt_vision/utils/__init__.py +0 -0
- mblt_vision/utils/datasets/__init__.py +85 -0
- mblt_vision/utils/datasets/ade20k.py +41 -0
- mblt_vision/utils/datasets/cityscapes.py +66 -0
- mblt_vision/utils/datasets/coco.py +243 -0
- mblt_vision/utils/datasets/dataloader.py +1016 -0
- mblt_vision/utils/datasets/dotav1.py +59 -0
- mblt_vision/utils/datasets/imagenet.py +29 -0
- mblt_vision/utils/datasets/organizer.py +2145 -0
- mblt_vision/utils/datasets/readiness.py +1063 -0
- mblt_vision/utils/evaluation/__init__.py +51 -0
- mblt_vision/utils/evaluation/_result.py +22 -0
- mblt_vision/utils/evaluation/eval_ade20k.py +302 -0
- mblt_vision/utils/evaluation/eval_cityscapes.py +32 -0
- mblt_vision/utils/evaluation/eval_coco.py +465 -0
- mblt_vision/utils/evaluation/eval_dota.py +878 -0
- mblt_vision/utils/evaluation/eval_imagenet.py +151 -0
- mblt_vision/utils/evaluation/eval_nyu_depth.py +189 -0
- mblt_vision/utils/evaluation/eval_widerface.py +440 -0
- mblt_vision/utils/letterbox.py +118 -0
- mblt_vision/utils/postprocess/__init__.py +9 -0
- mblt_vision/utils/postprocess/_letterbox.py +102 -0
- mblt_vision/utils/postprocess/base.py +743 -0
- mblt_vision/utils/postprocess/build_post.py +120 -0
- mblt_vision/utils/postprocess/cls_post.py +117 -0
- mblt_vision/utils/postprocess/common.py +1571 -0
- mblt_vision/utils/postprocess/depth_post.py +106 -0
- mblt_vision/utils/postprocess/semantic_seg_post.py +192 -0
- mblt_vision/utils/postprocess/yolo_anchor_post.py +469 -0
- mblt_vision/utils/postprocess/yolo_anchorless_post.py +952 -0
- mblt_vision/utils/postprocess/yolo_dflfree_post.py +983 -0
- mblt_vision/utils/postprocess/yolo_nmsfree_post.py +176 -0
- mblt_vision/utils/preprocess/__init__.py +27 -0
- mblt_vision/utils/preprocess/_validation.py +66 -0
- mblt_vision/utils/preprocess/base.py +157 -0
- mblt_vision/utils/preprocess/build_pre.py +48 -0
- mblt_vision/utils/preprocess/center_crop.py +75 -0
- mblt_vision/utils/preprocess/letterbox.py +123 -0
- mblt_vision/utils/preprocess/normalize.py +94 -0
- mblt_vision/utils/preprocess/order.py +74 -0
- mblt_vision/utils/preprocess/reader.py +94 -0
- mblt_vision/utils/preprocess/resize.py +202 -0
- mblt_vision/utils/preprocess/yolo_pre.py +7 -0
- mblt_vision/utils/results.py +725 -0
- mblt_vision/utils/types.py +15 -0
- mblt_vision/wrapper.py +1121 -0
- mblt_vision_python-0.0.0.dist-info/METADATA +152 -0
- mblt_vision_python-0.0.0.dist-info/RECORD +404 -0
- mblt_vision_python-0.0.0.dist-info/WHEEL +5 -0
- mblt_vision_python-0.0.0.dist-info/entry_points.txt +2 -0
- mblt_vision_python-0.0.0.dist-info/licenses/LICENSE +28 -0
- 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
|