euler-preprocess 3.4.0__tar.gz → 3.5.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_preprocess-3.4.0 → euler_preprocess-3.5.0}/PKG-INFO +13 -5
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/README.md +12 -4
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/models.py +21 -18
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/transform.py +111 -9
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/PKG-INFO +13 -5
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/pyproject.toml +1 -1
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_fog_aux_outputs.py +134 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/__init__.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/cli.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/__init__.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/dataset.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/device.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/intrinsics.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/io.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/logging.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/noise.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/normalize.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/output.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/sampling.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/common/transform.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/__init__.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/airlight_from_sky.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/atmospheric_light.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/augmentations.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/capture.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_airlight.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_airlight_torch.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_heuristic_airlight.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_heuristic_airlight_torch.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/foggify.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/foggify_logging.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/inference.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/logging.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/pipeline.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/radial/__init__.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/radial/transform.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/sky_depth/__init__.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/sky_depth/transform.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/SOURCES.txt +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/dependency_links.txt +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/entry_points.txt +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/requires.txt +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/top_level.txt +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/setup.cfg +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_airlight_fallback.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_cli_sample_selection.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_dcp_heuristic_airlight.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_foggify_integration.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_radial.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_sky_depth.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_source_backed_output.py +0 -0
- {euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/tests/test_zip_output.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: euler-preprocess
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Physics-based preprocessing (fog, etc.) for RGB+depth datasets
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -408,10 +408,14 @@ weights locally.
|
|
|
408
408
|
|
|
409
409
|
Set top-level `"mode": "progressive"` to emit every configured scenario for
|
|
410
410
|
every input image instead of sampling one scenario. Each scenario accepts
|
|
411
|
-
`"steps"` and `"
|
|
412
|
-
the
|
|
413
|
-
|
|
414
|
-
|
|
411
|
+
`"steps"` and `"progressive_weight"` (or `"max_weight"` / `"weight"` as
|
|
412
|
+
aliases); the transform writes steps from weight `0` through the scenario's
|
|
413
|
+
configured weight, and weight `1` matches the original scenario. Fog density is
|
|
414
|
+
progressed in scattering-coefficient space, while numeric camera/config values
|
|
415
|
+
blend from the base config toward the scenario config. Progressive blends clamp
|
|
416
|
+
probability-like values and non-negative physical factors back into valid
|
|
417
|
+
mathematical domains so extrapolated weights above `1` do not create invalid
|
|
418
|
+
render parameters.
|
|
415
419
|
Source-backed outputs are written as `fog_progression` variants under each
|
|
416
420
|
source file id.
|
|
417
421
|
|
|
@@ -493,6 +497,10 @@ Each fog model can override the dampening curve:
|
|
|
493
497
|
|
|
494
498
|
The factor is:
|
|
495
499
|
`min_factor + (max_factor - min_factor) / (1 + strength * beta / reference_beta)`.
|
|
500
|
+
`min_factor` and `max_factor` must be finite and non-negative. Values above
|
|
501
|
+
`1.0` are allowed when you intentionally want to brighten estimated airlight;
|
|
502
|
+
the final RGB output is still clamped to the valid image range. `strength`
|
|
503
|
+
must remain finite and non-negative.
|
|
496
504
|
`reference_beta` is either `reference_scattering_coefficient` /
|
|
497
505
|
`reference_beta`, or it is derived from `reference_visibility_m` using the
|
|
498
506
|
model's contrast threshold. The default applies only when `atmospheric_light`
|
|
@@ -394,10 +394,14 @@ weights locally.
|
|
|
394
394
|
|
|
395
395
|
Set top-level `"mode": "progressive"` to emit every configured scenario for
|
|
396
396
|
every input image instead of sampling one scenario. Each scenario accepts
|
|
397
|
-
`"steps"` and `"
|
|
398
|
-
the
|
|
399
|
-
|
|
400
|
-
|
|
397
|
+
`"steps"` and `"progressive_weight"` (or `"max_weight"` / `"weight"` as
|
|
398
|
+
aliases); the transform writes steps from weight `0` through the scenario's
|
|
399
|
+
configured weight, and weight `1` matches the original scenario. Fog density is
|
|
400
|
+
progressed in scattering-coefficient space, while numeric camera/config values
|
|
401
|
+
blend from the base config toward the scenario config. Progressive blends clamp
|
|
402
|
+
probability-like values and non-negative physical factors back into valid
|
|
403
|
+
mathematical domains so extrapolated weights above `1` do not create invalid
|
|
404
|
+
render parameters.
|
|
401
405
|
Source-backed outputs are written as `fog_progression` variants under each
|
|
402
406
|
source file id.
|
|
403
407
|
|
|
@@ -479,6 +483,10 @@ Each fog model can override the dampening curve:
|
|
|
479
483
|
|
|
480
484
|
The factor is:
|
|
481
485
|
`min_factor + (max_factor - min_factor) / (1 + strength * beta / reference_beta)`.
|
|
486
|
+
`min_factor` and `max_factor` must be finite and non-negative. Values above
|
|
487
|
+
`1.0` are allowed when you intentionally want to brighten estimated airlight;
|
|
488
|
+
the final RGB output is still clamped to the valid image range. `strength`
|
|
489
|
+
must remain finite and non-negative.
|
|
482
490
|
`reference_beta` is either `reference_scattering_coefficient` /
|
|
483
491
|
`reference_beta`, or it is derived from `reference_visibility_m` using the
|
|
484
492
|
model's contrast threshold. The default applies only when `atmospheric_light`
|
|
@@ -100,8 +100,12 @@ DEFAULT_MODEL_CONFIGS = {
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
def visibility_to_k(visibility_m: float, contrast_threshold: float) -> float:
|
|
103
|
-
if visibility_m <= 0:
|
|
103
|
+
if not math.isfinite(visibility_m) or visibility_m <= 0:
|
|
104
104
|
raise ValueError(f"Visibility must be > 0, got {visibility_m}")
|
|
105
|
+
if not math.isfinite(contrast_threshold) or not 0.0 < contrast_threshold < 1.0:
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"Contrast threshold must be in (0, 1), got {contrast_threshold}"
|
|
108
|
+
)
|
|
105
109
|
return -math.log(contrast_threshold) / visibility_m
|
|
106
110
|
|
|
107
111
|
|
|
@@ -132,7 +136,7 @@ def resolve_scattering_coefficient(
|
|
|
132
136
|
beta_spec = model_cfg.get("scattering_coefficient", model_cfg.get("beta"))
|
|
133
137
|
if beta_spec is not None:
|
|
134
138
|
beta = float(sample_value(beta_spec, rng))
|
|
135
|
-
if beta < 0:
|
|
139
|
+
if not math.isfinite(beta) or beta < 0:
|
|
136
140
|
raise ValueError(f"Scattering coefficient must be >= 0, got {beta}")
|
|
137
141
|
return beta, None, contrast_threshold
|
|
138
142
|
|
|
@@ -222,13 +226,13 @@ def resolve_airlight_dampening_config(
|
|
|
222
226
|
rng,
|
|
223
227
|
"airlight_dampening.strength",
|
|
224
228
|
)
|
|
225
|
-
if
|
|
229
|
+
if min_factor < 0.0:
|
|
226
230
|
raise ValueError(
|
|
227
|
-
f"airlight_dampening.min_factor must be
|
|
231
|
+
f"airlight_dampening.min_factor must be >= 0, got {min_factor}"
|
|
228
232
|
)
|
|
229
|
-
if
|
|
233
|
+
if max_factor < 0.0:
|
|
230
234
|
raise ValueError(
|
|
231
|
-
f"airlight_dampening.max_factor must be
|
|
235
|
+
f"airlight_dampening.max_factor must be >= 0, got {max_factor}"
|
|
232
236
|
)
|
|
233
237
|
if min_factor > max_factor:
|
|
234
238
|
raise ValueError("airlight_dampening.min_factor must be <= max_factor")
|
|
@@ -504,9 +508,12 @@ def _scale_pixels(value, rng: np.random.Generator, name: str) -> int:
|
|
|
504
508
|
def _sample_float(value, rng: np.random.Generator, name: str) -> float:
|
|
505
509
|
sampled = sample_value(value, rng)
|
|
506
510
|
try:
|
|
507
|
-
|
|
511
|
+
resolved = float(sampled)
|
|
508
512
|
except (TypeError, ValueError) as exc:
|
|
509
513
|
raise ValueError(f"{name} must resolve to a number, got {sampled!r}") from exc
|
|
514
|
+
if not math.isfinite(resolved):
|
|
515
|
+
raise ValueError(f"{name} must be finite, got {resolved}")
|
|
516
|
+
return resolved
|
|
510
517
|
|
|
511
518
|
|
|
512
519
|
def _unique_positive_scales(scales: list[int]) -> list[int]:
|
|
@@ -801,9 +808,11 @@ def _gradient_enabled(
|
|
|
801
808
|
rng,
|
|
802
809
|
f"{name}.probability",
|
|
803
810
|
)
|
|
804
|
-
if
|
|
805
|
-
|
|
806
|
-
|
|
811
|
+
if probability <= 0.0:
|
|
812
|
+
return False
|
|
813
|
+
if probability >= 1.0:
|
|
814
|
+
return True
|
|
815
|
+
return bool(rng.random() < probability)
|
|
807
816
|
|
|
808
817
|
|
|
809
818
|
def _ls_gradient_factors_np(
|
|
@@ -885,10 +894,7 @@ def _weight_ls_gradient_by_opacity_np(
|
|
|
885
894
|
rng,
|
|
886
895
|
"ls_gradient.fog_opacity_weight",
|
|
887
896
|
)
|
|
888
|
-
|
|
889
|
-
raise ValueError(
|
|
890
|
-
f"ls_gradient.fog_opacity_weight must be in [0, 1], got {weight}"
|
|
891
|
-
)
|
|
897
|
+
weight = float(np.clip(weight, 0.0, 1.0))
|
|
892
898
|
if weight <= 0.0:
|
|
893
899
|
return factors
|
|
894
900
|
gamma = _sample_float(
|
|
@@ -917,10 +923,7 @@ def _weight_ls_gradient_by_opacity_torch(
|
|
|
917
923
|
rng,
|
|
918
924
|
"ls_gradient.fog_opacity_weight",
|
|
919
925
|
)
|
|
920
|
-
|
|
921
|
-
raise ValueError(
|
|
922
|
-
f"ls_gradient.fog_opacity_weight must be in [0, 1], got {weight}"
|
|
923
|
-
)
|
|
926
|
+
weight = float(np.clip(weight, 0.0, 1.0))
|
|
924
927
|
if weight <= 0.0:
|
|
925
928
|
return factors
|
|
926
929
|
gamma = _sample_float(
|
|
@@ -129,6 +129,53 @@ _GPU_BATCH_SCOPE_VALUES = {"sample", "batch"}
|
|
|
129
129
|
_CONFIG_MODE_VALUES = {"sample", "sampled", "random", "default", "legacy"}
|
|
130
130
|
_PROGRESSIVE_ATTRIBUTE_KEY = "fog_progression"
|
|
131
131
|
_PROGRESSIVE_FILE_ID_HIERARCHY_NAME = "file_id"
|
|
132
|
+
_PROGRESSIVE_EPSILON = 1e-6
|
|
133
|
+
_PROGRESSIVE_UNIT_INTERVAL_KEYS = {
|
|
134
|
+
"probability",
|
|
135
|
+
"fog_opacity_weight",
|
|
136
|
+
"highlight_protection",
|
|
137
|
+
"center_weight",
|
|
138
|
+
"black_noise_floor",
|
|
139
|
+
}
|
|
140
|
+
_PROGRESSIVE_NON_NEGATIVE_KEYS = {
|
|
141
|
+
"beta",
|
|
142
|
+
"scattering_coefficient",
|
|
143
|
+
"strength",
|
|
144
|
+
"min_factor",
|
|
145
|
+
"max_factor",
|
|
146
|
+
"top_factor",
|
|
147
|
+
"bottom_factor",
|
|
148
|
+
"contrast",
|
|
149
|
+
"noise_contrast",
|
|
150
|
+
"smooth_sigma",
|
|
151
|
+
"smoothing_sigma",
|
|
152
|
+
"blur_sigma",
|
|
153
|
+
"smooth_sigma_fraction",
|
|
154
|
+
"smoothing_sigma_fraction",
|
|
155
|
+
"blur_sigma_fraction",
|
|
156
|
+
"read_noise_electrons",
|
|
157
|
+
"read_noise_sigma",
|
|
158
|
+
"fixed_pattern_sigma",
|
|
159
|
+
"row_noise_sigma",
|
|
160
|
+
"column_noise_sigma",
|
|
161
|
+
"hot_pixel_probability",
|
|
162
|
+
"dead_pixel_probability",
|
|
163
|
+
}
|
|
164
|
+
_PROGRESSIVE_POSITIVE_KEYS = {
|
|
165
|
+
"visibility_m",
|
|
166
|
+
"reference_visibility_m",
|
|
167
|
+
"reference_beta",
|
|
168
|
+
"reference_scattering_coefficient",
|
|
169
|
+
"gamma",
|
|
170
|
+
"fog_opacity_gamma",
|
|
171
|
+
"correlation_length_fraction",
|
|
172
|
+
"min_scale_fraction",
|
|
173
|
+
"max_scale_fraction",
|
|
174
|
+
"iso",
|
|
175
|
+
"base_iso",
|
|
176
|
+
"resize_scale",
|
|
177
|
+
}
|
|
178
|
+
_PROGRESSIVE_MIN_MAX_PAIRS = (("min_factor", "max_factor"),)
|
|
132
179
|
|
|
133
180
|
|
|
134
181
|
@dataclass(frozen=True)
|
|
@@ -826,16 +873,20 @@ class FogTransform(Transform):
|
|
|
826
873
|
base_model_cfg = _freeze_distribution_specs(base_model_cfg, rng)
|
|
827
874
|
target_model_cfg = _freeze_distribution_specs(target_model_cfg, rng)
|
|
828
875
|
|
|
829
|
-
step_effective_config = self.
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
876
|
+
step_effective_config = self._sanitize_progressive_blended_config(
|
|
877
|
+
self._progressive_blend_value(
|
|
878
|
+
base_effective_config,
|
|
879
|
+
target_effective_config,
|
|
880
|
+
step.weight,
|
|
881
|
+
)
|
|
833
882
|
)
|
|
834
|
-
model_cfg = self.
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
883
|
+
model_cfg = self._sanitize_progressive_blended_config(
|
|
884
|
+
self._progressive_model_config(
|
|
885
|
+
base_model_cfg,
|
|
886
|
+
target_model_cfg,
|
|
887
|
+
step.weight,
|
|
888
|
+
rng,
|
|
889
|
+
)
|
|
839
890
|
)
|
|
840
891
|
airlight_method = (
|
|
841
892
|
None
|
|
@@ -953,6 +1004,57 @@ class FogTransform(Transform):
|
|
|
953
1004
|
|
|
954
1005
|
return copy.deepcopy(target)
|
|
955
1006
|
|
|
1007
|
+
def _sanitize_progressive_blended_config(
|
|
1008
|
+
self,
|
|
1009
|
+
value: Any,
|
|
1010
|
+
*,
|
|
1011
|
+
key: str | None = None,
|
|
1012
|
+
) -> Any:
|
|
1013
|
+
if isinstance(value, dict):
|
|
1014
|
+
sanitized = {
|
|
1015
|
+
child_key: self._sanitize_progressive_blended_config(
|
|
1016
|
+
child,
|
|
1017
|
+
key=child_key,
|
|
1018
|
+
)
|
|
1019
|
+
for child_key, child in value.items()
|
|
1020
|
+
}
|
|
1021
|
+
for min_key, max_key in _PROGRESSIVE_MIN_MAX_PAIRS:
|
|
1022
|
+
min_value = sanitized.get(min_key)
|
|
1023
|
+
max_value = sanitized.get(max_key)
|
|
1024
|
+
if (
|
|
1025
|
+
_is_progressive_number(min_value)
|
|
1026
|
+
and _is_progressive_number(max_value)
|
|
1027
|
+
and float(max_value) < float(min_value)
|
|
1028
|
+
):
|
|
1029
|
+
sanitized[max_key] = float(min_value)
|
|
1030
|
+
return sanitized
|
|
1031
|
+
|
|
1032
|
+
if isinstance(value, list):
|
|
1033
|
+
return [
|
|
1034
|
+
self._sanitize_progressive_blended_config(item, key=key)
|
|
1035
|
+
for item in value
|
|
1036
|
+
]
|
|
1037
|
+
if isinstance(value, tuple):
|
|
1038
|
+
return tuple(
|
|
1039
|
+
self._sanitize_progressive_blended_config(item, key=key)
|
|
1040
|
+
for item in value
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
if not _is_progressive_number(value):
|
|
1044
|
+
return copy.deepcopy(value)
|
|
1045
|
+
|
|
1046
|
+
numeric = float(value)
|
|
1047
|
+
if not np.isfinite(numeric):
|
|
1048
|
+
label = key or "value"
|
|
1049
|
+
raise ValueError(f"progressive blended {label} must be finite")
|
|
1050
|
+
if key in _PROGRESSIVE_UNIT_INTERVAL_KEYS:
|
|
1051
|
+
return float(np.clip(numeric, 0.0, 1.0))
|
|
1052
|
+
if key in _PROGRESSIVE_POSITIVE_KEYS:
|
|
1053
|
+
return max(numeric, _PROGRESSIVE_EPSILON)
|
|
1054
|
+
if key in _PROGRESSIVE_NON_NEGATIVE_KEYS:
|
|
1055
|
+
return max(numeric, 0.0)
|
|
1056
|
+
return copy.deepcopy(value)
|
|
1057
|
+
|
|
956
1058
|
def _progressive_neutral_value(self, key: str | None, target: Any) -> Any:
|
|
957
1059
|
if _is_progressive_number(target):
|
|
958
1060
|
return self._progressive_neutral_number(key, float(target))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: euler-preprocess
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Physics-based preprocessing (fog, etc.) for RGB+depth datasets
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -408,10 +408,14 @@ weights locally.
|
|
|
408
408
|
|
|
409
409
|
Set top-level `"mode": "progressive"` to emit every configured scenario for
|
|
410
410
|
every input image instead of sampling one scenario. Each scenario accepts
|
|
411
|
-
`"steps"` and `"
|
|
412
|
-
the
|
|
413
|
-
|
|
414
|
-
|
|
411
|
+
`"steps"` and `"progressive_weight"` (or `"max_weight"` / `"weight"` as
|
|
412
|
+
aliases); the transform writes steps from weight `0` through the scenario's
|
|
413
|
+
configured weight, and weight `1` matches the original scenario. Fog density is
|
|
414
|
+
progressed in scattering-coefficient space, while numeric camera/config values
|
|
415
|
+
blend from the base config toward the scenario config. Progressive blends clamp
|
|
416
|
+
probability-like values and non-negative physical factors back into valid
|
|
417
|
+
mathematical domains so extrapolated weights above `1` do not create invalid
|
|
418
|
+
render parameters.
|
|
415
419
|
Source-backed outputs are written as `fog_progression` variants under each
|
|
416
420
|
source file id.
|
|
417
421
|
|
|
@@ -493,6 +497,10 @@ Each fog model can override the dampening curve:
|
|
|
493
497
|
|
|
494
498
|
The factor is:
|
|
495
499
|
`min_factor + (max_factor - min_factor) / (1 + strength * beta / reference_beta)`.
|
|
500
|
+
`min_factor` and `max_factor` must be finite and non-negative. Values above
|
|
501
|
+
`1.0` are allowed when you intentionally want to brighten estimated airlight;
|
|
502
|
+
the final RGB output is still clamped to the valid image range. `strength`
|
|
503
|
+
must remain finite and non-negative.
|
|
496
504
|
`reference_beta` is either `reference_scattering_coefficient` /
|
|
497
505
|
`reference_beta`, or it is derived from `reference_visibility_m` using the
|
|
498
506
|
model's contrast threshold. The default applies only when `atmospheric_light`
|
|
@@ -462,6 +462,70 @@ def test_progressive_scenario_profiles_write_steps_and_attributes(
|
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
|
|
465
|
+
def test_progressive_scenario_profiles_accept_extrapolated_airlight_dampening(
|
|
466
|
+
tmp_path: Path,
|
|
467
|
+
) -> None:
|
|
468
|
+
dataset = _make_dataset(tmp_path)
|
|
469
|
+
pipeline_root = tmp_path / "pipeline_root_progressive_airlight"
|
|
470
|
+
manifest_path = pipeline_root / ".euler_pipeline" / "pipeline_outputs.json"
|
|
471
|
+
config = _build_pipeline_config(
|
|
472
|
+
pipeline_root,
|
|
473
|
+
manifest_path,
|
|
474
|
+
include_scattering=False,
|
|
475
|
+
include_airlight=True,
|
|
476
|
+
)
|
|
477
|
+
fog_config_path = tmp_path / "fog_progressive_airlight.json"
|
|
478
|
+
fog_config_path.write_text(
|
|
479
|
+
json.dumps(
|
|
480
|
+
{
|
|
481
|
+
"mode": "progressive",
|
|
482
|
+
"airlight": "from_sky",
|
|
483
|
+
"device": "cpu",
|
|
484
|
+
"seed": 7,
|
|
485
|
+
"contrast_threshold": 0.05,
|
|
486
|
+
"scenario_profiles": [
|
|
487
|
+
{
|
|
488
|
+
"name": "bright-airlight",
|
|
489
|
+
"steps": 1,
|
|
490
|
+
"progressive_weight": 1.5,
|
|
491
|
+
"model": "uniform",
|
|
492
|
+
"models": {
|
|
493
|
+
"uniform": {
|
|
494
|
+
"visibility_m": 20.0,
|
|
495
|
+
"atmospheric_light": "from_sky",
|
|
496
|
+
"airlight_dampening": {
|
|
497
|
+
"min_factor": 0.8,
|
|
498
|
+
"max_factor": 1.1,
|
|
499
|
+
"strength": 0.0,
|
|
500
|
+
},
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
}
|
|
504
|
+
],
|
|
505
|
+
}
|
|
506
|
+
)
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
backends = prepare_output_backends(config, dataset, FogTransform)
|
|
510
|
+
transform = FogTransform(
|
|
511
|
+
config_path=str(fog_config_path),
|
|
512
|
+
out_path=str(backends["rgb"].root),
|
|
513
|
+
output_backends=backends,
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
saved_paths = transform.run(dataset)
|
|
517
|
+
|
|
518
|
+
assert saved_paths[-1] == (
|
|
519
|
+
pipeline_root
|
|
520
|
+
/ "foggy_rgb"
|
|
521
|
+
/ "Scene01"
|
|
522
|
+
/ "Camera_0"
|
|
523
|
+
/ "00001"
|
|
524
|
+
/ "bright-airlight_w1.5.png"
|
|
525
|
+
)
|
|
526
|
+
assert saved_paths[-1].exists()
|
|
527
|
+
|
|
528
|
+
|
|
465
529
|
def test_only_scattering_target_writes_only_scattering(tmp_path: Path) -> None:
|
|
466
530
|
dataset = _make_dataset(tmp_path)
|
|
467
531
|
pipeline_root = tmp_path / "pipeline_root_scat_only"
|
|
@@ -2424,6 +2488,76 @@ def test_airlight_dampening_alias_can_disable_default() -> None:
|
|
|
2424
2488
|
np.testing.assert_allclose(airlight, estimated, atol=1e-6)
|
|
2425
2489
|
|
|
2426
2490
|
|
|
2491
|
+
def test_airlight_dampening_accepts_brightening_factors() -> None:
|
|
2492
|
+
from euler_preprocess.fog.models import apply_model
|
|
2493
|
+
|
|
2494
|
+
rgb = np.full((4, 5, 3), 0.35, dtype=np.float32)
|
|
2495
|
+
depth = np.full((4, 5), 30.0, dtype=np.float32)
|
|
2496
|
+
estimated = np.array([0.35, 0.4, 0.45], dtype=np.float32)
|
|
2497
|
+
cfg = {
|
|
2498
|
+
"scattering_coefficient": 0.1,
|
|
2499
|
+
"atmospheric_light": "from_sky",
|
|
2500
|
+
"airlight_dampening": {
|
|
2501
|
+
"min_factor": 1.1,
|
|
2502
|
+
"max_factor": 1.25,
|
|
2503
|
+
"strength": 0.0,
|
|
2504
|
+
},
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
_, _, airlight, _, _ = apply_model(
|
|
2508
|
+
rgb,
|
|
2509
|
+
depth,
|
|
2510
|
+
"uniform",
|
|
2511
|
+
cfg,
|
|
2512
|
+
np.random.default_rng(0),
|
|
2513
|
+
contrast_threshold_default=0.05,
|
|
2514
|
+
estimated_airlight=estimated,
|
|
2515
|
+
)
|
|
2516
|
+
|
|
2517
|
+
np.testing.assert_allclose(airlight, estimated * 1.25, atol=1e-6)
|
|
2518
|
+
|
|
2519
|
+
|
|
2520
|
+
def test_ls_gradient_probability_and_opacity_weight_saturate() -> None:
|
|
2521
|
+
from euler_preprocess.fog.models import apply_model
|
|
2522
|
+
|
|
2523
|
+
rng = np.random.default_rng(123)
|
|
2524
|
+
rgb = np.zeros((20, 16, 3), dtype=np.float32)
|
|
2525
|
+
depth = np.full((20, 16), 80.0, dtype=np.float32)
|
|
2526
|
+
estimated = np.array([0.6, 0.65, 0.7], dtype=np.float32)
|
|
2527
|
+
cfg = {
|
|
2528
|
+
"scattering_coefficient": 0.08,
|
|
2529
|
+
"atmospheric_light": "from_sky",
|
|
2530
|
+
"airlight_dampening": {"enabled": False},
|
|
2531
|
+
"ls_hetero": {
|
|
2532
|
+
"scales": [4],
|
|
2533
|
+
"min_factor": 1.0,
|
|
2534
|
+
"max_factor": 1.0,
|
|
2535
|
+
"normalize_to_mean": False,
|
|
2536
|
+
"ls_gradient": {
|
|
2537
|
+
"enabled": True,
|
|
2538
|
+
"probability": 1.4,
|
|
2539
|
+
"top_factor": 1.18,
|
|
2540
|
+
"bottom_factor": 0.82,
|
|
2541
|
+
"gamma": 1.0,
|
|
2542
|
+
"normalize_to_mean": False,
|
|
2543
|
+
"fog_opacity_weight": 1.5,
|
|
2544
|
+
},
|
|
2545
|
+
},
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
_, _, _, _, ls_map = apply_model(
|
|
2549
|
+
rgb,
|
|
2550
|
+
depth,
|
|
2551
|
+
"heterogeneous_ls",
|
|
2552
|
+
cfg,
|
|
2553
|
+
rng,
|
|
2554
|
+
contrast_threshold_default=0.05,
|
|
2555
|
+
estimated_airlight=estimated,
|
|
2556
|
+
)
|
|
2557
|
+
|
|
2558
|
+
assert np.isfinite(ls_map).all()
|
|
2559
|
+
|
|
2560
|
+
|
|
2427
2561
|
def test_heterogeneous_ls_uses_dampened_airlight_base() -> None:
|
|
2428
2562
|
"""Perlin L_s modes should modulate around the already dampened base airlight."""
|
|
2429
2563
|
from euler_preprocess.fog.models import apply_model
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_airlight_torch.py
RENAMED
|
File without changes
|
{euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess/fog/dcp_heuristic_airlight.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{euler_preprocess-3.4.0 → euler_preprocess-3.5.0}/euler_preprocess.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|