euler-eval 2.30.0__tar.gz → 2.32.0__tar.gz
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.
- {euler_eval-2.30.0/euler_eval.egg-info → euler_eval-2.32.0}/PKG-INFO +8 -5
- {euler_eval-2.30.0 → euler_eval-2.32.0}/README.md +6 -3
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/README.md +1 -1
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/alignment.md +2 -1
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/cli.md +20 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/configuration.md +83 -19
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/metrics.md +82 -0
- euler_eval-2.32.0/docs/output.md +342 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/cli.py +667 -125
- euler_eval-2.32.0/euler_eval/config_paths.py +258 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/data.py +72 -46
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/evaluate.py +359 -11
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/__init__.py +18 -0
- euler_eval-2.32.0/euler_eval/metrics/sky_iou.py +167 -0
- euler_eval-2.32.0/euler_eval/protocol.py +145 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0/euler_eval.egg-info}/PKG-INFO +8 -5
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval.egg-info/SOURCES.txt +8 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval.egg-info/requires.txt +1 -1
- {euler_eval-2.30.0 → euler_eval-2.32.0}/pyproject.toml +2 -2
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/conftest.py +2 -2
- euler_eval-2.32.0/tests/eval_output.py +16 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_cli_sparse_outputs.py +20 -7
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_config.py +148 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_data_builders.py +10 -5
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_depth_alignment_output.py +2 -1
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_evaluate_helpers.py +20 -6
- euler_eval-2.32.0/tests/test_mask_sky_pairing.py +197 -0
- euler_eval-2.32.0/tests/test_mask_sky_prediction.py +239 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_points_3d_sparse.py +8 -8
- euler_eval-2.32.0/tests/test_protocol.py +398 -0
- euler_eval-2.32.0/tests/test_save_results.py +513 -0
- euler_eval-2.32.0/tests/test_sky_iou.py +550 -0
- euler_eval-2.32.0/tests/test_sky_iou_cli.py +498 -0
- euler_eval-2.30.0/docs/output.md +0 -160
- euler_eval-2.30.0/euler_eval/config_paths.py +0 -127
- euler_eval-2.30.0/tests/test_save_results.py +0 -301
- {euler_eval-2.30.0 → euler_eval-2.32.0}/LICENSE +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/MANIFEST.in +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/distributions.md +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/feature-request-unified-evaluation-framework.md +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/docs/validation.md +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/THIRD_PARTY_NOTICES.md +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/__init__.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/calibration.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/distribution_contract.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/distributions.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metric_sets.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/_natural_scene_models.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/absrel.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/daniel_error.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/depth_binned_error.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/depth_edge_f1.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/depth_standard.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/fade.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/fid_kid.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/gpu_depth_batch.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/gpu_image_batch.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/high_freq_energy.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/lpips_metric.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/niqe.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/normal_consistency.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/points3d_cloud.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/points3d_decomposition.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/points3d_distance.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/points3d_geometry.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/psnr.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/rgb_edge_f1.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/rgb_lpips.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/rgb_psnr_ssim.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/rho_a.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/rmse.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/scale_invariant_log.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/ssim.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/tail_errors.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/metrics/utils.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/sanity_checker.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/schemas/distribution-v1.schema.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/utils/hierarchy_parser.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval/validation.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval.egg-info/dependency_links.txt +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval.egg-info/entry_points.txt +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/euler_eval.egg-info/top_level.txt +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/init_cache.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/scripts/generate_distribution_fixtures.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/setup.cfg +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/__init__.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/distribution_contract_utils.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/README.md +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/counts-depth.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/counts-points3d.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/counts-sparsedepth.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/future-sum-by-depth.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/histogram-only.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/per-file-only.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/fixtures/distributions/scalar-only.eval.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/mock_files/calibration_output.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/mock_files/depth_output.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/mock_files/rgb_output.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/mock_files/segmentation_output.json +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_alignment.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_cli_device.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_data.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_depth_standard.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_distribution_contract.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_distributions.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_domain_metrics.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_init_cache.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_integration.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_meta_output.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_metrics_utils.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_normal_consistency.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_points_3d.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_rgb_fid_output.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_rho_a.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_sparse_depth.py +0 -0
- {euler_eval-2.30.0 → euler_eval-2.32.0}/tests/test_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: euler-eval
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.32.0
|
|
4
4
|
Summary: Evaluation toolkit for depth, RGB, ray and 3D point-map predictions
|
|
5
5
|
Author-email: Daniel Rothenpieler <rothenpielerdaniel@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -33,7 +33,7 @@ Requires-Dist: opencv-python-headless>=4.5.0
|
|
|
33
33
|
Requires-Dist: lpips>=0.1.4
|
|
34
34
|
Requires-Dist: torchmetrics>=1.0
|
|
35
35
|
Requires-Dist: tqdm>=4.62.0
|
|
36
|
-
Requires-Dist: euler-loading>=2.
|
|
36
|
+
Requires-Dist: euler-loading>=2.29
|
|
37
37
|
Requires-Dist: ds-crawler>=2.10
|
|
38
38
|
Requires-Dist: euler-metric-naming>=0.2
|
|
39
39
|
Provides-Extra: logging
|
|
@@ -133,8 +133,10 @@ euler-eval config.json --batch-size 32
|
|
|
133
133
|
|
|
134
134
|
Ground truth and prediction files are matched by ID rather than by directory
|
|
135
135
|
order, so an incomplete prediction set scores the frames it does have instead of
|
|
136
|
-
silently comparing the wrong pairs. Results are written
|
|
137
|
-
|
|
136
|
+
silently comparing the wrong pairs. Results are written into each prediction
|
|
137
|
+
dataset, under `.eval/` beside its `.ds_crawler/` metadata — e.g.
|
|
138
|
+
`/data/model_a/depth/.eval/eval.json`, or `.eval/<scope>/eval.json` for a scoped
|
|
139
|
+
dataset ([details](docs/output.md#where-results-land)):
|
|
138
140
|
|
|
139
141
|
```json
|
|
140
142
|
{
|
|
@@ -176,7 +178,8 @@ metric is written under, is in [Metrics](docs/metrics.md).
|
|
|
176
178
|
| **Metadata-driven decoding** | Radial vs planar depth, value ranges, point-cloud column layout and loader choice all come from the dataset index — no per-dataset flags. |
|
|
177
179
|
| **Honest spaces** | Relative models are scored `native` *and* `metric` (after scale/shift or a similarity gauge), so a scale failure never reads as a geometry failure. |
|
|
178
180
|
| **Benchmark depth bins** | `--benchmark-depth-range MIN MAX` adds near/mid/far bins in square-root depth space, additive to the regular metrics. |
|
|
179
|
-
| **Sky masking** | `--mask-sky` drops sky pixels using GT segmentation — from the metrics *and* from the alignment fit. |
|
|
181
|
+
| **Sky masking** | `--mask-sky` drops sky pixels using GT segmentation — from the metrics *and* from the alignment fit. `--mask-sky-prediction` does the same with each prediction's own `sky_mask`. |
|
|
182
|
+
| **Sky IoU** | `--sky-iou` scores predicted sky — a `sky_mask`, or depth reaching a fixed cap — against GT segmentation, without changing any depth metric. |
|
|
180
183
|
| **Per-file + aggregate** | Dataset-level numbers plus per-image metrics in dataset-hierarchy order, in the same file. |
|
|
181
184
|
| **Sanity checks** | Results are validated against configurable thresholds; implausible ranges, degenerate inputs and scale mismatches are reported instead of quietly scored. |
|
|
182
185
|
| **Structured metric names** | Each result carries a `metricSet` envelope declaring its namespace, axes, units and metric directions. |
|
|
@@ -83,8 +83,10 @@ euler-eval config.json --batch-size 32
|
|
|
83
83
|
|
|
84
84
|
Ground truth and prediction files are matched by ID rather than by directory
|
|
85
85
|
order, so an incomplete prediction set scores the frames it does have instead of
|
|
86
|
-
silently comparing the wrong pairs. Results are written
|
|
87
|
-
|
|
86
|
+
silently comparing the wrong pairs. Results are written into each prediction
|
|
87
|
+
dataset, under `.eval/` beside its `.ds_crawler/` metadata — e.g.
|
|
88
|
+
`/data/model_a/depth/.eval/eval.json`, or `.eval/<scope>/eval.json` for a scoped
|
|
89
|
+
dataset ([details](docs/output.md#where-results-land)):
|
|
88
90
|
|
|
89
91
|
```json
|
|
90
92
|
{
|
|
@@ -126,7 +128,8 @@ metric is written under, is in [Metrics](docs/metrics.md).
|
|
|
126
128
|
| **Metadata-driven decoding** | Radial vs planar depth, value ranges, point-cloud column layout and loader choice all come from the dataset index — no per-dataset flags. |
|
|
127
129
|
| **Honest spaces** | Relative models are scored `native` *and* `metric` (after scale/shift or a similarity gauge), so a scale failure never reads as a geometry failure. |
|
|
128
130
|
| **Benchmark depth bins** | `--benchmark-depth-range MIN MAX` adds near/mid/far bins in square-root depth space, additive to the regular metrics. |
|
|
129
|
-
| **Sky masking** | `--mask-sky` drops sky pixels using GT segmentation — from the metrics *and* from the alignment fit. |
|
|
131
|
+
| **Sky masking** | `--mask-sky` drops sky pixels using GT segmentation — from the metrics *and* from the alignment fit. `--mask-sky-prediction` does the same with each prediction's own `sky_mask`. |
|
|
132
|
+
| **Sky IoU** | `--sky-iou` scores predicted sky — a `sky_mask`, or depth reaching a fixed cap — against GT segmentation, without changing any depth metric. |
|
|
130
133
|
| **Per-file + aggregate** | Dataset-level numbers plus per-image metrics in dataset-hierarchy order, in the same file. |
|
|
131
134
|
| **Sanity checks** | Results are validated against configurable thresholds; implausible ranges, degenerate inputs and scale mismatches are reported instead of quietly scored. |
|
|
132
135
|
| **Structured metric names** | Each result carries a `metricSet` envelope declaring its namespace, axes, units and metric directions. |
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| [Spaces & alignment](alignment.md) | Why `native` and `metric` exist, depth affine fitting, points-3d gauge alignment, benchmark depth bins |
|
|
8
8
|
| [Metrics](metrics.md) | The full metric inventory per modality, with the key each one is written under |
|
|
9
9
|
| [Error distributions](distributions.md) | Optional per-sample and pooled RMSE histograms, bin settings, axes and JSON layout |
|
|
10
|
-
| [Results & output](output.md) | Where files land, the anatomy of `eval.json`, per-file metrics, the sanity-check report |
|
|
10
|
+
| [Results & output](output.md) | Where files land, the anatomy of `eval.json`, comparing evaluations, per-file metrics, the sanity-check report |
|
|
11
11
|
| [In-training validation](validation.md) | The programmatic API for scoring in-memory predictions during training |
|
|
12
12
|
|
|
13
13
|
## Proposed features
|
|
@@ -32,7 +32,8 @@ map `d_aligned = s · d_pred + t` by least squares over valid pixels.
|
|
|
32
32
|
|
|
33
33
|
The fit uses pixels where GT and prediction are finite and GT > 0. With
|
|
34
34
|
`--mask-sky`, sky pixels are excluded and the fit is trimmed to `gt ≤ P95(gt)`
|
|
35
|
-
so residual sky outliers do not dominate.
|
|
35
|
+
so residual sky outliers do not dominate. Pixels in a prediction's `sky_mask`
|
|
36
|
+
are excluded from the fit with `--sky-depth` or `--mask-sky-prediction`.
|
|
36
37
|
|
|
37
38
|
Declaring the prediction with the `relative_depth` or `affine_depth` config key
|
|
38
39
|
(instead of `depth`) tells the evaluator the model is not metric, so
|
|
@@ -23,7 +23,9 @@ validation exits with status `1` before any dataset is opened.
|
|
|
23
23
|
| `--skip-rays` | flag | off | Skip rays (spherical direction map) evaluation |
|
|
24
24
|
| `--skip-points-3d` | flag | off | Skip points_3d (per-pixel 3D point map) evaluation |
|
|
25
25
|
| `--mask-sky` | flag | off | Mask sky regions from metrics using GT segmentation |
|
|
26
|
+
| `--mask-sky-prediction` | flag | off | Exclude pixels in a prediction's `datasets[].sky_mask` from dense and sparse depth metrics and the alignment fit; predictions without a `sky_mask` are scored in full ([details](configuration.md#masking-predicted-sky)) |
|
|
26
27
|
| `--sky-depth` | `float` | none | Cap GT and predicted depths in meters and fill predicted `sky_mask` pixels with this value; must be finite and positive |
|
|
28
|
+
| `--sky-iou` | flag | off | Score predicted sky against GT segmentation sky: IoU, precision and recall for the `explicit` (`datasets[].sky_mask`) and `implicit` (`depth >= --sky-depth`, metric predictions only) variants. Requires `gt.segmentation`; depth metrics are unchanged ([details](metrics.md#sky-segmentation)) |
|
|
27
29
|
| `--no-sanity-check` | flag | off | Disable sanity checking of metric configurations |
|
|
28
30
|
| `--metrics-config` | `str` | auto-detect | Path to `metrics_config.json` for sanity checking |
|
|
29
31
|
| `--depth-alignment` | `{none,auto_affine,affine}` | `auto_affine` | Depth calibration mode ([details](alignment.md#depth-alignment)) |
|
|
@@ -35,6 +37,7 @@ validation exits with status `1` before any dataset is opened.
|
|
|
35
37
|
| `--distribution-bins` | `int` | `50` | Total histogram bins, including tails; minimum 3 |
|
|
36
38
|
| `--distribution-scale` | `{log,linear}` | `log` | Spacing of finite histogram bins |
|
|
37
39
|
| `--distribution-range` | `float float` | `0.001 100` | Finite error range `[MIN, MAX)` in evaluated space units; zero/small-error and overflow bins retain the tails |
|
|
40
|
+
| `--eval-name` | `str` | `eval` | Name this evaluation: results are written as `<name>.json` in each prediction dataset's `.eval/` folder, so differently named runs sit side by side; a dataset's `output_file` still wins ([details](output.md#where-results-land)) |
|
|
38
41
|
|
|
39
42
|
Histogram settings can also be specified in the config's `distributions`
|
|
40
43
|
section. A bin, scale or range flag enables histograms and overrides that
|
|
@@ -54,12 +57,22 @@ euler-eval config.json --batch-size 32
|
|
|
54
57
|
# Sky masking (requires gt.segmentation)
|
|
55
58
|
euler-eval config.json --mask-sky -v
|
|
56
59
|
|
|
60
|
+
# Exclude each prediction's own sky (datasets[].sky_mask) from depth metrics
|
|
61
|
+
euler-eval config.json --mask-sky-prediction
|
|
62
|
+
|
|
57
63
|
# Cap depth at 100 m and fill predicted sky at 100 m (optional datasets[].sky_mask)
|
|
58
64
|
euler-eval config.json --sky-depth 100
|
|
59
65
|
|
|
66
|
+
# Sky IoU: explicit from datasets[].sky_mask, implicit at depth >= 100 m
|
|
67
|
+
# (requires gt.segmentation; the threshold is also the depth cap)
|
|
68
|
+
euler-eval config.json --sky-iou --sky-depth 100
|
|
69
|
+
|
|
60
70
|
# Only depth evaluation
|
|
61
71
|
euler-eval config.json --skip-rgb --skip-rays --skip-points-3d
|
|
62
72
|
|
|
73
|
+
# Keep a sky-masked run beside the default results: .eval/[<scope>/]no_sky.json
|
|
74
|
+
euler-eval config.json --mask-sky --eval-name no_sky
|
|
75
|
+
|
|
63
76
|
# Force affine scale+shift alignment on all depth predictions
|
|
64
77
|
euler-eval config.json --depth-alignment affine
|
|
65
78
|
|
|
@@ -109,6 +122,13 @@ per prediction dataset and modality with the GT and prediction paths, the
|
|
|
109
122
|
resolved modality metadata (such as `radial_depth`), and the number of matched
|
|
110
123
|
pairs.
|
|
111
124
|
|
|
125
|
+
With `--sky-iou`, each depth block ends with one line holding the pooled
|
|
126
|
+
(`pixel_pool`) sky IoU, precision and recall of every computed variant, for
|
|
127
|
+
example `Sky IoU, pixel_pool, 'model': explicit 0.9120 (precision 0.9500,
|
|
128
|
+
recall 0.9580); implicit (depth >= 100 m) 0.4410 (precision 0.9800, recall
|
|
129
|
+
0.4450)`. Skipped variants, GT segmentation without sky and an empty implicit
|
|
130
|
+
sky are reported as warnings above it.
|
|
131
|
+
|
|
112
132
|
A matched-pair count that is much lower than expected is the first sign that GT
|
|
113
133
|
and predictions are not indexed consistently — see
|
|
114
134
|
[Loader resolution & dataset metadata](configuration.md#loader-resolution--dataset-metadata).
|
|
@@ -71,7 +71,8 @@ required.
|
|
|
71
71
|
| `gt.sparse_depth.path` | no\* | Sparse pointcloud GT, `(N,C)` points whose first columns are `x,y,z` in metres |
|
|
72
72
|
| `gt.rays.path` | no\* | GT ray direction map dataset |
|
|
73
73
|
| `gt.points_3d.path` | no\* | GT per-pixel 3D point map `(H,W,3)` in camera-frame metres |
|
|
74
|
-
| `gt.segmentation.path` | no | GT segmentation (needed for `--mask-sky`) |
|
|
74
|
+
| `gt.segmentation.path` | no | GT segmentation (needed for `--mask-sky` and `--sky-iou`); see [GT segmentation](#gt-segmentation) |
|
|
75
|
+
| `gt.semantic_segmentation.path` | no | Alias of `gt.segmentation`; configure only one of the two |
|
|
75
76
|
| `gt.calibration.path` | no | Calibration data (camera intrinsics); enables true camera-frame [surface normals](metrics.md#surface-normals-and-calibration) |
|
|
76
77
|
| `gt.intrinsics.path` | with `gt.sparse_depth` | Camera intrinsics for pointcloud projection |
|
|
77
78
|
| `gt.camera_extrinsics.path` | with `gt.sparse_depth` | Source-to-camera extrinsics (e.g. MUSES `lidar2rgb`) |
|
|
@@ -80,6 +81,35 @@ required.
|
|
|
80
81
|
|
|
81
82
|
\* At least one of the five modality entries must be present.
|
|
82
83
|
|
|
84
|
+
### GT segmentation
|
|
85
|
+
|
|
86
|
+
`gt.segmentation` is the canonical key. `gt.semantic_segmentation` is accepted
|
|
87
|
+
as an alias, for archives whose segmentation scope carries that name (MUSES,
|
|
88
|
+
for example); configuring both keys is an error. The segmentation is read only
|
|
89
|
+
when `--mask-sky` or `--sky-iou` needs it. `--mask-sky` without it warns and
|
|
90
|
+
disables itself, while `--sky-iou` without it exits with an error.
|
|
91
|
+
|
|
92
|
+
The dataset head's loader module must expose a `sky_mask` function, and the
|
|
93
|
+
head must declare the sky label as `skyclass` (euler-loading 2.29 or later).
|
|
94
|
+
euler-eval contains no label IDs.
|
|
95
|
+
|
|
96
|
+
Segmentation is per frame, so it is paired with the evaluated frames by
|
|
97
|
+
hierarchy path and file ID, like depth: its index must use the same folder
|
|
98
|
+
structure and IDs as the frames it masks. A frame without its own segmentation
|
|
99
|
+
file is not evaluated, and the run prints how many pairs the segmentation
|
|
100
|
+
dropped. When segmentation is read only for `--sky-iou`, it must not change
|
|
101
|
+
the evaluated pairs, so a segmentation that lacks frames is not loaded; the run
|
|
102
|
+
warns and the sky IoU is skipped. A segmentation whose IDs match no frame
|
|
103
|
+
stops the run with euler-loading's "No common IDs" error and per-modality file
|
|
104
|
+
counts.
|
|
105
|
+
|
|
106
|
+
The config key is also the default metadata scope. If the path has no
|
|
107
|
+
`#scope=` selector, no root-level metadata, and no scope of that name, the
|
|
108
|
+
scope is chosen among the archive's scopes: the one whose name or
|
|
109
|
+
`dataset-head.json` modality key is `segmentation` or `semantic_segmentation`
|
|
110
|
+
(both names are candidates under either key), or the only scope. If several
|
|
111
|
+
scopes match, or none among several, the run stops and asks for `#scope=`.
|
|
112
|
+
|
|
83
113
|
## `datasets` section
|
|
84
114
|
|
|
85
115
|
Each entry needs a `name` and at least one prediction modality. Use only **one**
|
|
@@ -94,10 +124,10 @@ would be ambiguous.
|
|
|
94
124
|
| `depth.path` | no\* | Predicted dense metric depth; also used against sparse pointcloud GT |
|
|
95
125
|
| `relative_depth.path` | no\* | Predicted dense relative depth (scale/shift alignment supported) |
|
|
96
126
|
| `affine_depth.path` | no\* | Predicted dense affine depth (scale/shift alignment supported) |
|
|
97
|
-
| `sky_mask.path` | no | Auxiliary predicted sky mask for a dense depth entry; used with `--sky-depth` |
|
|
127
|
+
| `sky_mask.path` | no | Auxiliary predicted sky mask for a dense depth entry; used with `--sky-depth`, `--mask-sky-prediction` and `--sky-iou` |
|
|
98
128
|
| `rays.path` | no\* | Predicted ray direction map dataset |
|
|
99
129
|
| `points_3d.path` | no\* | Predicted per-pixel 3D point map `(H,W,3)` |
|
|
100
|
-
| `output_file` | no | Custom results path (default:
|
|
130
|
+
| `output_file` | no | Custom results path for every modality of this entry, replacing the `.eval/` layout and `--eval-name` (default: `.eval/[<scope>/][split_<split>/]eval.json` in each prediction modality's dataset root; see [where results land](output.md#where-results-land)) |
|
|
101
131
|
|
|
102
132
|
\* At least one prediction modality must be present.
|
|
103
133
|
|
|
@@ -123,8 +153,8 @@ The sky mask is paired with GT and predicted depth by sample ID and hierarchy.
|
|
|
123
153
|
It supports the same archive, split, and `#scope=` selectors as depth, defaulting
|
|
124
154
|
to the `sky_mask` metadata scope. Its loader must return a boolean mask with
|
|
125
155
|
**True meaning sky**. For example, `generic_dense_depth.sky_mask` uses the RGB
|
|
126
|
-
sky color in the mask dataset's `meta.
|
|
127
|
-
`(1, H, W)` tensor. Masks at another resolution follow the depth grid's crop
|
|
156
|
+
sky color in the mask dataset's `meta.skyclass` (`[R, G, B]`; the older
|
|
157
|
+
`meta.sky_mask` key is deprecated) and returns a `(1, H, W)` tensor. Masks at another resolution follow the depth grid's crop
|
|
128
158
|
rule or use nearest-neighbor resizing.
|
|
129
159
|
|
|
130
160
|
`--sky-depth` applies to dense and sparse depth evaluation. GT and both native
|
|
@@ -139,9 +169,37 @@ contributes only at projected points. Predicted sky stays in the scores where
|
|
|
139
169
|
GT is valid; `--mask-sky` separately excludes pixels using GT segmentation and
|
|
140
170
|
can be combined with `--sky-depth`.
|
|
141
171
|
|
|
142
|
-
Without `--sky-depth`,
|
|
143
|
-
|
|
144
|
-
|
|
172
|
+
Without `--sky-depth`, `--mask-sky-prediction` or `--sky-iou`, the predicted
|
|
173
|
+
mask is not loaded and depth evaluation uses the usual uncapped values.
|
|
174
|
+
`--sky-iou` loads the mask
|
|
175
|
+
even without `--sky-depth`, but only to score it against GT sky
|
|
176
|
+
([Sky segmentation](metrics.md#sky-segmentation)); the depth fill and the
|
|
177
|
+
affine-fit exclusion stay tied to `--sky-depth` (and `--mask-sky-prediction`),
|
|
178
|
+
so depth values do not change.
|
|
179
|
+
Because the mask is paired by sample ID, a mask that lacks some depth frames
|
|
180
|
+
also drops them from the depth metrics; the run prints how many. When the mask
|
|
181
|
+
is loaded only for `--sky-iou`, such a mask is not loaded at all: the run
|
|
182
|
+
warns, keeps every depth pair and skips the explicit variant. The effective cap and mask
|
|
183
|
+
source are recorded in `eval.json` under `meta.eval_params.sky_depth` and
|
|
184
|
+
`meta.pred.sky_mask`.
|
|
185
|
+
|
|
186
|
+
### Masking predicted sky
|
|
187
|
+
|
|
188
|
+
`--mask-sky-prediction` excludes the pixels of a prediction's `sky_mask` from
|
|
189
|
+
dense and sparse depth evaluation, as `--mask-sky` does for GT sky: from every
|
|
190
|
+
metric, benchmark bin and histogram, and from the scale/shift fit. For sparse
|
|
191
|
+
depth, lidar points that project into predicted sky are not scored. A dataset
|
|
192
|
+
without a `sky_mask` is scored in full and the run warns. The flag loads the
|
|
193
|
+
mask without `--sky-depth`, combines with `--mask-sky` (the union of both skies
|
|
194
|
+
is excluded) and with `--sky-depth` (the cap still applies to the remaining
|
|
195
|
+
pixels). It does not change `--sky-iou`, which scores the masks themselves.
|
|
196
|
+
|
|
197
|
+
The excluded pixels come from the evaluated model, so two models are scored on
|
|
198
|
+
different pixel sets, and a model can lower its error by calling hard pixels
|
|
199
|
+
sky. Each result records how much it excluded under `meta.pred_sky_masking`
|
|
200
|
+
([Results & output](output.md#predicted-sky-masking)); compare models with
|
|
201
|
+
this flag only alongside that fraction, or prefer `--mask-sky`, whose GT sky is
|
|
202
|
+
the same for every model.
|
|
145
203
|
|
|
146
204
|
## Sparse depth (pointcloud GT)
|
|
147
205
|
|
|
@@ -156,14 +214,16 @@ and evaluated as `points_3d`.
|
|
|
156
214
|
|
|
157
215
|
An explicit `datasets[].points_3d` prediction can be evaluated separately
|
|
158
216
|
against the same sparse cloud. That evaluation uses the points-3D similarity
|
|
159
|
-
gauge, writes an atomic `points3d.eval` metric set
|
|
160
|
-
prediction, and is controlled by `--skip-points-3d`. If a dataset
|
|
161
|
-
depth and `points_3d`, each prediction modality gets its own
|
|
162
|
-
|
|
217
|
+
gauge, writes an atomic `points3d.eval` metric set to the point-map
|
|
218
|
+
prediction's results file, and is controlled by `--skip-points-3d`. If a dataset
|
|
219
|
+
provides both depth and `points_3d`, each prediction modality gets its own
|
|
220
|
+
results file, also when both live in one archive under separate scopes (see
|
|
221
|
+
[where results land](output.md#where-results-land)).
|
|
163
222
|
|
|
164
223
|
Sparse depth does not require segmentation GT. `gt.segmentation` is loaded only
|
|
165
|
-
when `--mask-sky` is set
|
|
166
|
-
metrics and from scale/shift fitting
|
|
224
|
+
when `--mask-sky` or `--sky-iou` is set. `--mask-sky` excludes sky pixels from
|
|
225
|
+
projected-point metrics and from scale/shift fitting; `--sky-iou` scores the
|
|
226
|
+
dense prediction's sky against it without changing any depth metric.
|
|
167
227
|
|
|
168
228
|
```json
|
|
169
229
|
{
|
|
@@ -239,11 +299,15 @@ The scope defaults to the configuration key name, so the common case is compact:
|
|
|
239
299
|
|
|
240
300
|
Use `#scope=<scope>` when an artifact scope is not named exactly like the config
|
|
241
301
|
key, e.g. `"sparse_depth": { "path": "/data/capture.zip:test#scope=lidar" }`.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
`
|
|
246
|
-
|
|
302
|
+
GT segmentation is the exception: under either of its keys it also finds a
|
|
303
|
+
scope named after the other key, as described in [GT segmentation](#gt-segmentation).
|
|
304
|
+
|
|
305
|
+
Regular modalities (`rgb`, `depth`, `rays`, `points_3d`, `sparse_depth`, GT
|
|
306
|
+
segmentation and a predicted `sky_mask`) participate in file-ID intersection;
|
|
307
|
+
calibration and pose data (`intrinsics`, `calibration`, `camera_extrinsics`,
|
|
308
|
+
`lidar_extrinsics`) are loaded hierarchically and do not. A hierarchical file
|
|
309
|
+
applies to every frame at or below its folder, which suits one calibration per
|
|
310
|
+
scene but not per-frame data.
|
|
247
311
|
|
|
248
312
|
## `metrics_config.json`
|
|
249
313
|
|
|
@@ -76,6 +76,87 @@ the 45° sanity threshold.
|
|
|
76
76
|
> plane read as nearly fronto-parallel and the focal length was unused. Values
|
|
77
77
|
> are not comparable with earlier releases.
|
|
78
78
|
|
|
79
|
+
### Sky segmentation
|
|
80
|
+
|
|
81
|
+
`--sky-iou` scores how well each prediction's sky matches the GT segmentation
|
|
82
|
+
sky. It is opt-in and read-only: no depth value, mask or alignment fit changes,
|
|
83
|
+
so every other key keeps its value. It requires `gt.segmentation` (or its alias
|
|
84
|
+
`gt.semantic_segmentation`); the sky label comes from that dataset head's
|
|
85
|
+
`skyclass`, as for `--mask-sky`.
|
|
86
|
+
|
|
87
|
+
There are two variants. They answer different questions, so they are reported
|
|
88
|
+
under separate keys and never merged:
|
|
89
|
+
|
|
90
|
+
| Variant | Predicted sky `P` | Computed when |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `explicit` | The prediction's `datasets[].sky_mask` (True = sky) | The prediction has a `sky_mask` |
|
|
93
|
+
| `implicit` | `depth >= --sky-depth` | `--sky-depth` is set and the prediction is metric |
|
|
94
|
+
|
|
95
|
+
The implicit test reads the prediction after planar-to-radial conversion and
|
|
96
|
+
before calibration and capping. `+inf` counts as sky; NaN and values `<= 0` do
|
|
97
|
+
not. It is not computed for `relative_depth`, `affine_depth` or predictions
|
|
98
|
+
detected as normalized, since their values are not in meters. When both sources
|
|
99
|
+
exist, both variants are reported side by side; neither replaces the other. A
|
|
100
|
+
dataset with neither prints a warning and writes no sky keys.
|
|
101
|
+
|
|
102
|
+
| Metric | Key |
|
|
103
|
+
|---|---|
|
|
104
|
+
| Sky IoU / precision / recall | `depth.eval.sky_segmentation.{explicit,implicit}.{pixel_pool,image_mean,image_median}.{iou,precision,recall}` |
|
|
105
|
+
| Sparse-depth runs | `sparsedepth.eval.sky_segmentation.{explicit,implicit}.{pixel_pool,image_mean,image_median}.{iou,precision,recall}` |
|
|
106
|
+
| Per file | `{depth,sparsedepth}.eval.sky_segmentation.{explicit,implicit}.{iou,precision,recall}` |
|
|
107
|
+
|
|
108
|
+
`sky_segmentation` sits beside `native` and `metric`, not under them, because
|
|
109
|
+
the IoU does not depend on the evaluated depth space. Sparse-depth runs score
|
|
110
|
+
the dense prediction grid against the GT segmentation exactly like dense runs;
|
|
111
|
+
the sparse GT depth plays no part. Provenance, including the threshold and the
|
|
112
|
+
GT and predicted sky fractions, is recorded under
|
|
113
|
+
[`meta.sky_segmentation`](output.md#sky-segmentation-provenance).
|
|
114
|
+
|
|
115
|
+
If the GT segmentation lacks frames and `--mask-sky` is off, it is not loaded
|
|
116
|
+
and no sky IoU is computed, so that the depth pairs stay the same; see
|
|
117
|
+
[GT segmentation](configuration.md#gt-segmentation).
|
|
118
|
+
|
|
119
|
+
**Definitions.** GT sky `G` is the segmentation of the sample's own frame,
|
|
120
|
+
resized to the prediction grid with the same rule as GT depth (crop for the
|
|
121
|
+
VAE multiple-of-8 pattern, nearest neighbour otherwise). An explicit mask is
|
|
122
|
+
resized the same way. The domain `D` is the full prediction grid. Per sample:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
I = |P ∩ G ∩ D| U = |(P ∪ G) ∩ D| T_p = |P ∩ D| T_g = |G ∩ D|
|
|
126
|
+
iou = I / U precision = I / T_p recall = I / T_g
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Each value is undefined when its denominator is 0. `image_mean` and
|
|
130
|
+
`image_median` reduce the defined per-image values. `pixel_pool` is
|
|
131
|
+
`ΣI / ΣU`, `ΣI / ΣT_p` and `ΣI / ΣT_g` over all samples, so a sample with an
|
|
132
|
+
undefined IoU (no sky in `P` or `G`) is left out of the image reducers but
|
|
133
|
+
still adds its zero counts to the pooled sums. Undefined dataset values are
|
|
134
|
+
omitted from `eval.json`.
|
|
135
|
+
|
|
136
|
+
**Interpreting the numbers.**
|
|
137
|
+
|
|
138
|
+
- **Explicit IoU** measures agreement between a dedicated sky prediction and GT
|
|
139
|
+
sky. It does not depend on depth quality.
|
|
140
|
+
- **Implicit IoU** measures whether the depth output reaches `--sky-depth` on
|
|
141
|
+
GT sky pixels. It does not measure whether the regressor recognizes sky. A
|
|
142
|
+
regressor that outputs about 95 m over the sky, as UniDepth V2 does in fog,
|
|
143
|
+
never reaches a 250 m cap; its implicit IoU is close to zero by construction,
|
|
144
|
+
even if it places the sky correctly relative to everything else. The same
|
|
145
|
+
model at `--sky-depth 80` can score high. Implicit IoU therefore depends on
|
|
146
|
+
both the model's saturation behaviour and the cap.
|
|
147
|
+
|
|
148
|
+
Consequences:
|
|
149
|
+
|
|
150
|
+
- Never present implicit and explicit IoU as the same quantity, and always
|
|
151
|
+
state the threshold with an implicit value (`meta.sky_segmentation.threshold_m`).
|
|
152
|
+
- Do not choose `--sky-depth` on the benchmark to maximize implicit IoU. That
|
|
153
|
+
is the same leakage as choosing the fill constant on the test set. Fix the
|
|
154
|
+
threshold beforehand, or report several runs at fixed thresholds.
|
|
155
|
+
- Pooled IoU weights images by their sky area, so a few large-sky images can
|
|
156
|
+
dominate it. `image_median` shows typical behaviour.
|
|
157
|
+
- Precision and recall separate the two failure modes. Low recall with high
|
|
158
|
+
precision usually means the regressor does not saturate at the cap.
|
|
159
|
+
|
|
79
160
|
## Sparse depth
|
|
80
161
|
|
|
81
162
|
With a sparse pointcloud GT, only metrics that stay meaningful at isolated
|
|
@@ -86,6 +167,7 @@ skipped. Results serialize under the `sparsedepth.eval` root:
|
|
|
86
167
|
|---|---|
|
|
87
168
|
| Standard | `sparsedepth.eval.{native,metric}.standard.{image_mean,image_median,pixel_pool}.*` |
|
|
88
169
|
| AbsRel / RMSE / SILog | `sparsedepth.eval.{native,metric}.depth_metrics.*` |
|
|
170
|
+
| Sky segmentation (`--sky-iou`) | `sparsedepth.eval.sky_segmentation.*` ([details](#sky-segmentation)) |
|
|
89
171
|
|
|
90
172
|
## RGB
|
|
91
173
|
|