cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a4__cp313-cp313-win_amd64.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.
Potentially problematic release.
This version of cars might be problematic. Click here for more details.
- cars/__init__.py +3 -3
- cars/applications/__init__.py +0 -3
- cars/applications/application.py +14 -6
- cars/applications/application_template.py +42 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
- cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
- cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
- cars/applications/dem_generation/rasterization_app.py +112 -43
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +48 -14
- cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
- cars/applications/dense_matching/disparity_grid_algo.py +95 -79
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
- cars/applications/dsm_filling/border_interpolation_app.py +11 -12
- cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
- cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
- cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
- cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +88 -116
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +60 -53
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +5 -25
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +364 -22
- cars/core/geometry/shareloc_geometry.py +112 -82
- cars/core/inputs.py +72 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +126 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +12 -10
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +149 -22
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +15 -4
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +461 -1052
- cars/pipelines/parameters/advanced_parameters.py +91 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +122 -73
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +676 -1070
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
- cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
- cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
- cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
- cars/applications/dense_match_filling/cpp/__init__.py +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
- cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
- cars/applications/dense_match_filling/cpp/meson.build +0 -9
- cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
- cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
- cars/applications/dense_match_filling/plane_app.py +0 -556
- cars/applications/hole_detection/__init__.py +0 -30
- cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
- cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
- cars/applications/hole_detection/hole_detection_algo.py +0 -144
- cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
- cars/applications/point_cloud_denoising/__init__.py +0 -29
- cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
- cars/applications/point_cloud_fusion/__init__.py +0 -30
- cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
- cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
- cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
- cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
- cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -24,18 +24,18 @@ Used for full_res and low_res pipelines
|
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
26
|
import logging
|
|
27
|
+
import math
|
|
27
28
|
import os
|
|
28
29
|
|
|
30
|
+
import numpy as np
|
|
29
31
|
import rasterio as rio
|
|
30
|
-
from json_checker import Checker,
|
|
32
|
+
from json_checker import Checker, Or
|
|
31
33
|
|
|
32
34
|
# CARS imports
|
|
33
|
-
from cars.core import inputs,
|
|
35
|
+
from cars.core import inputs, projection
|
|
34
36
|
from cars.core.geometry.abstract_geometry import AbstractGeometry
|
|
35
37
|
from cars.core.utils import make_relative_path_absolute
|
|
36
|
-
from cars.
|
|
37
|
-
depth_map_inputs_constants as depth_map_cst,
|
|
38
|
-
)
|
|
38
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
39
39
|
from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
|
|
40
40
|
from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
|
|
41
41
|
|
|
@@ -68,7 +68,6 @@ def sensors_check_inputs(conf, config_dir=None): # noqa: C901
|
|
|
68
68
|
sens_cst.PAIRING: Or([[str]], None),
|
|
69
69
|
sens_cst.INITIAL_ELEVATION: Or(str, dict, None),
|
|
70
70
|
sens_cst.ROI: Or(str, dict, None),
|
|
71
|
-
OptionalKey(depth_map_cst.DEPTH_MAPS): dict,
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
checker_inputs = Checker(inputs_schema)
|
|
@@ -111,12 +110,12 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
|
|
|
111
110
|
sens_cst.INPUT_IMG, None
|
|
112
111
|
)
|
|
113
112
|
if isinstance(image, str):
|
|
114
|
-
loader_name = "
|
|
113
|
+
loader_name = "basic_image"
|
|
115
114
|
elif isinstance(image, dict):
|
|
116
|
-
loader_name = image.get("loader", "
|
|
115
|
+
loader_name = image.get("loader", "basic_image")
|
|
117
116
|
else:
|
|
118
117
|
raise TypeError(f"Image {image} is not of type str or dict")
|
|
119
|
-
image_loader = SensorLoader(loader_name, image,
|
|
118
|
+
image_loader = SensorLoader(loader_name, image, config_dir)
|
|
120
119
|
image_as_pivot_format = (
|
|
121
120
|
image_loader.get_pivot_format() # pylint: disable=E1101
|
|
122
121
|
)
|
|
@@ -145,14 +144,12 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
|
|
|
145
144
|
)
|
|
146
145
|
if classif is not None:
|
|
147
146
|
if isinstance(classif, str):
|
|
148
|
-
loader_name = "
|
|
147
|
+
loader_name = "basic_classif"
|
|
149
148
|
elif isinstance(classif, dict):
|
|
150
|
-
loader_name = classif.get("loader", "
|
|
149
|
+
loader_name = classif.get("loader", "basic_classif")
|
|
151
150
|
else:
|
|
152
151
|
raise TypeError(f"Classif {classif} is not of type str or dict")
|
|
153
|
-
classif_loader = SensorLoader(
|
|
154
|
-
loader_name, classif, "classification", config_dir
|
|
155
|
-
)
|
|
152
|
+
classif_loader = SensorLoader(loader_name, classif, config_dir)
|
|
156
153
|
classif_as_pivot_format = (
|
|
157
154
|
classif_loader.get_pivot_format() # pylint: disable=E1101
|
|
158
155
|
)
|
|
@@ -235,7 +232,68 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
|
|
|
235
232
|
return overloaded_conf
|
|
236
233
|
|
|
237
234
|
|
|
238
|
-
def
|
|
235
|
+
def get_sensor_resolution(
|
|
236
|
+
geom_plugin, sensor_path, geomodel, target_epsg=32631
|
|
237
|
+
):
|
|
238
|
+
"""
|
|
239
|
+
Estimate the sensor image resolution in meters per pixel
|
|
240
|
+
using geolocation of 3 corners of the image.
|
|
241
|
+
|
|
242
|
+
:param geom_plugin: geometry plugin instance
|
|
243
|
+
:param sensor_path: path to the sensor image
|
|
244
|
+
:type sensor_path: dict
|
|
245
|
+
:param geomodel: geometric model for the sensor image
|
|
246
|
+
:param target_epsg: target EPSG code for projection
|
|
247
|
+
:type target_epsg: int
|
|
248
|
+
:return: average resolution in meters/pixel along x and y
|
|
249
|
+
:rtype: float
|
|
250
|
+
"""
|
|
251
|
+
width, height = inputs.rasterio_get_size(sensor_path[sens_cst.MAIN_FILE])
|
|
252
|
+
|
|
253
|
+
upper_left = (0.5, 0.5)
|
|
254
|
+
upper_right = (width - 0.5, 0.5)
|
|
255
|
+
bottom_left = (0.5, height - 0.5)
|
|
256
|
+
|
|
257
|
+
# get geodetic coordinates
|
|
258
|
+
lat_ul, lon_ul, _ = geom_plugin.direct_loc(
|
|
259
|
+
sensor_path[sens_cst.MAIN_FILE],
|
|
260
|
+
geomodel,
|
|
261
|
+
np.array([upper_left[0]]),
|
|
262
|
+
np.array([upper_left[1]]),
|
|
263
|
+
)
|
|
264
|
+
lat_ur, lon_ur, _ = geom_plugin.direct_loc(
|
|
265
|
+
sensor_path[sens_cst.MAIN_FILE],
|
|
266
|
+
geomodel,
|
|
267
|
+
np.array([upper_right[0]]),
|
|
268
|
+
np.array([upper_right[1]]),
|
|
269
|
+
)
|
|
270
|
+
lat_bl, lon_bl, _ = geom_plugin.direct_loc(
|
|
271
|
+
sensor_path[sens_cst.MAIN_FILE],
|
|
272
|
+
geomodel,
|
|
273
|
+
np.array([bottom_left[0]]),
|
|
274
|
+
np.array([bottom_left[1]]),
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
coords_ll = np.array(
|
|
278
|
+
[[lon_ul, lat_ul, 0], [lon_ur, lat_ur, 0], [lon_bl, lat_bl, 0]]
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Convert to target CRS
|
|
282
|
+
coords_xy = projection.point_cloud_conversion(coords_ll, 4326, target_epsg)
|
|
283
|
+
|
|
284
|
+
diff_x = np.linalg.norm(coords_xy[1] - coords_xy[0]) # UL to UR (width)
|
|
285
|
+
diff_y = np.linalg.norm(coords_xy[2] - coords_xy[0]) # UL to BL (height)
|
|
286
|
+
|
|
287
|
+
# resolution in meters per pixel
|
|
288
|
+
res_x = diff_x / (width - 1)
|
|
289
|
+
res_y = diff_y / (height - 1)
|
|
290
|
+
|
|
291
|
+
return (res_x + res_y) / 2
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def check_geometry_plugin(
|
|
295
|
+
conf_inputs, conf_geom_plugin, epipolar_resolution, output_dem_dir
|
|
296
|
+
):
|
|
239
297
|
"""
|
|
240
298
|
Check the geometry plugin with inputs
|
|
241
299
|
|
|
@@ -245,6 +303,8 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
|
|
|
245
303
|
:type conf_advanced: type
|
|
246
304
|
:param conf_geom_plugin: name of geometry plugin
|
|
247
305
|
:type conf_geom_plugin: str
|
|
306
|
+
:param epipolar_resolution: epipolar resolution
|
|
307
|
+
:type epipolar_resolution: int
|
|
248
308
|
:return: overload inputs conf
|
|
249
309
|
overloaded geometry plugin conf
|
|
250
310
|
geometry plugin without dem
|
|
@@ -253,11 +313,41 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
|
|
|
253
313
|
if conf_geom_plugin is None:
|
|
254
314
|
conf_geom_plugin = "SharelocGeometry"
|
|
255
315
|
|
|
316
|
+
# Initialize a temporary plugin, to get the product's resolution
|
|
317
|
+
temp_geom_plugin = (
|
|
318
|
+
AbstractGeometry( # pylint: disable=abstract-class-instantiated
|
|
319
|
+
conf_geom_plugin,
|
|
320
|
+
default_alt=sens_cst.CARS_DEFAULT_ALT,
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
average_sensor_resolution = 0
|
|
324
|
+
for _, sensor_image in conf_inputs[sens_cst.SENSORS].items():
|
|
325
|
+
sensor = sensor_image[sens_cst.INPUT_IMG]
|
|
326
|
+
geomodel = sensor_image[sens_cst.INPUT_GEO_MODEL]
|
|
327
|
+
(
|
|
328
|
+
sensor,
|
|
329
|
+
geomodel,
|
|
330
|
+
) = temp_geom_plugin.check_product_consistency(sensor, geomodel)
|
|
331
|
+
average_sensor_resolution += (
|
|
332
|
+
get_sensor_resolution(temp_geom_plugin, sensor, geomodel)
|
|
333
|
+
* epipolar_resolution
|
|
334
|
+
)
|
|
335
|
+
average_sensor_resolution /= len(conf_inputs[sens_cst.SENSORS])
|
|
336
|
+
# approximate resolution to the highest digit:
|
|
337
|
+
# 0.47 -> 0.5
|
|
338
|
+
# 7.52 -> 8
|
|
339
|
+
# 12.9 -> 10
|
|
340
|
+
nb_digits = int(math.floor(math.log10(abs(average_sensor_resolution))))
|
|
341
|
+
scaling_coeff = round(average_sensor_resolution, -nb_digits)
|
|
342
|
+
# make it so 0.5 (CO3D) is the baseline for parameters
|
|
343
|
+
scaling_coeff *= 2
|
|
344
|
+
|
|
256
345
|
# Initialize the desired geometry plugin without elevation information
|
|
257
346
|
geom_plugin_without_dem_and_geoid = (
|
|
258
347
|
AbstractGeometry( # pylint: disable=abstract-class-instantiated
|
|
259
348
|
conf_geom_plugin,
|
|
260
349
|
default_alt=sens_cst.CARS_DEFAULT_ALT,
|
|
350
|
+
scaling_coeff=scaling_coeff,
|
|
261
351
|
)
|
|
262
352
|
)
|
|
263
353
|
|
|
@@ -280,75 +370,29 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
|
|
|
280
370
|
] = geomodel
|
|
281
371
|
|
|
282
372
|
geom_plugin_with_dem_and_geoid = generate_geometry_plugin_with_dem(
|
|
283
|
-
conf_geom_plugin,
|
|
373
|
+
conf_geom_plugin,
|
|
374
|
+
conf_inputs,
|
|
375
|
+
scaling_coeff=scaling_coeff,
|
|
376
|
+
output_dem_dir=output_dem_dir,
|
|
284
377
|
)
|
|
285
378
|
|
|
286
|
-
# Check dem is big enough
|
|
287
|
-
dem_generation_roi_poly = None
|
|
288
|
-
needed_dem_roi = geom_plugin_with_dem_and_geoid.dem_roi
|
|
289
|
-
needed_dem_roi_epsg = geom_plugin_with_dem_and_geoid.dem_roi_epsg
|
|
290
|
-
if needed_dem_roi is not None:
|
|
291
|
-
needed_dem_roi_poly = roi_tools.bounds_to_poly(needed_dem_roi)
|
|
292
|
-
# convert to 4326 roi
|
|
293
|
-
dem_generation_roi_poly = preprocessing.compute_roi_poly(
|
|
294
|
-
needed_dem_roi_poly, needed_dem_roi_epsg, 4326
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
if (
|
|
298
|
-
conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
|
|
299
|
-
is not None
|
|
300
|
-
):
|
|
301
|
-
# get dem total roi
|
|
302
|
-
total_input_roi_poly = roi_tools.bounds_to_poly(
|
|
303
|
-
inputs.rasterio_get_bounds(
|
|
304
|
-
conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
|
|
305
|
-
)
|
|
306
|
-
)
|
|
307
|
-
total_input_roi_epsg = inputs.rasterio_get_epsg_code(
|
|
308
|
-
conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
|
|
309
|
-
)
|
|
310
|
-
if not isinstance(total_input_roi_epsg, int):
|
|
311
|
-
total_input_roi_epsg = total_input_roi_epsg.to_epsg()
|
|
312
|
-
total_input_roi_poly = preprocessing.compute_roi_poly(
|
|
313
|
-
total_input_roi_poly, total_input_roi_epsg, 4326
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
# if needed roi not inside dem, raise error
|
|
317
|
-
if not total_input_roi_poly.contains_properly(
|
|
318
|
-
dem_generation_roi_poly
|
|
319
|
-
):
|
|
320
|
-
base_message = (
|
|
321
|
-
"Given initial elevation ROI is not covering needed ROI: "
|
|
322
|
-
" EPSG:4326, ROI: {}".format(dem_generation_roi_poly.bounds)
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
if total_input_roi_poly.intersects(dem_generation_roi_poly):
|
|
326
|
-
logging.warning(
|
|
327
|
-
"{}. Only a part of it intersects. "
|
|
328
|
-
"Errors might occur".format(base_message)
|
|
329
|
-
)
|
|
330
|
-
else:
|
|
331
|
-
# Exit, Error is certain to occur
|
|
332
|
-
raise RuntimeError(base_message)
|
|
333
|
-
|
|
334
|
-
else:
|
|
335
|
-
logging.warning(
|
|
336
|
-
"Current geometry plugin doesnt compute dem roi needed "
|
|
337
|
-
"for later computations. Errors related to unsufficient "
|
|
338
|
-
"dem roi might occur."
|
|
339
|
-
)
|
|
340
|
-
|
|
341
379
|
return (
|
|
342
380
|
overloaded_conf_inputs,
|
|
343
381
|
conf_geom_plugin,
|
|
344
382
|
geom_plugin_without_dem_and_geoid,
|
|
345
383
|
geom_plugin_with_dem_and_geoid,
|
|
346
|
-
|
|
384
|
+
scaling_coeff,
|
|
347
385
|
)
|
|
348
386
|
|
|
349
387
|
|
|
388
|
+
# pylint: disable=too-many-positional-arguments
|
|
350
389
|
def generate_geometry_plugin_with_dem(
|
|
351
|
-
conf_geom_plugin,
|
|
390
|
+
conf_geom_plugin,
|
|
391
|
+
conf_inputs,
|
|
392
|
+
dem=None,
|
|
393
|
+
crop_dem=True,
|
|
394
|
+
output_dem_dir=None,
|
|
395
|
+
scaling_coeff=1,
|
|
352
396
|
):
|
|
353
397
|
"""
|
|
354
398
|
Generate geometry plugin with dem and geoid
|
|
@@ -356,6 +400,8 @@ def generate_geometry_plugin_with_dem(
|
|
|
356
400
|
:param conf_geom_plugin: plugin configuration
|
|
357
401
|
:param conf_inputs: inputs configuration
|
|
358
402
|
:param dem: dem to overide the one in inputs
|
|
403
|
+
:param scaling_coeff: scaling factor for resolution
|
|
404
|
+
:type scaling_coeff: float
|
|
359
405
|
|
|
360
406
|
:return: geometry plugin object, with a dem
|
|
361
407
|
"""
|
|
@@ -389,6 +435,8 @@ def generate_geometry_plugin_with_dem(
|
|
|
389
435
|
geoid=conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.GEOID],
|
|
390
436
|
default_alt=sens_cst.CARS_DEFAULT_ALT,
|
|
391
437
|
pairs_for_roi=pairs_for_roi,
|
|
438
|
+
scaling_coeff=scaling_coeff,
|
|
439
|
+
output_dem_dir=output_dem_dir,
|
|
392
440
|
)
|
|
393
441
|
)
|
|
394
442
|
|
|
@@ -644,6 +692,7 @@ def check_all_nbits_equal_one(nbits):
|
|
|
644
692
|
return False
|
|
645
693
|
|
|
646
694
|
|
|
695
|
+
@cars_profile(name="Generate inputs")
|
|
647
696
|
def generate_inputs(conf, geometry_plugin):
|
|
648
697
|
"""
|
|
649
698
|
Generate sensors inputs form inputs conf :
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
CARS application module init file
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
from .
|
|
27
|
-
from .
|
|
25
|
+
from .basic_classif_loader import BasicClassifSensorLoader # noqa: F401
|
|
26
|
+
from .basic_image_loader import BasicImageSensorLoader # noqa: F401
|
|
27
|
+
from .pivot_classif_loader import PivotClassifSensorLoader # noqa: F401
|
|
28
|
+
from .pivot_image_loader import PivotImageSensorLoader # noqa: F401
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES).
|
|
5
|
+
#
|
|
6
|
+
# This file is part of CARS
|
|
7
|
+
# (see https://github.com/CNES/cars).
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
"""
|
|
22
|
+
This module contains the ClassifSensorLoader class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from json_checker import Checker
|
|
26
|
+
|
|
27
|
+
from cars.core import inputs
|
|
28
|
+
from cars.core.utils import make_relative_path_absolute
|
|
29
|
+
from cars.pipelines.parameters.sensor_loaders.pivot_classif_loader import (
|
|
30
|
+
PivotClassifSensorLoader,
|
|
31
|
+
)
|
|
32
|
+
from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
|
|
33
|
+
from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
|
|
34
|
+
SensorLoaderTemplate,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@SensorLoader.register("basic_classif")
|
|
39
|
+
class BasicClassifSensorLoader(SensorLoaderTemplate):
|
|
40
|
+
"""
|
|
41
|
+
Default sensor loader (used when no sensor loader is specified)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def check_conf(self, conf):
|
|
45
|
+
"""
|
|
46
|
+
Check configuration
|
|
47
|
+
|
|
48
|
+
:param conf: configuration to check
|
|
49
|
+
|
|
50
|
+
:return: overloaded configuration
|
|
51
|
+
:rtype: dict
|
|
52
|
+
"""
|
|
53
|
+
default_filling = {
|
|
54
|
+
"fill_with_geoid": "b0",
|
|
55
|
+
"interpolate_from_borders": "b1",
|
|
56
|
+
"fill_with_endogenous_dem": "b2",
|
|
57
|
+
"fill_with_exogenous_dem": "b3",
|
|
58
|
+
}
|
|
59
|
+
if isinstance(conf, str):
|
|
60
|
+
overloaded_conf = {}
|
|
61
|
+
image_path = make_relative_path_absolute(conf, self.config_dir)
|
|
62
|
+
overloaded_conf["path"] = image_path
|
|
63
|
+
overloaded_conf["loader"] = "basic_classif"
|
|
64
|
+
overloaded_conf["filling"] = default_filling
|
|
65
|
+
elif isinstance(conf, dict):
|
|
66
|
+
overloaded_conf = conf.copy()
|
|
67
|
+
image_path = make_relative_path_absolute(
|
|
68
|
+
conf["path"], self.config_dir
|
|
69
|
+
)
|
|
70
|
+
overloaded_conf["path"] = image_path
|
|
71
|
+
overloaded_conf["loader"] = conf.get("loader", "basic")
|
|
72
|
+
overloaded_conf["filling"] = conf.get("filling", default_filling)
|
|
73
|
+
else:
|
|
74
|
+
raise TypeError(f"Input {conf} is not a string ot dict")
|
|
75
|
+
|
|
76
|
+
sensor_schema = {"loader": str, "path": str, "filling": dict}
|
|
77
|
+
|
|
78
|
+
# Check conf
|
|
79
|
+
checker = Checker(sensor_schema)
|
|
80
|
+
checker.validate(overloaded_conf)
|
|
81
|
+
|
|
82
|
+
return overloaded_conf
|
|
83
|
+
|
|
84
|
+
def set_pivot_format(self):
|
|
85
|
+
"""
|
|
86
|
+
Transform input configuration to pivot format and store it
|
|
87
|
+
"""
|
|
88
|
+
pivot_config = {
|
|
89
|
+
"loader": "pivot_classif",
|
|
90
|
+
"main_file": self.used_config["path"],
|
|
91
|
+
"filling": self.used_config["filling"],
|
|
92
|
+
}
|
|
93
|
+
pivot_config["bands"] = {}
|
|
94
|
+
for band_id in range(
|
|
95
|
+
inputs.rasterio_get_nb_bands(self.used_config["path"])
|
|
96
|
+
):
|
|
97
|
+
band_name = "b" + str(band_id)
|
|
98
|
+
pivot_config["bands"][band_name] = {
|
|
99
|
+
"path": self.used_config["path"],
|
|
100
|
+
"band": band_id,
|
|
101
|
+
}
|
|
102
|
+
pivot_config["texture_bands"] = None
|
|
103
|
+
pivot_sensor_loader = PivotClassifSensorLoader(
|
|
104
|
+
pivot_config, self.config_dir
|
|
105
|
+
)
|
|
106
|
+
self.pivot_format = pivot_sensor_loader.get_pivot_format()
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
# limitations under the License.
|
|
20
20
|
#
|
|
21
21
|
"""
|
|
22
|
-
|
|
22
|
+
This module contains the BasicImageSensorLoader class.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
from json_checker import Checker, Or
|
|
@@ -27,8 +27,8 @@ from json_checker import Checker, Or
|
|
|
27
27
|
from cars.core import inputs
|
|
28
28
|
from cars.core.utils import make_relative_path_absolute
|
|
29
29
|
from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
|
|
30
|
-
from cars.pipelines.parameters.sensor_loaders.
|
|
31
|
-
|
|
30
|
+
from cars.pipelines.parameters.sensor_loaders.pivot_image_loader import (
|
|
31
|
+
PivotImageSensorLoader,
|
|
32
32
|
)
|
|
33
33
|
from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
|
|
34
34
|
from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
|
|
@@ -36,10 +36,10 @@ from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
|
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
@SensorLoader.register("
|
|
40
|
-
class
|
|
39
|
+
@SensorLoader.register("basic_image")
|
|
40
|
+
class BasicImageSensorLoader(SensorLoaderTemplate):
|
|
41
41
|
"""
|
|
42
|
-
Default sensor loader (used when no sensor loader is specified)
|
|
42
|
+
Default sensor loader for image (used when no sensor loader is specified)
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
45
|
def check_conf(self, conf):
|
|
@@ -55,26 +55,20 @@ class BasicSensorLoader(SensorLoaderTemplate):
|
|
|
55
55
|
overloaded_conf = {}
|
|
56
56
|
image_path = make_relative_path_absolute(conf, self.config_dir)
|
|
57
57
|
overloaded_conf["path"] = image_path
|
|
58
|
-
overloaded_conf["loader"] = "
|
|
59
|
-
|
|
60
|
-
overloaded_conf[sens_cst.INPUT_NODATA] = 0
|
|
61
|
-
else:
|
|
62
|
-
overloaded_conf[sens_cst.INPUT_NODATA] = None
|
|
58
|
+
overloaded_conf["loader"] = "basic_image"
|
|
59
|
+
overloaded_conf[sens_cst.INPUT_NODATA] = 0
|
|
63
60
|
elif isinstance(conf, dict):
|
|
64
61
|
overloaded_conf = conf.copy()
|
|
65
62
|
image_path = make_relative_path_absolute(
|
|
66
63
|
conf["path"], self.config_dir
|
|
67
64
|
)
|
|
68
65
|
overloaded_conf["path"] = image_path
|
|
69
|
-
overloaded_conf["loader"] = conf.get("loader", "
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
else:
|
|
75
|
-
overloaded_conf[sens_cst.INPUT_NODATA] = None
|
|
66
|
+
overloaded_conf["loader"] = conf.get("loader", "basic_image")
|
|
67
|
+
overloaded_conf[sens_cst.INPUT_NODATA] = conf.get(
|
|
68
|
+
sens_cst.INPUT_NODATA, 0
|
|
69
|
+
)
|
|
76
70
|
else:
|
|
77
|
-
raise TypeError(f"Input {
|
|
71
|
+
raise TypeError(f"Input {conf} is not a string ot dict")
|
|
78
72
|
|
|
79
73
|
sensor_schema = {"loader": str, "path": str, "no_data": Or(None, int)}
|
|
80
74
|
|
|
@@ -89,7 +83,7 @@ class BasicSensorLoader(SensorLoaderTemplate):
|
|
|
89
83
|
Transform input configuration to pivot format and store it
|
|
90
84
|
"""
|
|
91
85
|
pivot_config = {
|
|
92
|
-
"loader": "
|
|
86
|
+
"loader": "pivot_image",
|
|
93
87
|
"main_file": self.used_config["path"],
|
|
94
88
|
}
|
|
95
89
|
pivot_config["bands"] = {}
|
|
@@ -102,7 +96,7 @@ class BasicSensorLoader(SensorLoaderTemplate):
|
|
|
102
96
|
"band": band_id,
|
|
103
97
|
}
|
|
104
98
|
pivot_config["texture_bands"] = None
|
|
105
|
-
pivot_sensor_loader =
|
|
106
|
-
pivot_config, self.
|
|
99
|
+
pivot_sensor_loader = PivotImageSensorLoader(
|
|
100
|
+
pivot_config, self.config_dir
|
|
107
101
|
)
|
|
108
102
|
self.pivot_format = pivot_sensor_loader.get_pivot_format()
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES).
|
|
5
|
+
#
|
|
6
|
+
# This file is part of CARS
|
|
7
|
+
# (see https://github.com/CNES/cars).
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
"""
|
|
22
|
+
this module contains the PivotImageSensorLoader class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from json_checker import Checker, Or
|
|
26
|
+
|
|
27
|
+
from cars.core import inputs
|
|
28
|
+
from cars.core.utils import make_relative_path_absolute
|
|
29
|
+
from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
|
|
30
|
+
from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
|
|
31
|
+
SensorLoaderTemplate,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@SensorLoader.register("pivot_classif")
|
|
36
|
+
class PivotClassifSensorLoader(SensorLoaderTemplate):
|
|
37
|
+
"""
|
|
38
|
+
Pivot image sensor loader : used by CARS to read inputs
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def check_conf(self, conf):
|
|
42
|
+
"""
|
|
43
|
+
Check configuration
|
|
44
|
+
|
|
45
|
+
:param conf: configuration to check
|
|
46
|
+
|
|
47
|
+
:return: overloaded configuration
|
|
48
|
+
:rtype: dict
|
|
49
|
+
"""
|
|
50
|
+
default_filling = {
|
|
51
|
+
"fill_with_geoid": "b0",
|
|
52
|
+
"interpolate_from_borders": "b1",
|
|
53
|
+
"fill_with_endogenous_dem": "b2",
|
|
54
|
+
"fill_with_exogenous_dem": "b3",
|
|
55
|
+
}
|
|
56
|
+
overloaded_conf = conf.copy()
|
|
57
|
+
# Make relative paths absolutes
|
|
58
|
+
for band in overloaded_conf["bands"]:
|
|
59
|
+
overloaded_conf["bands"][band]["path"] = (
|
|
60
|
+
make_relative_path_absolute(
|
|
61
|
+
overloaded_conf["bands"][band]["path"], self.config_dir
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
# Check consistency between files
|
|
65
|
+
b0_path = overloaded_conf["bands"]["b0"]["path"]
|
|
66
|
+
b0_size = inputs.rasterio_get_size(b0_path)
|
|
67
|
+
b0_transform = inputs.rasterio_get_transform(b0_path)
|
|
68
|
+
for band in overloaded_conf["bands"]:
|
|
69
|
+
band_path = overloaded_conf["bands"][band]["path"]
|
|
70
|
+
band_id = overloaded_conf["bands"][band]["band"]
|
|
71
|
+
nb_bands = inputs.rasterio_get_nb_bands(band_path)
|
|
72
|
+
if band_id >= nb_bands:
|
|
73
|
+
raise RuntimeError(
|
|
74
|
+
"Band id {} is not valid for sensor which "
|
|
75
|
+
"has only {} bands".format(band_id, nb_bands)
|
|
76
|
+
)
|
|
77
|
+
if band_path != b0_path:
|
|
78
|
+
band_size = inputs.rasterio_get_size(band_path)
|
|
79
|
+
band_transform = inputs.rasterio_get_transform(band_path)
|
|
80
|
+
if b0_size != band_size:
|
|
81
|
+
raise RuntimeError(
|
|
82
|
+
"The files {} and {} do not have the same size"
|
|
83
|
+
"but are in the same image".format(b0_path, band_path)
|
|
84
|
+
)
|
|
85
|
+
if b0_transform != band_transform:
|
|
86
|
+
raise RuntimeError(
|
|
87
|
+
"The files {} and {} do not have the same size"
|
|
88
|
+
"but are in the same image".format(
|
|
89
|
+
b0_transform,
|
|
90
|
+
band_transform,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
overloaded_conf["main_file"] = overloaded_conf["bands"]["b0"]["path"]
|
|
94
|
+
overloaded_conf["filling"] = conf.get("filling", default_filling)
|
|
95
|
+
overloaded_conf["texture_bands"] = conf.get("texture_bands", None)
|
|
96
|
+
if overloaded_conf["texture_bands"] is not None:
|
|
97
|
+
for texture_band in overloaded_conf["texture_bands"]:
|
|
98
|
+
if texture_band not in overloaded_conf["bands"]:
|
|
99
|
+
raise RuntimeError(
|
|
100
|
+
"Texture band {} not found in bands {} "
|
|
101
|
+
"of sensor image".format(
|
|
102
|
+
texture_band, overloaded_conf["bands"]
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
sensor_schema = {
|
|
107
|
+
"loader": str,
|
|
108
|
+
"main_file": str,
|
|
109
|
+
"bands": dict,
|
|
110
|
+
"filling": dict,
|
|
111
|
+
"texture_bands": Or(None, [str]),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# Check conf
|
|
115
|
+
checker = Checker(sensor_schema)
|
|
116
|
+
checker.validate(overloaded_conf)
|
|
117
|
+
|
|
118
|
+
return overloaded_conf
|
|
119
|
+
|
|
120
|
+
def set_pivot_format(self):
|
|
121
|
+
self.pivot_format = self.used_config
|