cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a3__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.

Files changed (53) hide show
  1. cars/applications/application.py +14 -6
  2. cars/applications/application_template.py +22 -0
  3. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +15 -10
  4. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  5. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  6. cars/applications/dem_generation/dem_generation_wrappers.py +46 -27
  7. cars/applications/dem_generation/dichotomic_generation_app.py +6 -3
  8. cars/applications/dem_generation/rasterization_app.py +15 -5
  9. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.dll.a +0 -0
  10. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.pyd +0 -0
  11. cars/applications/dense_matching/census_mccnn_sgm_app.py +11 -22
  12. cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
  13. cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.pyd +0 -0
  14. cars/applications/dense_matching/disparity_grid_algo.py +26 -32
  15. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  16. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  17. cars/applications/dense_matching/loaders/pandora_loader.py +78 -1
  18. cars/applications/dsm_filling/border_interpolation_app.py +10 -5
  19. cars/applications/dsm_filling/bulldozer_filling_app.py +14 -7
  20. cars/applications/dsm_filling/exogenous_filling_app.py +10 -5
  21. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +9 -5
  22. cars/applications/point_cloud_outlier_removal/small_components_app.py +5 -3
  23. cars/applications/point_cloud_outlier_removal/statistical_app.py +4 -2
  24. cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -0
  25. cars/applications/rasterization/simple_gaussian_app.py +28 -3
  26. cars/applications/resampling/resampling_algo.py +44 -49
  27. cars/applications/sparse_matching/sift_app.py +2 -22
  28. cars/core/geometry/abstract_geometry.py +113 -2
  29. cars/core/geometry/shareloc_geometry.py +2 -0
  30. cars/core/inputs.py +15 -0
  31. cars/core/projection.py +117 -0
  32. cars/data_structures/cars_dataset.py +7 -5
  33. cars/orchestrator/cluster/log_wrapper.py +1 -1
  34. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +1 -1
  35. cars/orchestrator/orchestrator.py +1 -1
  36. cars/pipelines/default/default_pipeline.py +46 -26
  37. cars/pipelines/parameters/advanced_parameters.py +17 -0
  38. cars/pipelines/parameters/advanced_parameters_constants.py +4 -0
  39. cars/pipelines/parameters/output_parameters.py +44 -8
  40. cars/pipelines/parameters/sensor_inputs.py +97 -3
  41. cars/pipelines/unit/unit_pipeline.py +194 -99
  42. cars-1.0.0a3.dist-info/DELVEWHEEL +2 -0
  43. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/METADATA +1 -1
  44. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/RECORD +49 -47
  45. cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
  46. cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
  47. cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
  48. cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
  49. cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
  50. cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
  51. cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
  52. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/WHEEL +0 -0
  53. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/entry_points.txt +0 -0
@@ -60,6 +60,10 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
60
60
  adv_cst.SAVE_INTERMEDIATE_DATA, False
61
61
  )
62
62
 
63
+ overloaded_conf[adv_cst.LAND_COVER_MAP] = conf.get(
64
+ adv_cst.LAND_COVER_MAP, "global_land_cover_map.tif"
65
+ )
66
+
63
67
  overloaded_conf[adv_cst.KEEP_LOW_RES_DIR] = conf.get(
64
68
  adv_cst.KEEP_LOW_RES_DIR, True
65
69
  )
@@ -68,6 +72,10 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
68
72
  adv_cst.DEBUG_WITH_ROI, False
69
73
  )
70
74
 
75
+ overloaded_conf[adv_cst.CLASSIFICATION_TO_CONFIGURATION_MAPPING] = conf.get(
76
+ adv_cst.CLASSIFICATION_TO_CONFIGURATION_MAPPING, "config_mapping.json"
77
+ )
78
+
71
79
  overloaded_conf[adv_cst.PHASING] = conf.get(adv_cst.PHASING, None)
72
80
 
73
81
  overloaded_conf[adv_cst.EPIPOLAR_RESOLUTIONS] = conf.get(
@@ -144,6 +152,7 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
144
152
  ]
145
153
  )
146
154
 
155
+ scaling_coeff = None
147
156
  if inputs[sens_cst.SENSORS] is not None:
148
157
  # Check geometry plugin and overwrite geomodel in conf inputs
149
158
  (
@@ -152,10 +161,13 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
152
161
  geom_plugin_without_dem_and_geoid,
153
162
  geom_plugin_with_dem_and_geoid,
154
163
  dem_generation_roi,
164
+ scaling_coeff,
155
165
  ) = sensor_inputs.check_geometry_plugin(
156
166
  inputs, conf.get(adv_cst.GEOMETRY_PLUGIN, None)
157
167
  )
158
168
  elif depth_cst.DEPTH_MAPS in inputs or dsm_cst.DSMS in inputs:
169
+ # assume the input comes from 0.5m sensor images
170
+ scaling_coeff = 1
159
171
  # If there's an initial elevation with
160
172
  # point clouds as inputs, generate a plugin (used in dsm_filling)
161
173
  (
@@ -182,6 +194,8 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
182
194
  adv_cst.DSM_MERGING_TILE_SIZE: And(int, lambda x: x > 0),
183
195
  adv_cst.TEXTURE_BANDS: list,
184
196
  adv_cst.EPIPOLAR_RESOLUTIONS: Or(int, list),
197
+ adv_cst.LAND_COVER_MAP: str,
198
+ adv_cst.CLASSIFICATION_TO_CONFIGURATION_MAPPING: str,
185
199
  }
186
200
  if check_epipolar_a_priori:
187
201
  schema[adv_cst.USE_EPIPOLAR_A_PRIORI] = bool
@@ -245,6 +259,9 @@ def check_advanced_parameters(inputs, conf, check_epipolar_a_priori=True):
245
259
  geom_plugin_without_dem_and_geoid,
246
260
  geom_plugin_with_dem_and_geoid,
247
261
  dem_generation_roi,
262
+ scaling_coeff,
263
+ overloaded_conf[adv_cst.LAND_COVER_MAP],
264
+ overloaded_conf[adv_cst.CLASSIFICATION_TO_CONFIGURATION_MAPPING],
248
265
  )
249
266
 
250
267
 
@@ -27,6 +27,10 @@ SAVE_INTERMEDIATE_DATA = "save_intermediate_data"
27
27
  KEEP_LOW_RES_DIR = "keep_low_res_dir"
28
28
  PHASING = "phasing"
29
29
  DEBUG_WITH_ROI = "debug_with_roi"
30
+ LAND_COVER_MAP = "land_cover_map"
31
+ CLASSIFICATION_TO_CONFIGURATION_MAPPING = (
32
+ "classification_to_configuration_mapping"
33
+ )
30
34
 
31
35
  USE_EPIPOLAR_A_PRIORI = "use_epipolar_a_priori"
32
36
  EPIPOLAR_A_PRIORI = "epipolar_a_priori"
@@ -26,7 +26,7 @@ This module contains the output definition
26
26
  import logging
27
27
  import os
28
28
 
29
- from json_checker import Checker, Or
29
+ from json_checker import And, Checker, Or
30
30
  from pyproj import CRS
31
31
 
32
32
  import cars.core.constants as cst
@@ -34,12 +34,29 @@ from cars.core.utils import safe_makedirs
34
34
  from cars.pipelines.parameters import output_constants
35
35
 
36
36
 
37
- def check_output_parameters(conf):
37
+ def is_valid_epsg(epsg) -> bool:
38
+ """
39
+ Check if the given EPSG code is valid using pyproj.
40
+ """
41
+ if epsg is None:
42
+ return True
43
+
44
+ try:
45
+ # Try creating a CRS
46
+ CRS(f"EPSG:{epsg}")
47
+ return True
48
+ except Exception:
49
+ return False
50
+
51
+
52
+ def check_output_parameters(conf, scaling_coeff):
38
53
  """
39
54
  Check the output json configuration and fill in default values
40
55
 
41
56
  :param conf: configuration of output
42
57
  :type conf: dict
58
+ :param scaling_coeff: scaling factor for resolution
59
+ :type scaling_coeff: float
43
60
  :param pipeline_name: name of corresponding pipeline
44
61
  :type pipeline_name: str
45
62
  """
@@ -64,15 +81,34 @@ def check_output_parameters(conf):
64
81
  raise RuntimeError("Unknown product level {}".format(level))
65
82
 
66
83
  overloaded_conf[output_constants.OUT_GEOID] = overloaded_conf.get(
67
- output_constants.OUT_GEOID, False
84
+ output_constants.OUT_GEOID, True
68
85
  )
69
86
  overloaded_conf[output_constants.EPSG] = overloaded_conf.get(
70
87
  output_constants.EPSG, None
71
88
  )
72
89
 
73
- overloaded_conf[output_constants.RESOLUTION] = overloaded_conf.get(
74
- output_constants.RESOLUTION, 0.5
75
- )
90
+ resolution = None
91
+ overloaded_scaling_coeff = scaling_coeff
92
+ if output_constants.RESOLUTION in overloaded_conf:
93
+ resolution = overloaded_conf[output_constants.RESOLUTION]
94
+ # update scaling coeff so the parameters are right for the dsm
95
+ # overloaded_scaling_coeff = 2*resolution
96
+
97
+ if resolution < 0.5 * scaling_coeff:
98
+ logging.warning(
99
+ "The requested DSM resolution of "
100
+ f"{overloaded_conf[output_constants.RESOLUTION]} seems "
101
+ "too low for the sensor images' resolution. "
102
+ "The pipeline will still continue with it."
103
+ )
104
+
105
+ else:
106
+ resolution = float(0.5 * scaling_coeff)
107
+ logging.warning(
108
+ "The resolution of the output DSM will be " f"{resolution} meters. "
109
+ )
110
+
111
+ overloaded_conf[output_constants.RESOLUTION] = resolution
76
112
 
77
113
  overloaded_conf[output_constants.SAVE_BY_PAIR] = overloaded_conf.get(
78
114
  output_constants.SAVE_BY_PAIR, False
@@ -145,7 +181,7 @@ def check_output_parameters(conf):
145
181
  output_constants.OUT_DIRECTORY: str,
146
182
  output_constants.PRODUCT_LEVEL: list,
147
183
  output_constants.OUT_GEOID: Or(bool, str),
148
- output_constants.EPSG: Or(int, None),
184
+ output_constants.EPSG: And(Or(int, str, None), is_valid_epsg),
149
185
  output_constants.RESOLUTION: Or(int, float),
150
186
  output_constants.SAVE_BY_PAIR: bool,
151
187
  output_constants.AUXILIARY: dict,
@@ -181,7 +217,7 @@ def check_output_parameters(conf):
181
217
  + "fixed according to the epsg"
182
218
  )
183
219
 
184
- return overloaded_conf
220
+ return overloaded_conf, overloaded_scaling_coeff
185
221
 
186
222
 
187
223
  def intialize_product_index(orchestrator, product_levels, input_pairs):
@@ -24,13 +24,15 @@ 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
32
  from json_checker import Checker, OptionalKey, Or
31
33
 
32
34
  # CARS imports
33
- from cars.core import inputs, preprocessing, roi_tools
35
+ from cars.core import inputs, preprocessing, projection, roi_tools
34
36
  from cars.core.geometry.abstract_geometry import AbstractGeometry
35
37
  from cars.core.utils import make_relative_path_absolute
36
38
  from cars.pipelines.parameters import (
@@ -235,6 +237,65 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
235
237
  return overloaded_conf
236
238
 
237
239
 
240
+ def get_sensor_resolution(
241
+ geom_plugin, sensor_path, geomodel, target_epsg=32631
242
+ ):
243
+ """
244
+ Estimate the sensor image resolution in meters per pixel
245
+ using geolocation of 3 corners of the image.
246
+
247
+ :param geom_plugin: geometry plugin instance
248
+ :param sensor_path: path to the sensor image
249
+ :type sensor_path: dict
250
+ :param geomodel: geometric model for the sensor image
251
+ :param target_epsg: target EPSG code for projection
252
+ :type target_epsg: int
253
+ :return: average resolution in meters/pixel along x and y
254
+ :rtype: float
255
+ """
256
+ width, height = inputs.rasterio_get_size(sensor_path[sens_cst.MAIN_FILE])
257
+
258
+ upper_left = (0.5, 0.5)
259
+ upper_right = (width - 0.5, 0.5)
260
+ bottom_left = (0.5, height - 0.5)
261
+
262
+ # get geodetic coordinates
263
+ lat_ul, lon_ul, _ = geom_plugin.direct_loc(
264
+ sensor_path[sens_cst.MAIN_FILE],
265
+ geomodel,
266
+ np.array([upper_left[0]]),
267
+ np.array([upper_left[1]]),
268
+ )
269
+ lat_ur, lon_ur, _ = geom_plugin.direct_loc(
270
+ sensor_path[sens_cst.MAIN_FILE],
271
+ geomodel,
272
+ np.array([upper_right[0]]),
273
+ np.array([upper_right[1]]),
274
+ )
275
+ lat_bl, lon_bl, _ = geom_plugin.direct_loc(
276
+ sensor_path[sens_cst.MAIN_FILE],
277
+ geomodel,
278
+ np.array([bottom_left[0]]),
279
+ np.array([bottom_left[1]]),
280
+ )
281
+
282
+ coords_ll = np.array(
283
+ [[lon_ul, lat_ul, 0], [lon_ur, lat_ur, 0], [lon_bl, lat_bl, 0]]
284
+ )
285
+
286
+ # Convert to target CRS
287
+ coords_xy = projection.point_cloud_conversion(coords_ll, 4326, target_epsg)
288
+
289
+ diff_x = np.linalg.norm(coords_xy[1] - coords_xy[0]) # UL to UR (width)
290
+ diff_y = np.linalg.norm(coords_xy[2] - coords_xy[0]) # UL to BL (height)
291
+
292
+ # resolution in meters per pixel
293
+ res_x = diff_x / (width - 1)
294
+ res_y = diff_y / (height - 1)
295
+
296
+ return (res_x + res_y) / 2
297
+
298
+
238
299
  def check_geometry_plugin(conf_inputs, conf_geom_plugin):
239
300
  """
240
301
  Check the geometry plugin with inputs
@@ -253,11 +314,40 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
253
314
  if conf_geom_plugin is None:
254
315
  conf_geom_plugin = "SharelocGeometry"
255
316
 
317
+ # Initialize a temporary plugin, to get the product's resolution
318
+ temp_geom_plugin = (
319
+ AbstractGeometry( # pylint: disable=abstract-class-instantiated
320
+ conf_geom_plugin,
321
+ default_alt=sens_cst.CARS_DEFAULT_ALT,
322
+ )
323
+ )
324
+ average_sensor_resolution = 0
325
+ for _, sensor_image in conf_inputs[sens_cst.SENSORS].items():
326
+ sensor = sensor_image[sens_cst.INPUT_IMG]
327
+ geomodel = sensor_image[sens_cst.INPUT_GEO_MODEL]
328
+ (
329
+ sensor,
330
+ geomodel,
331
+ ) = temp_geom_plugin.check_product_consistency(sensor, geomodel)
332
+ average_sensor_resolution += get_sensor_resolution(
333
+ temp_geom_plugin, sensor, geomodel
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,7 +370,7 @@ 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, conf_inputs
373
+ conf_geom_plugin, conf_inputs, scaling_coeff=scaling_coeff
284
374
  )
285
375
 
286
376
  # Check dem is big enough
@@ -344,11 +434,12 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
344
434
  geom_plugin_without_dem_and_geoid,
345
435
  geom_plugin_with_dem_and_geoid,
346
436
  dem_generation_roi_poly,
437
+ scaling_coeff,
347
438
  )
348
439
 
349
440
 
350
441
  def generate_geometry_plugin_with_dem(
351
- conf_geom_plugin, conf_inputs, dem=None, crop_dem=True
442
+ conf_geom_plugin, conf_inputs, dem=None, crop_dem=True, scaling_coeff=1
352
443
  ):
353
444
  """
354
445
  Generate geometry plugin with dem and geoid
@@ -356,6 +447,8 @@ def generate_geometry_plugin_with_dem(
356
447
  :param conf_geom_plugin: plugin configuration
357
448
  :param conf_inputs: inputs configuration
358
449
  :param dem: dem to overide the one in inputs
450
+ :param scaling_coeff: scaling factor for resolution
451
+ :type scaling_coeff: float
359
452
 
360
453
  :return: geometry plugin object, with a dem
361
454
  """
@@ -389,6 +482,7 @@ def generate_geometry_plugin_with_dem(
389
482
  geoid=conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.GEOID],
390
483
  default_alt=sens_cst.CARS_DEFAULT_ALT,
391
484
  pairs_for_roi=pairs_for_roi,
485
+ scaling_coeff=scaling_coeff,
392
486
  )
393
487
  )
394
488