stabilo-benchmark 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. stabilo_benchmark/__init__.py +8 -0
  2. stabilo_benchmark/__main__.py +15 -0
  3. stabilo_benchmark/annotation.py +72 -0
  4. stabilo_benchmark/cfg/pipelines.yaml +131 -0
  5. stabilo_benchmark/cli.py +715 -0
  6. stabilo_benchmark/config.py +391 -0
  7. stabilo_benchmark/datasets.py +322 -0
  8. stabilo_benchmark/environment.py +129 -0
  9. stabilo_benchmark/gcp.py +539 -0
  10. stabilo_benchmark/masking.py +458 -0
  11. stabilo_benchmark/metrics/__init__.py +59 -0
  12. stabilo_benchmark/metrics/diagnostics.py +222 -0
  13. stabilo_benchmark/metrics/geometric.py +321 -0
  14. stabilo_benchmark/metrics/photometric.py +196 -0
  15. stabilo_benchmark/oracle.py +188 -0
  16. stabilo_benchmark/perturbations.py +259 -0
  17. stabilo_benchmark/pipelines.py +333 -0
  18. stabilo_benchmark/regions.py +396 -0
  19. stabilo_benchmark/report/__init__.py +35 -0
  20. stabilo_benchmark/report/annotate_gcp.py +932 -0
  21. stabilo_benchmark/report/audit_figure.py +612 -0
  22. stabilo_benchmark/report/build.py +1859 -0
  23. stabilo_benchmark/report/capture.py +1082 -0
  24. stabilo_benchmark/report/case_figure.py +222 -0
  25. stabilo_benchmark/report/contrasts.py +696 -0
  26. stabilo_benchmark/report/figures.py +999 -0
  27. stabilo_benchmark/report/margin.py +253 -0
  28. stabilo_benchmark/report/names.py +61 -0
  29. stabilo_benchmark/report/repeats.py +105 -0
  30. stabilo_benchmark/report/scenes.py +94 -0
  31. stabilo_benchmark/report/survey_cases.py +155 -0
  32. stabilo_benchmark/report/tables.py +1824 -0
  33. stabilo_benchmark/report/trial_figure.py +399 -0
  34. stabilo_benchmark/resources.py +153 -0
  35. stabilo_benchmark/results.py +494 -0
  36. stabilo_benchmark/runners/__init__.py +5 -0
  37. stabilo_benchmark/runners/audit.py +461 -0
  38. stabilo_benchmark/runners/dynamic.py +957 -0
  39. stabilo_benchmark/runners/fetch.py +595 -0
  40. stabilo_benchmark/runners/prepare.py +430 -0
  41. stabilo_benchmark/runners/static.py +466 -0
  42. stabilo_benchmark/runners/survey.py +811 -0
  43. stabilo_benchmark/sampling.py +286 -0
  44. stabilo_benchmark/scene.py +393 -0
  45. stabilo_benchmark/seeding.py +47 -0
  46. stabilo_benchmark/stats.py +293 -0
  47. stabilo_benchmark/trial_cache.py +166 -0
  48. stabilo_benchmark-1.0.0.dist-info/METADATA +747 -0
  49. stabilo_benchmark-1.0.0.dist-info/RECORD +53 -0
  50. stabilo_benchmark-1.0.0.dist-info/WHEEL +5 -0
  51. stabilo_benchmark-1.0.0.dist-info/entry_points.txt +2 -0
  52. stabilo_benchmark-1.0.0.dist-info/licenses/LICENSE +21 -0
  53. stabilo_benchmark-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Author: Robert Fonod (robert.fonod@ieee.org)
4
+
5
+ """Stabilo Benchmark - reproducible benchmarks for reference-based UAV video stabilization."""
6
+
7
+ __version__ = '1.0.0'
8
+ __all__ = ['__version__']
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Author: Robert Fonod (robert.fonod@ieee.org)
4
+
5
+ """Allow `python -m stabilo_benchmark <command>` to behave like the console script."""
6
+
7
+ import sys
8
+
9
+ from stabilo_benchmark.cli import main
10
+
11
+ if __name__ == '__main__':
12
+ # sys.exit, not a bare call: the console-script wrapper setuptools generates exits with
13
+ # main()'s return value, and `python -m` must agree with it. Discarding it made every
14
+ # invocation succeed, so a scripted campaign would run on past a failed stage.
15
+ sys.exit(main())
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Author: Robert Fonod (robert.fonod@ieee.org)
4
+
5
+ """
6
+ annotation.py - The two hbb2obb commands that annotate an image directory.
7
+
8
+ <root>/
9
+ images/ the frames
10
+ labels_hbb/ hbb2obb-detect: horizontal boxes, absolute pixels
11
+ labels_obb/ hbb2obb: oriented boxes, one per horizontal box, same order
12
+ labels_confidence/ hbb2obb: per-box conversion score (0.0 marks an HBB fallback)
13
+ PROVENANCE_hbb.txt hbb2obb-detect: command, settings, checkpoint SHA-256
14
+ PROVENANCE_obb.txt hbb2obb: the same for the conversion
15
+
16
+ The detector is hbb2obb's registered `geotrax` model; the conversion settings are those selected
17
+ for Songdo Vision OBB. The README prints the same two commands, and `tests/test_samples.py`
18
+ checks that they match.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import shutil
24
+ import subprocess
25
+ import sys
26
+ from pathlib import Path
27
+ from typing import List, Optional
28
+
29
+ DETECT_ARGS = ['--model', 'geotrax', '--no_confidence', '--save_provenance']
30
+ # fmt: off
31
+ CONVERT_ARGS = [
32
+ '--sam_models', 'sam_l',
33
+ '--imgsz', '1024',
34
+ '--scale_factors', '0.02',
35
+ '--opening_kernel_percentage', '-0.1',
36
+ '--fragment_ratio', '0.1',
37
+ '--confidence_dir',
38
+ '--save_provenance',
39
+ ]
40
+ # fmt: on
41
+
42
+
43
+ class AnnotationError(RuntimeError):
44
+ """Raised when an hbb2obb command is missing or fails."""
45
+
46
+
47
+ def commands(images_dir: Path, device: Optional[str] = None, overwrite: bool = False) -> List[List[str]]:
48
+ """The hbb2obb-detect and hbb2obb command lines for an image directory."""
49
+ device_args = ['--device', str(device)] if device else []
50
+ detect = ['hbb2obb-detect', str(images_dir), *DETECT_ARGS, *device_args, *(['--overwrite'] if overwrite else [])]
51
+ convert = ['hbb2obb', str(images_dir), *CONVERT_ARGS, *device_args]
52
+ return [detect, convert]
53
+
54
+
55
+ def annotate(images_dir: Path, device: Optional[str] = None, overwrite: bool = False) -> None:
56
+ """Run both commands; labels land beside `images_dir`."""
57
+ for command in commands(Path(images_dir), device=device, overwrite=overwrite):
58
+ executable = _executable(command[0])
59
+ result = subprocess.run([executable, *command[1:]], check=False)
60
+ if result.returncode != 0:
61
+ raise AnnotationError(f"{' '.join(command)} exited with status {result.returncode}")
62
+
63
+
64
+ def _executable(name: str) -> str:
65
+ """The console script beside this interpreter first, so an unactivated venv still finds it."""
66
+ beside = Path(sys.executable).parent / name
67
+ if beside.is_file():
68
+ return str(beside)
69
+ found = shutil.which(name)
70
+ if found is None:
71
+ raise AnnotationError(f"'{name}' was not found. It is installed with hbb2obb: pip install hbb2obb")
72
+ return found
@@ -0,0 +1,131 @@
1
+ # =============================================================================
2
+ # stabilo-benchmark - named registration pipeline presets
3
+ # =============================================================================
4
+ # Each entry is a partial set of stabilo `Stabilizer` keyword arguments; keys absent from
5
+ # stabilo's cfg/default.yaml are rejected by `pipelines.validate_spec`.
6
+ #
7
+ # `masking` (none | hbb | obb) is an experiment-config axis, and `mask_use` is derived from it;
8
+ # neither is set here.
9
+ #
10
+ # `extends: <name>` inherits from another preset; keys given locally win.
11
+ #
12
+ # `filter_ratio` and `ransac_epipolar_threshold` of each benchmarked preset are its mAA-optimal point
13
+ # in configs/songdo/static/tuning.yaml, on the tuning scenes. LightGlue and LoFTR do not apply the ratio
14
+ # test, so only the threshold is set for them.
15
+ # =============================================================================
16
+
17
+ # -----------------------------------------------------------------------------
18
+ # Shared baseline; every preset inherits from it.
19
+ # -----------------------------------------------------------------------------
20
+ base:
21
+ matcher_name: bf
22
+ filter_type: ratio
23
+ filter_ratio: 0.9
24
+ transformation_type: projective
25
+ ransac_method: 38 # MAGSAC++
26
+ ransac_epipolar_threshold: 2.0
27
+ ransac_max_iter: 5000
28
+ ransac_confidence: 0.999999
29
+ clahe: false
30
+ downsample_ratio: 1.0 # matched operating point, from configs/songdo/static/budget.yaml
31
+ max_features: 8000
32
+ ref_multiplier: 2.0
33
+ mask_margin_ratio: 0.15
34
+
35
+ # -----------------------------------------------------------------------------
36
+ # Classical detectors (OpenCV).
37
+ # -----------------------------------------------------------------------------
38
+ orb:
39
+ extends: base
40
+ detector_name: orb
41
+ filter_ratio: 0.85
42
+ ransac_epipolar_threshold: 4.0
43
+
44
+ sift:
45
+ extends: base
46
+ detector_name: sift
47
+ filter_ratio: 0.7
48
+ ransac_epipolar_threshold: 0.5
49
+
50
+ rsift:
51
+ extends: base
52
+ detector_name: rsift
53
+ filter_ratio: 0.7
54
+ ransac_epipolar_threshold: 0.5
55
+
56
+ brisk:
57
+ extends: base
58
+ detector_name: brisk
59
+ filter_ratio: 0.7
60
+ ransac_epipolar_threshold: 1.5
61
+
62
+ kaze:
63
+ extends: base
64
+ detector_name: kaze
65
+ filter_ratio: 0.7
66
+ ransac_epipolar_threshold: 0.5
67
+
68
+ akaze:
69
+ extends: base
70
+ detector_name: akaze
71
+ filter_ratio: 0.7
72
+ ransac_epipolar_threshold: 4.0
73
+
74
+ # -----------------------------------------------------------------------------
75
+ # Learning-based detectors / matchers (kornia, via stabilo >= 1.4.0).
76
+ #
77
+ # `pipelines.check_resolution` warns when a preset exceeds Stabilizer.DL_PIXEL_BUDGETS; a
78
+ # configuration the machine cannot hold is recorded as infeasible and reported as N/A.
79
+ #
80
+ # xfeat / disk / dedode / loftr are upright models: matching degrades past roughly 30 degrees of
81
+ # in-plane rotation. keynet estimates keypoint orientation.
82
+ #
83
+ # lightglue accepts only the detectors in Stabilizer.LIGHTGLUE_FEATURE_NAMES (disk, dedode,
84
+ # keynet), not xfeat.
85
+ # -----------------------------------------------------------------------------
86
+ xfeat:
87
+ extends: base
88
+ detector_name: xfeat
89
+ matcher_name: bf
90
+ filter_ratio: 0.7
91
+ ransac_epipolar_threshold: 2.0
92
+
93
+ disk_lightglue:
94
+ extends: base
95
+ detector_name: disk
96
+ matcher_name: lightglue
97
+ ransac_epipolar_threshold: 2.0
98
+
99
+ dedode_lightglue:
100
+ extends: base
101
+ detector_name: dedode
102
+ matcher_name: lightglue
103
+ ransac_epipolar_threshold: 1.0
104
+ dedode_detector_weights: L-C4-v2
105
+ dedode_descriptor_weights: B-upright
106
+
107
+ keynet_lightglue:
108
+ extends: base
109
+ detector_name: keynet
110
+ matcher_name: lightglue
111
+ ransac_epipolar_threshold: 4.0
112
+
113
+ loftr:
114
+ extends: base
115
+ detector_name: loftr # detector-free: matcher_name / filter_type are ignored
116
+ loftr_weights: outdoor
117
+ loftr_confidence: 0.0
118
+
119
+ # -----------------------------------------------------------------------------
120
+ # Reference estimator (pseudo-ground truth) for the dynamic benchmark: the sift preset with its
121
+ # tuned ratio test and inlier threshold, at full resolution with a larger feature budget and a
122
+ # stricter estimator. Its error is bounded by `stabilo-benchmark audit`.
123
+ # -----------------------------------------------------------------------------
124
+ oracle:
125
+ extends: sift
126
+ downsample_ratio: 1.0
127
+ max_features: 20000
128
+ ref_multiplier: 2.0
129
+ ransac_max_iter: 20000
130
+ ransac_confidence: 0.9999999
131
+ mask_margin_ratio: 0.20