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,440 @@
|
|
|
1
|
+
"""Evaluation script for WiderFace face detection."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from time import time
|
|
9
|
+
from typing import TYPE_CHECKING, Any, NamedTuple, cast
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from mblt_vision.utils.postprocess.base import YOLODetectionPostBase
|
|
13
|
+
from scipy.io import loadmat
|
|
14
|
+
from tqdm import tqdm
|
|
15
|
+
|
|
16
|
+
from ..datasets import CustomWiderFaceDataset, get_widerface_loader
|
|
17
|
+
from ..datasets.readiness import (
|
|
18
|
+
_load_widerface_image_names,
|
|
19
|
+
_widerface_image_shapes,
|
|
20
|
+
_widerface_difficulty_metadata_ready,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ...wrapper import MBLT_Engine
|
|
25
|
+
|
|
26
|
+
CustomWiderface = CustomWiderFaceDataset
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class WiderFaceResult(NamedTuple):
|
|
30
|
+
"""WiderFace AP metrics."""
|
|
31
|
+
|
|
32
|
+
easy_ap: float
|
|
33
|
+
medium_ap: float
|
|
34
|
+
hard_ap: float
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def mean_ap(self) -> float:
|
|
38
|
+
"""Return the mean AP across Easy, Medium, and Hard."""
|
|
39
|
+
|
|
40
|
+
return (self.easy_ap + self.medium_ap + self.hard_ap) / 3.0
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def primary_score(self) -> float:
|
|
44
|
+
"""Return mean AP across the three validation splits."""
|
|
45
|
+
|
|
46
|
+
return self.mean_ap
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def secondary_score(self) -> float:
|
|
50
|
+
"""Return Hard-set AP."""
|
|
51
|
+
|
|
52
|
+
return self.hard_ap
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _empty_prediction() -> np.ndarray:
|
|
56
|
+
"""Return an empty WiderFace prediction array."""
|
|
57
|
+
|
|
58
|
+
return np.zeros((0, 5), dtype=np.float32)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _initialize_predictions(
|
|
62
|
+
dataset: CustomWiderFaceDataset,
|
|
63
|
+
) -> dict[str, dict[str, np.ndarray]]:
|
|
64
|
+
"""Initialize empty predictions for every WiderFace sample."""
|
|
65
|
+
|
|
66
|
+
predictions: dict[str, dict[str, np.ndarray]] = {}
|
|
67
|
+
for _, event_name, file_name in dataset.samples:
|
|
68
|
+
predictions.setdefault(event_name, {})[os.path.splitext(file_name)[0]] = (
|
|
69
|
+
_empty_prediction()
|
|
70
|
+
)
|
|
71
|
+
return predictions
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _boxes_scores_to_prediction(
|
|
75
|
+
boxes: list[list[float]], scores: list[float]
|
|
76
|
+
) -> np.ndarray:
|
|
77
|
+
"""Convert xywh boxes and scores to a WiderFace prediction array."""
|
|
78
|
+
|
|
79
|
+
if len(boxes) != len(scores):
|
|
80
|
+
raise ValueError(
|
|
81
|
+
"WiderFace postprocess returned unequal box and score counts: "
|
|
82
|
+
f"boxes={len(boxes)}, scores={len(scores)}."
|
|
83
|
+
)
|
|
84
|
+
if not boxes:
|
|
85
|
+
return _empty_prediction()
|
|
86
|
+
prediction = np.zeros((len(boxes), 5), dtype=np.float32)
|
|
87
|
+
for index, (box, score) in enumerate(zip(boxes, scores)):
|
|
88
|
+
prediction[index, :4] = np.asarray(box, dtype=np.float32)
|
|
89
|
+
prediction[index, 4] = float(score)
|
|
90
|
+
return prediction
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def eval_widerface(
|
|
94
|
+
model: MBLT_Engine,
|
|
95
|
+
data_path: str,
|
|
96
|
+
batch_size: int,
|
|
97
|
+
conf_thres: float | None = None,
|
|
98
|
+
iou_thres: float | None = None,
|
|
99
|
+
) -> WiderFaceResult:
|
|
100
|
+
"""Evaluate a face-detection model on WiderFace validation data.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
model: The face-detection engine to evaluate.
|
|
104
|
+
data_path: Organized WiderFace dataset root.
|
|
105
|
+
batch_size: Validation batch size.
|
|
106
|
+
conf_thres: Optional confidence threshold override.
|
|
107
|
+
iou_thres: Optional IoU threshold override.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
WiderFace Easy, Medium, and Hard AP metrics.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
if model.post_cfg["task"] != "face_detection":
|
|
114
|
+
raise NotImplementedError(
|
|
115
|
+
f"Task {model.post_cfg['task']} is not supported for WiderFace evaluation."
|
|
116
|
+
)
|
|
117
|
+
dataset_name = model.post_cfg.get("dataset")
|
|
118
|
+
if not isinstance(dataset_name, str) or dataset_name.lower() != "widerface":
|
|
119
|
+
raise ValueError(
|
|
120
|
+
"WiderFace evaluation requires model post_cfg.dataset to be 'widerface', "
|
|
121
|
+
f"got {dataset_name!r}."
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
dataset_root = Path(data_path)
|
|
125
|
+
expected_images = _load_widerface_image_names(dataset_root / "wider_face_val.mat")
|
|
126
|
+
image_shapes = (
|
|
127
|
+
_widerface_image_shapes(dataset_root, expected_images)
|
|
128
|
+
if expected_images is not None
|
|
129
|
+
else None
|
|
130
|
+
)
|
|
131
|
+
if (
|
|
132
|
+
expected_images is None
|
|
133
|
+
or image_shapes is None
|
|
134
|
+
or not _widerface_difficulty_metadata_ready(
|
|
135
|
+
dataset_root, expected_images, image_shapes=image_shapes
|
|
136
|
+
)
|
|
137
|
+
):
|
|
138
|
+
raise ValueError(
|
|
139
|
+
"WiderFace evaluation metadata is malformed or has inconsistent difficulty indices."
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
dataset = CustomWiderface(os.path.join(data_path, "images"))
|
|
143
|
+
actual_images: dict[str, set[str]] = {}
|
|
144
|
+
for _, event_name, file_name in dataset.samples:
|
|
145
|
+
actual_images.setdefault(event_name, set()).add(file_name)
|
|
146
|
+
if actual_images != expected_images or sum(
|
|
147
|
+
len(file_names) for file_names in actual_images.values()
|
|
148
|
+
) != len(dataset.samples):
|
|
149
|
+
raise ValueError(
|
|
150
|
+
"WiderFace image tree does not match the validation metadata identities."
|
|
151
|
+
)
|
|
152
|
+
dataloader = get_widerface_loader(
|
|
153
|
+
dataset, batch_size, model.preprocess_with_metadata
|
|
154
|
+
)
|
|
155
|
+
model.set_postprocess_thresholds(conf_thres=conf_thres, iou_thres=iou_thres)
|
|
156
|
+
|
|
157
|
+
predictions = _initialize_predictions(dataset)
|
|
158
|
+
num_data = len(dataset)
|
|
159
|
+
total_iter = math.ceil(num_data / batch_size)
|
|
160
|
+
pbar = tqdm(dataloader, total=total_iter, desc="Evaluating WiderFace")
|
|
161
|
+
inference_time = 0.0
|
|
162
|
+
cum_num_data = 0
|
|
163
|
+
|
|
164
|
+
for input_npu, org_shape, ratio_pad, target_classes, fnames in pbar:
|
|
165
|
+
cum_num_data += len(fnames)
|
|
166
|
+
tic = time()
|
|
167
|
+
out_npu = model(input_npu)
|
|
168
|
+
inference_time += time() - tic
|
|
169
|
+
nms_outs = model.postprocess(out_npu)
|
|
170
|
+
input_shape = (int(input_npu.shape[1]), int(input_npu.shape[2]))
|
|
171
|
+
img0_shapes = [(int(shape[0]), int(shape[1])) for shape in org_shape.tolist()]
|
|
172
|
+
postprocessor = cast(YOLODetectionPostBase, model.postprocessor)
|
|
173
|
+
_, boxes_list, scores_list = postprocessor.nmsout2eval(
|
|
174
|
+
nms_outs.output,
|
|
175
|
+
input_shape,
|
|
176
|
+
img0_shapes,
|
|
177
|
+
ratio_pad=ratio_pad,
|
|
178
|
+
)
|
|
179
|
+
batch_lengths = {
|
|
180
|
+
"input batch": int(input_npu.shape[0]),
|
|
181
|
+
"original shapes": len(org_shape),
|
|
182
|
+
"ratio pads": len(ratio_pad),
|
|
183
|
+
"target classes": len(target_classes),
|
|
184
|
+
"file names": len(fnames),
|
|
185
|
+
"boxes": len(boxes_list),
|
|
186
|
+
"scores": len(scores_list),
|
|
187
|
+
}
|
|
188
|
+
if len(set(batch_lengths.values())) != 1:
|
|
189
|
+
details = ", ".join(
|
|
190
|
+
f"{name}={length}" for name, length in batch_lengths.items()
|
|
191
|
+
)
|
|
192
|
+
raise ValueError(f"WiderFace evaluation batch length mismatch: {details}.")
|
|
193
|
+
|
|
194
|
+
for event_name, file_name, boxes, scores in zip(
|
|
195
|
+
target_classes, fnames, boxes_list, scores_list, strict=True
|
|
196
|
+
):
|
|
197
|
+
predictions[event_name][os.path.splitext(file_name)[0]] = (
|
|
198
|
+
_boxes_scores_to_prediction(boxes, scores)
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
pbar.set_postfix_str(f"NPU FPS: {cum_num_data / inference_time:.3f}")
|
|
202
|
+
|
|
203
|
+
pbar.close()
|
|
204
|
+
aps = evaluation(norm_score(predictions), data_path)
|
|
205
|
+
print("WiderFace evaluation completed")
|
|
206
|
+
return WiderFaceResult(*aps)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def bbox_overlaps(boxes: np.ndarray, query_boxes: np.ndarray) -> np.ndarray:
|
|
210
|
+
"""Compute pairwise IoU overlaps between boxes and query boxes."""
|
|
211
|
+
|
|
212
|
+
boxes = boxes.astype(np.float32)
|
|
213
|
+
query_boxes = query_boxes.astype(np.float32)
|
|
214
|
+
|
|
215
|
+
boxes = boxes[:, None, :]
|
|
216
|
+
query_boxes = query_boxes[None, :, :]
|
|
217
|
+
|
|
218
|
+
iw = (
|
|
219
|
+
np.minimum(boxes[..., 2], query_boxes[..., 2])
|
|
220
|
+
- np.maximum(boxes[..., 0], query_boxes[..., 0])
|
|
221
|
+
+ 1
|
|
222
|
+
)
|
|
223
|
+
ih = (
|
|
224
|
+
np.minimum(boxes[..., 3], query_boxes[..., 3])
|
|
225
|
+
- np.maximum(boxes[..., 1], query_boxes[..., 1])
|
|
226
|
+
+ 1
|
|
227
|
+
)
|
|
228
|
+
iw = np.maximum(iw, 0)
|
|
229
|
+
ih = np.maximum(ih, 0)
|
|
230
|
+
inter = iw * ih
|
|
231
|
+
|
|
232
|
+
box_area = (boxes[..., 2] - boxes[..., 0] + 1) * (boxes[..., 3] - boxes[..., 1] + 1)
|
|
233
|
+
query_area = (query_boxes[..., 2] - query_boxes[..., 0] + 1) * (
|
|
234
|
+
query_boxes[..., 3] - query_boxes[..., 1] + 1
|
|
235
|
+
)
|
|
236
|
+
union = box_area + query_area - inter
|
|
237
|
+
|
|
238
|
+
return inter / union
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_gt_boxes(gt_dir: str) -> tuple[Any, ...]:
|
|
242
|
+
"""Load WiderFace evaluation `.mat` files from the organized dataset."""
|
|
243
|
+
|
|
244
|
+
gt_mat = loadmat(os.path.join(gt_dir, "wider_face_val.mat"))
|
|
245
|
+
hard_mat = loadmat(os.path.join(gt_dir, "wider_hard_val.mat"))
|
|
246
|
+
medium_mat = loadmat(os.path.join(gt_dir, "wider_medium_val.mat"))
|
|
247
|
+
easy_mat = loadmat(os.path.join(gt_dir, "wider_easy_val.mat"))
|
|
248
|
+
|
|
249
|
+
facebox_list = gt_mat["face_bbx_list"]
|
|
250
|
+
event_list = gt_mat["event_list"]
|
|
251
|
+
file_list = gt_mat["file_list"]
|
|
252
|
+
hard_gt_list = hard_mat["gt_list"]
|
|
253
|
+
medium_gt_list = medium_mat["gt_list"]
|
|
254
|
+
easy_gt_list = easy_mat["gt_list"]
|
|
255
|
+
|
|
256
|
+
return (
|
|
257
|
+
facebox_list,
|
|
258
|
+
event_list,
|
|
259
|
+
file_list,
|
|
260
|
+
hard_gt_list,
|
|
261
|
+
medium_gt_list,
|
|
262
|
+
easy_gt_list,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def norm_score(pred: dict[str, Any]) -> dict[str, Any]:
|
|
267
|
+
"""Normalize WiderFace prediction scores to ``[0, 1]``."""
|
|
268
|
+
|
|
269
|
+
max_score = -1e9
|
|
270
|
+
min_score = 1e9
|
|
271
|
+
found = False
|
|
272
|
+
|
|
273
|
+
for _, event_predictions in pred.items():
|
|
274
|
+
for _, image_predictions in event_predictions.items():
|
|
275
|
+
if len(image_predictions) == 0:
|
|
276
|
+
continue
|
|
277
|
+
found = True
|
|
278
|
+
_min = float(np.min(image_predictions[:, -1]))
|
|
279
|
+
_max = float(np.max(image_predictions[:, -1]))
|
|
280
|
+
if _max > max_score:
|
|
281
|
+
max_score = _max
|
|
282
|
+
if _min < min_score:
|
|
283
|
+
min_score = _min
|
|
284
|
+
|
|
285
|
+
if not found:
|
|
286
|
+
return pred
|
|
287
|
+
|
|
288
|
+
diff = max_score - min_score
|
|
289
|
+
if diff <= 0:
|
|
290
|
+
return pred
|
|
291
|
+
|
|
292
|
+
for _, event_predictions in pred.items():
|
|
293
|
+
for _, image_predictions in event_predictions.items():
|
|
294
|
+
if len(image_predictions) == 0:
|
|
295
|
+
continue
|
|
296
|
+
image_predictions[:, -1] = (image_predictions[:, -1] - min_score) / diff
|
|
297
|
+
|
|
298
|
+
return pred
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def image_eval(
|
|
302
|
+
pred: np.ndarray, gt: np.ndarray, ignore: np.ndarray, iou_thresh: float
|
|
303
|
+
) -> tuple[np.ndarray, np.ndarray]:
|
|
304
|
+
"""Evaluate one image worth of WiderFace predictions."""
|
|
305
|
+
|
|
306
|
+
_pred = pred.copy()
|
|
307
|
+
_gt = gt.copy()
|
|
308
|
+
pred_recall = np.zeros(_pred.shape[0])
|
|
309
|
+
recall_list = np.zeros(_gt.shape[0])
|
|
310
|
+
proposal_list = np.ones(_pred.shape[0])
|
|
311
|
+
|
|
312
|
+
_pred[:, 2] = _pred[:, 2] + _pred[:, 0]
|
|
313
|
+
_pred[:, 3] = _pred[:, 3] + _pred[:, 1]
|
|
314
|
+
_gt[:, 2] = _gt[:, 2] + _gt[:, 0]
|
|
315
|
+
_gt[:, 3] = _gt[:, 3] + _gt[:, 1]
|
|
316
|
+
|
|
317
|
+
overlaps = bbox_overlaps(_pred[:, :4], _gt)
|
|
318
|
+
|
|
319
|
+
for prediction_index in range(_pred.shape[0]):
|
|
320
|
+
gt_overlap = overlaps[prediction_index]
|
|
321
|
+
max_overlap = np.max(gt_overlap)
|
|
322
|
+
max_idx = np.argmax(gt_overlap)
|
|
323
|
+
if max_overlap >= iou_thresh:
|
|
324
|
+
if ignore[max_idx] == 0:
|
|
325
|
+
recall_list[max_idx] = -1
|
|
326
|
+
proposal_list[prediction_index] = -1
|
|
327
|
+
elif recall_list[max_idx] == 0:
|
|
328
|
+
recall_list[max_idx] = 1
|
|
329
|
+
|
|
330
|
+
r_keep_index = np.where(recall_list == 1)[0]
|
|
331
|
+
pred_recall[prediction_index] = len(r_keep_index)
|
|
332
|
+
return pred_recall, proposal_list
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def img_pr_info(
|
|
336
|
+
thresh_num: int,
|
|
337
|
+
pred_info: np.ndarray,
|
|
338
|
+
proposal_list: np.ndarray,
|
|
339
|
+
pred_recall: np.ndarray,
|
|
340
|
+
) -> np.ndarray:
|
|
341
|
+
"""Compute precision and recall contributions for one image."""
|
|
342
|
+
|
|
343
|
+
pr_info = np.zeros((thresh_num, 2), dtype=np.float32)
|
|
344
|
+
for threshold_index in range(thresh_num):
|
|
345
|
+
thresh = 1 - (threshold_index + 1) / thresh_num
|
|
346
|
+
recall_index = np.where(pred_info[:, 4] >= thresh)[0]
|
|
347
|
+
if len(recall_index) == 0:
|
|
348
|
+
pr_info[threshold_index, 0] = 0
|
|
349
|
+
pr_info[threshold_index, 1] = 0
|
|
350
|
+
else:
|
|
351
|
+
last_index = recall_index[-1]
|
|
352
|
+
proposal_index = np.where(proposal_list[: last_index + 1] == 1)[0]
|
|
353
|
+
pr_info[threshold_index, 0] = len(proposal_index)
|
|
354
|
+
pr_info[threshold_index, 1] = pred_recall[last_index]
|
|
355
|
+
return pr_info
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def dataset_pr_info(
|
|
359
|
+
thresh_num: int, pr_curve: np.ndarray, count_face: int
|
|
360
|
+
) -> np.ndarray:
|
|
361
|
+
"""Normalize a WiderFace precision-recall accumulator."""
|
|
362
|
+
|
|
363
|
+
_pr_curve = np.zeros((thresh_num, 2), dtype=np.float32)
|
|
364
|
+
for threshold_index in range(thresh_num):
|
|
365
|
+
proposals = pr_curve[threshold_index, 0]
|
|
366
|
+
matched = pr_curve[threshold_index, 1]
|
|
367
|
+
_pr_curve[threshold_index, 0] = matched / proposals if proposals > 0 else 0.0
|
|
368
|
+
_pr_curve[threshold_index, 1] = matched / count_face if count_face > 0 else 0.0
|
|
369
|
+
return _pr_curve
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def voc_ap(rec: np.ndarray, prec: np.ndarray) -> float:
|
|
373
|
+
"""Compute VOC-style average precision."""
|
|
374
|
+
|
|
375
|
+
mrec = np.concatenate((np.array([0.0]), rec, np.array([1.0])))
|
|
376
|
+
mpre = np.concatenate((np.array([0.0]), prec, np.array([0.0])))
|
|
377
|
+
|
|
378
|
+
for index in range(mpre.size - 1, 0, -1):
|
|
379
|
+
mpre[index - 1] = np.maximum(mpre[index - 1], mpre[index])
|
|
380
|
+
|
|
381
|
+
recall_change_index = np.where(mrec[1:] != mrec[:-1])[0]
|
|
382
|
+
ap = np.sum(
|
|
383
|
+
(mrec[recall_change_index + 1] - mrec[recall_change_index])
|
|
384
|
+
* mpre[recall_change_index + 1]
|
|
385
|
+
)
|
|
386
|
+
return float(ap)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def evaluation(
|
|
390
|
+
pred: dict[str, Any], gt_path: str, iou_thresh: float = 0.5
|
|
391
|
+
) -> list[float]:
|
|
392
|
+
"""Evaluate WiderFace predictions against Easy, Medium, and Hard settings."""
|
|
393
|
+
|
|
394
|
+
facebox_list, event_list, file_list, hard_gt_list, medium_gt_list, easy_gt_list = (
|
|
395
|
+
get_gt_boxes(gt_path)
|
|
396
|
+
)
|
|
397
|
+
event_num = len(event_list)
|
|
398
|
+
thresh_num = 1000
|
|
399
|
+
settings = ["easy", "medium", "hard"]
|
|
400
|
+
setting_gts = [easy_gt_list, medium_gt_list, hard_gt_list]
|
|
401
|
+
aps = []
|
|
402
|
+
for setting_id in range(3):
|
|
403
|
+
gt_list = setting_gts[setting_id]
|
|
404
|
+
count_face = 0
|
|
405
|
+
pr_curve = np.zeros((thresh_num, 2), dtype=np.float32)
|
|
406
|
+
pbar = tqdm(range(event_num))
|
|
407
|
+
for event_index in pbar:
|
|
408
|
+
pbar.set_description(f"Processing {settings[setting_id]}")
|
|
409
|
+
event_name = str(event_list[event_index][0][0])
|
|
410
|
+
img_list = file_list[event_index][0]
|
|
411
|
+
pred_list = pred[event_name]
|
|
412
|
+
sub_gt_list = gt_list[event_index][0]
|
|
413
|
+
gt_bbx_list = facebox_list[event_index][0]
|
|
414
|
+
for image_index, img_info in enumerate(img_list):
|
|
415
|
+
pred_info = pred_list[str(img_info[0][0])]
|
|
416
|
+
gt_boxes = np.array(gt_bbx_list[image_index][0], dtype=np.float32)
|
|
417
|
+
keep_index = np.array(sub_gt_list[image_index][0], dtype=np.int64)
|
|
418
|
+
count_face += len(keep_index)
|
|
419
|
+
|
|
420
|
+
if len(gt_boxes) == 0 or len(pred_info) == 0:
|
|
421
|
+
continue
|
|
422
|
+
ignore = np.zeros(gt_boxes.shape[0])
|
|
423
|
+
if len(keep_index) != 0:
|
|
424
|
+
ignore[keep_index - 1] = 1
|
|
425
|
+
pred_recall, proposal_list = image_eval(
|
|
426
|
+
pred_info, gt_boxes, ignore, iou_thresh
|
|
427
|
+
)
|
|
428
|
+
pr_curve += img_pr_info(
|
|
429
|
+
thresh_num, pred_info, proposal_list, pred_recall
|
|
430
|
+
)
|
|
431
|
+
pbar.close()
|
|
432
|
+
pr_curve = dataset_pr_info(thresh_num, pr_curve, count_face)
|
|
433
|
+
aps.append(voc_ap(pr_curve[:, 1], pr_curve[:, 0]))
|
|
434
|
+
|
|
435
|
+
print("==================== Results ====================")
|
|
436
|
+
print(f"Easy Val AP: {aps[0]}")
|
|
437
|
+
print(f"Medium Val AP: {aps[1]}")
|
|
438
|
+
print(f"Hard Val AP: {aps[2]}")
|
|
439
|
+
print("=================================================")
|
|
440
|
+
return aps
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Shared forward and inverse geometry for aspect-preserving letterboxing."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TypeAlias
|
|
7
|
+
|
|
8
|
+
RatioPad: TypeAlias = tuple[tuple[float, float], tuple[float, float]]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class LetterBoxGeometry:
|
|
13
|
+
"""Geometry shared by letterbox preprocessing and output restoration."""
|
|
14
|
+
|
|
15
|
+
input_shape: tuple[int, int]
|
|
16
|
+
original_shape: tuple[int, int]
|
|
17
|
+
ratio: float
|
|
18
|
+
resized_shape: tuple[int, int]
|
|
19
|
+
pad: tuple[int, int]
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def from_shapes(
|
|
23
|
+
cls,
|
|
24
|
+
input_shape: tuple[int, int],
|
|
25
|
+
original_shape: tuple[int, int],
|
|
26
|
+
) -> LetterBoxGeometry:
|
|
27
|
+
"""Calculate YOLO-style centered letterbox geometry.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
input_shape: Target shape as ``(height, width)``.
|
|
31
|
+
original_shape: Source shape as ``(height, width)``.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Calculated resize ratio, resized shape, and top-left padding.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
input_height, input_width = input_shape
|
|
38
|
+
original_height, original_width = original_shape
|
|
39
|
+
ratio = min(input_height / original_height, input_width / original_width)
|
|
40
|
+
resized_height = int(round(original_height * ratio))
|
|
41
|
+
resized_width = int(round(original_width * ratio))
|
|
42
|
+
left = int(round((input_width - resized_width) / 2 - 0.1))
|
|
43
|
+
top = int(round((input_height - resized_height) / 2 - 0.1))
|
|
44
|
+
return cls(
|
|
45
|
+
input_shape=input_shape,
|
|
46
|
+
original_shape=original_shape,
|
|
47
|
+
ratio=ratio,
|
|
48
|
+
resized_shape=(resized_height, resized_width),
|
|
49
|
+
pad=(left, top),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def ratio_pad(self) -> RatioPad:
|
|
54
|
+
"""Return metadata consumed by inverse letterbox operations."""
|
|
55
|
+
|
|
56
|
+
return ((self.ratio, self.ratio), self.pad)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def borders(self) -> tuple[int, int, int, int]:
|
|
60
|
+
"""Return OpenCV border widths as ``(top, bottom, left, right)``."""
|
|
61
|
+
|
|
62
|
+
input_height, input_width = self.input_shape
|
|
63
|
+
resized_height, resized_width = self.resized_shape
|
|
64
|
+
left, top = self.pad
|
|
65
|
+
return (
|
|
66
|
+
top,
|
|
67
|
+
input_height - resized_height - top,
|
|
68
|
+
left,
|
|
69
|
+
input_width - resized_width - left,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def crop_bounds(
|
|
73
|
+
self,
|
|
74
|
+
output_shape: tuple[int, int],
|
|
75
|
+
pad: tuple[float, float] | None = None,
|
|
76
|
+
) -> tuple[int, int, int, int]:
|
|
77
|
+
"""Scale inverse-letterbox crop bounds to a dense output shape.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
output_shape: Dense output shape as ``(height, width)``.
|
|
81
|
+
pad: Optional exact top-left padding metadata as ``(x, y)``.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Crop bounds as ``(top, bottom, left, right)``.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
output_height, output_width = output_shape
|
|
88
|
+
input_height, input_width = self.input_shape
|
|
89
|
+
scale_x = output_width / input_width
|
|
90
|
+
scale_y = output_height / input_height
|
|
91
|
+
pad_x, pad_y = self.pad if pad is None else pad
|
|
92
|
+
left = int(round(pad_x * scale_x))
|
|
93
|
+
top = int(round(pad_y * scale_y))
|
|
94
|
+
resized_height, resized_width = self.resized_shape
|
|
95
|
+
right = left + int(round(resized_width * scale_x))
|
|
96
|
+
bottom = top + int(round(resized_height * scale_y))
|
|
97
|
+
return top, bottom, left, right
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def resolve_ratio_pad(
|
|
101
|
+
input_shape: tuple[int, int],
|
|
102
|
+
original_shape: tuple[int, int],
|
|
103
|
+
ratio_pad: RatioPad | None = None,
|
|
104
|
+
) -> RatioPad:
|
|
105
|
+
"""Return supplied letterbox metadata or derive it from image shapes.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
input_shape: Letterboxed shape as ``(height, width)``.
|
|
109
|
+
original_shape: Source shape as ``(height, width)``.
|
|
110
|
+
ratio_pad: Optional metadata recorded during preprocessing.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Resize ratios and top-left padding as ``((ratio_x, ratio_y), (pad_x, pad_y))``.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
if ratio_pad is not None:
|
|
117
|
+
return ratio_pad
|
|
118
|
+
return LetterBoxGeometry.from_shapes(input_shape, original_shape).ratio_pad
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Private helpers shared by dense prediction postprocessors."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import torch
|
|
9
|
+
|
|
10
|
+
from ..letterbox import LetterBoxGeometry, RatioPad, resolve_ratio_pad
|
|
11
|
+
from .common import normalize_ratio_pads
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_letterbox_input_shape(
|
|
15
|
+
pre_cfg: dict[str, Any],
|
|
16
|
+
requirement_name: str,
|
|
17
|
+
size_name: str | None = None,
|
|
18
|
+
) -> tuple[int, int]:
|
|
19
|
+
"""Validate and return a dense task's configured letterbox input shape.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
pre_cfg: Model preprocessing configuration.
|
|
23
|
+
requirement_name: Task name used when LetterBox is absent.
|
|
24
|
+
size_name: Optional shorter name used for invalid-size errors.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Configured input height and width.
|
|
28
|
+
|
|
29
|
+
Raises:
|
|
30
|
+
ValueError: If LetterBox or its two-item image size is missing or invalid.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
letterbox_cfg = pre_cfg.get("LetterBox")
|
|
34
|
+
if not isinstance(letterbox_cfg, dict) or "img_size" not in letterbox_cfg:
|
|
35
|
+
raise ValueError(
|
|
36
|
+
f"{requirement_name} requires a LetterBox configuration in pre_cfg."
|
|
37
|
+
)
|
|
38
|
+
image_size = letterbox_cfg["img_size"]
|
|
39
|
+
if not isinstance(image_size, list) or len(image_size) != 2:
|
|
40
|
+
raise ValueError(
|
|
41
|
+
f"{size_name or requirement_name} LetterBox img_size must be a two-item [height, width] list."
|
|
42
|
+
)
|
|
43
|
+
return int(image_size[0]), int(image_size[1])
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def resolve_ratio_pads(
|
|
47
|
+
ratio_pad: RatioPad | Sequence[RatioPad | None] | None,
|
|
48
|
+
batch_size: int,
|
|
49
|
+
shapes: Sequence[tuple[int, int]],
|
|
50
|
+
input_shape: tuple[int, int],
|
|
51
|
+
) -> list[RatioPad]:
|
|
52
|
+
"""Normalize letterbox metadata and derive values missing from a dense task batch.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
ratio_pad: Shared or per-image letterbox metadata.
|
|
56
|
+
batch_size: Number of images in the output batch.
|
|
57
|
+
shapes: Original image shapes.
|
|
58
|
+
input_shape: Configured model input shape.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
One resolved ratio/padding pair per batch item.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ValueError: If ratio/padding metadata is invalid for the batch.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
pads = normalize_ratio_pads(ratio_pad, batch_size)
|
|
68
|
+
return [
|
|
69
|
+
resolve_ratio_pad(input_shape, shape, pad) for pad, shape in zip(pads, shapes)
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def crop_letterbox(
|
|
74
|
+
output: torch.Tensor,
|
|
75
|
+
shape: tuple[int, int],
|
|
76
|
+
ratio_pad: RatioPad,
|
|
77
|
+
input_shape: tuple[int, int],
|
|
78
|
+
task_name: str,
|
|
79
|
+
) -> torch.Tensor:
|
|
80
|
+
"""Crop letterbox padding from a dense two-dimensional output.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
output: Dense two-dimensional model output.
|
|
84
|
+
shape: Original image height and width.
|
|
85
|
+
ratio_pad: Resize ratio and padding applied during preprocessing.
|
|
86
|
+
input_shape: Configured model input height and width.
|
|
87
|
+
task_name: Task label used in validation errors.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Output with letterbox padding removed.
|
|
91
|
+
|
|
92
|
+
Raises:
|
|
93
|
+
ValueError: If inverse letterboxing produces an empty crop.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
geometry = LetterBoxGeometry.from_shapes(input_shape, shape)
|
|
97
|
+
output_shape = (int(output.shape[0]), int(output.shape[1]))
|
|
98
|
+
top, bottom, left, right = geometry.crop_bounds(output_shape, pad=ratio_pad[1])
|
|
99
|
+
cropped = output[top:bottom, left:right]
|
|
100
|
+
if cropped.numel() == 0:
|
|
101
|
+
raise ValueError(f"{task_name} letterbox restoration produced an empty crop.")
|
|
102
|
+
return cropped
|