cars 0.12.0rc2__cp311-cp311-win_amd64.whl → 1.0.0a2__cp311-cp311-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 (144) hide show
  1. cars/__init__.py +4 -4
  2. cars/applications/auxiliary_filling/__init__.py +2 -2
  3. cars/applications/auxiliary_filling/{auxiliary_filling_tools.py → auxiliary_filling_algo.py} +129 -170
  4. cars/applications/auxiliary_filling/{auxiliary_filling_from_sensors.py → auxiliary_filling_from_sensors_app.py} +34 -21
  5. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +89 -0
  6. cars/applications/dem_generation/__init__.py +4 -2
  7. cars/applications/dem_generation/dem_generation_algo.py +232 -0
  8. cars/applications/dem_generation/dem_generation_wrappers.py +380 -0
  9. cars/applications/dem_generation/{dichotomic_generation.py → dichotomic_generation_app.py} +30 -175
  10. cars/applications/dem_generation/rasterization_app.py +538 -0
  11. cars/applications/dense_match_filling/__init__.py +2 -2
  12. cars/applications/dense_match_filling/{dense_match_filling.py → abstract_dense_match_filling_app.py} +5 -1
  13. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.dll.a +0 -0
  14. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.pyd +0 -0
  15. cars/applications/dense_match_filling/fill_disp_algo.py +457 -0
  16. cars/applications/dense_match_filling/fill_disp_wrappers.py +426 -0
  17. cars/applications/dense_match_filling/{plane.py → plane_app.py} +27 -13
  18. cars/applications/dense_match_filling/{zero_padding.py → zero_padding_app.py} +19 -6
  19. cars/applications/dense_matching/__init__.py +4 -2
  20. cars/applications/dense_matching/{dense_matching.py → abstract_dense_matching_app.py} +7 -3
  21. cars/applications/dense_matching/{census_mccnn_sgm.py → census_mccnn_sgm_app.py} +404 -546
  22. cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.dll.a +0 -0
  23. cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.pyd +0 -0
  24. cars/applications/dense_matching/cpp/dense_matching_cpp.py +11 -2
  25. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +4 -2
  26. cars/applications/dense_matching/cpp/src/dense_matching.cpp +25 -8
  27. cars/applications/dense_matching/dense_matching_algo.py +304 -0
  28. cars/applications/dense_matching/{dense_matching_tools.py → dense_matching_wrappers.py} +161 -243
  29. cars/applications/dense_matching/disparity_grid_algo.py +572 -0
  30. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +2 -1
  31. cars/applications/dense_matching/loaders/pandora_loader.py +13 -11
  32. cars/applications/dsm_filling/__init__.py +6 -2
  33. cars/applications/dsm_filling/{border_interpolation.py → border_interpolation_app.py} +1 -1
  34. cars/applications/dsm_filling/{bulldozer_filling.py → bulldozer_filling_app.py} +1 -1
  35. cars/applications/dsm_filling/{exogenous_filling.py → exogenous_filling_app.py} +1 -1
  36. cars/applications/grid_generation/__init__.py +4 -2
  37. cars/applications/grid_generation/{epipolar_grid_generation.py → epipolar_grid_generation_app.py} +29 -46
  38. cars/applications/grid_generation/{grid_correction.py → grid_correction_app.py} +52 -104
  39. cars/applications/grid_generation/{grids.py → grid_generation_algo.py} +8 -13
  40. cars/applications/grid_generation/{grid_constants.py → grid_generation_constants.py} +2 -1
  41. cars/applications/grid_generation/transform_grid.py +88 -0
  42. cars/applications/ground_truth_reprojection/__init__.py +2 -2
  43. cars/applications/ground_truth_reprojection/{ground_truth_reprojection.py → abstract_ground_truth_reprojection_app.py} +1 -1
  44. cars/applications/ground_truth_reprojection/{direct_localization.py → direct_localization_app.py} +15 -12
  45. cars/applications/ground_truth_reprojection/{ground_truth_reprojection_tools.py → ground_truth_reprojection_algo.py} +2 -2
  46. cars/applications/hole_detection/__init__.py +4 -2
  47. cars/applications/hole_detection/{cloud_to_bbox.py → cloud_to_bbox_app.py} +9 -7
  48. cars/applications/hole_detection/{hole_detection_tools.py → hole_detection_algo.py} +4 -27
  49. cars/applications/hole_detection/hole_detection_wrappers.py +53 -0
  50. cars/applications/point_cloud_denoising/__init__.py +2 -2
  51. cars/applications/point_cloud_fusion/__init__.py +2 -2
  52. cars/applications/point_cloud_fusion/{point_cloud_fusion.py → abstract_pc_fusion_app.py} +1 -1
  53. cars/applications/point_cloud_fusion/{mapping_to_terrain_tiles.py → mapping_to_terrain_tiles_app.py} +12 -12
  54. cars/applications/point_cloud_fusion/{pc_tif_tools.py → pc_fusion_algo.py} +519 -434
  55. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +869 -0
  56. cars/applications/point_cloud_outlier_removal/__init__.py +2 -2
  57. cars/applications/point_cloud_outlier_removal/{pc_out_removal.py → abstract_outlier_removal_app.py} +1 -1
  58. cars/applications/point_cloud_outlier_removal/{outlier_removal_tools.py → outlier_removal_algo.py} +1 -6
  59. cars/applications/point_cloud_outlier_removal/{small_components.py → small_components_app.py} +37 -18
  60. cars/applications/point_cloud_outlier_removal/{statistical.py → statistical_app.py} +11 -10
  61. cars/applications/rasterization/__init__.py +2 -2
  62. cars/applications/rasterization/rasterization_algo.py +522 -0
  63. cars/applications/rasterization/rasterization_constants.py +1 -1
  64. cars/applications/rasterization/{rasterization_tools.py → rasterization_wrappers.py} +10 -496
  65. cars/applications/rasterization/{simple_gaussian.py → simple_gaussian_app.py} +50 -45
  66. cars/applications/resampling/__init__.py +2 -2
  67. cars/applications/resampling/{resampling.py → abstract_resampling_app.py} +12 -3
  68. cars/applications/resampling/{bicubic_resampling.py → bicubic_resampling_app.py} +102 -382
  69. cars/applications/resampling/resampling_algo.py +563 -0
  70. cars/applications/resampling/resampling_wrappers.py +296 -0
  71. cars/applications/sparse_matching/__init__.py +4 -2
  72. cars/applications/sparse_matching/{sparse_matching.py → abstract_sparse_matching_app.py} +13 -11
  73. cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
  74. cars/applications/sparse_matching/{sift.py → sift_app.py} +79 -8
  75. cars/applications/sparse_matching/sparse_matching_algo.py +326 -0
  76. cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
  77. cars/applications/triangulation/__init__.py +4 -2
  78. cars/applications/triangulation/{triangulation.py → abstract_triangulation_app.py} +3 -3
  79. cars/applications/triangulation/{line_of_sight_intersection.py → line_of_sight_intersection_app.py} +50 -54
  80. cars/applications/triangulation/{triangulation_tools.py → triangulation_algo.py} +9 -232
  81. cars/applications/triangulation/triangulation_wrappers.py +258 -0
  82. cars/bundleadjustment.py +54 -13
  83. cars/cars.py +25 -9
  84. cars/core/constants.py +12 -6
  85. cars/core/datasets.py +13 -18
  86. cars/core/geometry/abstract_geometry.py +138 -84
  87. cars/core/geometry/shareloc_geometry.py +74 -31
  88. cars/core/inputs.py +10 -3
  89. cars/core/preprocessing.py +30 -42
  90. cars/core/projection.py +1 -0
  91. cars/data_structures/cars_dataset.py +2 -2
  92. cars/devibrate.py +1 -1
  93. cars/extractroi.py +44 -13
  94. cars/orchestrator/cluster/log_wrapper.py +7 -2
  95. cars/orchestrator/cluster/sequential_cluster.py +1 -1
  96. cars/orchestrator/orchestrator.py +18 -9
  97. cars/orchestrator/registry/saver_registry.py +0 -78
  98. cars/pipelines/conf_resolution/conf_final_resolution.json +7 -0
  99. cars/pipelines/conf_resolution/conf_first_resolution.json +1 -0
  100. cars/pipelines/conf_resolution/conf_intermediate_resolution.json +1 -0
  101. cars/pipelines/default/default_pipeline.py +470 -2185
  102. cars/pipelines/parameters/advanced_parameters.py +71 -3
  103. cars/pipelines/parameters/advanced_parameters_constants.py +6 -0
  104. cars/pipelines/parameters/depth_map_inputs.py +23 -68
  105. cars/pipelines/parameters/dsm_inputs.py +18 -30
  106. cars/pipelines/parameters/output_constants.py +5 -1
  107. cars/pipelines/parameters/output_parameters.py +23 -5
  108. cars/pipelines/parameters/sensor_inputs.py +89 -66
  109. cars/pipelines/parameters/sensor_inputs_constants.py +1 -1
  110. cars/pipelines/parameters/sensor_loaders/__init__.py +27 -0
  111. cars/pipelines/parameters/sensor_loaders/basic_sensor_loader.py +108 -0
  112. cars/pipelines/parameters/sensor_loaders/pivot_sensor_loader.py +130 -0
  113. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +95 -0
  114. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +73 -0
  115. cars/pipelines/pipeline.py +8 -8
  116. cars/pipelines/pipeline_template.py +3 -27
  117. cars/pipelines/unit/__init__.py +26 -0
  118. cars/pipelines/unit/unit_pipeline.py +3039 -0
  119. cars/starter.py +20 -1
  120. cars-1.0.0a2.dist-info/DELVEWHEEL +2 -0
  121. {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/METADATA +4 -3
  122. cars-1.0.0a2.dist-info/RECORD +222 -0
  123. cars.libs/{libgcc_s_seh-1-5dff426d781f17f961e57918b62ba809.dll → libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll} +0 -0
  124. cars.libs/{libstdc++-6-45391cced8aa80fea5519d684c730dc3.dll → libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll} +0 -0
  125. cars/applications/dem_generation/dem_generation_tools.py +0 -127
  126. cars/applications/dem_generation/rasterization.py +0 -769
  127. cars/applications/dense_match_filling/fill_disp_tools.py +0 -813
  128. cars/applications/point_cloud_fusion/point_cloud_tools.py +0 -934
  129. cars/applications/resampling/resampling_tools.py +0 -484
  130. cars/applications/sparse_matching/pandora_sparse_matching.py +0 -814
  131. cars/applications/sparse_matching/sparse_matching_tools.py +0 -910
  132. cars-0.12.0rc2.dist-info/DELVEWHEEL +0 -2
  133. cars-0.12.0rc2.dist-info/RECORD +0 -201
  134. /cars/applications/auxiliary_filling/{auxiliary_filling.py → abstract_auxiliary_filling_app.py} +0 -0
  135. /cars/applications/dem_generation/{dem_generation.py → abstract_dem_generation_app.py} +0 -0
  136. /cars/applications/dsm_filling/{dsm_filling.py → abstract_dsm_filling_app.py} +0 -0
  137. /cars/applications/grid_generation/{grid_generation.py → abstract_grid_generation_app.py} +0 -0
  138. /cars/applications/hole_detection/{hole_detection.py → abstract_hole_detection_app.py} +0 -0
  139. /cars/applications/point_cloud_denoising/{point_cloud_denoising.py → abstract_pc_denoising_app.py} +0 -0
  140. /cars/applications/point_cloud_outlier_removal/{point_removal_constants.py → outlier_removal_constants.py} +0 -0
  141. /cars/applications/rasterization/{point_cloud_rasterization.py → abstract_pc_rasterization_app.py} +0 -0
  142. {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/WHEEL +0 -0
  143. {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/entry_points.txt +0 -0
  144. /cars.libs/{libwinpthread-1-9fce0fc5eca62fc2578af36d8585939c.dll → libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll} +0 -0
cars/__init__.py CHANGED
@@ -24,14 +24,14 @@ Cars module init file
24
24
 
25
25
 
26
26
  # start delvewheel patch
27
- def _delvewheel_patch_1_10_1():
27
+ def _delvewheel_patch_1_11_1():
28
28
  import os
29
29
  if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'cars.libs'))):
30
30
  os.add_dll_directory(libs_dir)
31
31
 
32
32
 
33
- _delvewheel_patch_1_10_1()
34
- del _delvewheel_patch_1_10_1
33
+ _delvewheel_patch_1_11_1()
34
+ del _delvewheel_patch_1_11_1
35
35
  # end delvewheel patch
36
36
 
37
37
  import os
@@ -83,4 +83,4 @@ def import_plugins() -> None:
83
83
  entry_point.load()
84
84
 
85
85
 
86
- import_plugins()
86
+ import_plugins()
@@ -23,7 +23,7 @@ CARS auxiliary filling module init file
23
23
  """
24
24
  # flake8: noqa: F401
25
25
 
26
- import cars.applications.auxiliary_filling.auxiliary_filling
27
- from cars.applications.auxiliary_filling.auxiliary_filling_from_sensors import (
26
+ import cars.applications.auxiliary_filling.abstract_auxiliary_filling_app
27
+ from cars.applications.auxiliary_filling.auxiliary_filling_from_sensors_app import ( # pylint: disable=C0301
28
28
  AuxiliaryFilling,
29
29
  )
@@ -26,9 +26,6 @@ this module contains the AuxiliaryFillingFromSensors application class.
26
26
  import numpy as np
27
27
  import rasterio as rio
28
28
  from scipy import interpolate
29
- from shapely.geometry import Polygon
30
-
31
- from cars.core.projection import polygon_projection
32
29
 
33
30
 
34
31
  def fill_auxiliary(
@@ -40,7 +37,8 @@ def fill_auxiliary(
40
37
  geom_plugin,
41
38
  number_of_color_bands,
42
39
  number_of_classification_bands,
43
- color_interpolator,
40
+ texture_bands,
41
+ texture_interpolator,
44
42
  use_mask=False,
45
43
  ):
46
44
  """
@@ -63,9 +61,11 @@ def fill_auxiliary(
63
61
  :type number_of_color_bands: int
64
62
  :param number_of_classification_bands: number of bands in the color image
65
63
  :type number_of_classification_bands: int
66
- :param color_interpolator: scipy interpolator use to interpolate color
64
+ :param texture_bands: list of band names used for output texture
65
+ :type texture_bands: list
66
+ :param texture_interpolator: scipy interpolator use to interpolate color
67
67
  values
68
- :type color_interpolator: str
68
+ :type texture_interpolator: str
69
69
  :param use_mask: use mask information from sensors in color computation
70
70
  :type use_mask: bool
71
71
 
@@ -107,7 +107,8 @@ def fill_auxiliary(
107
107
  geom_plugin,
108
108
  number_of_color_bands,
109
109
  number_of_classification_bands,
110
- color_interpolator,
110
+ texture_bands,
111
+ texture_interpolator,
111
112
  not_interpolated_mask=None,
112
113
  use_mask=use_mask,
113
114
  return_all_points=True,
@@ -132,7 +133,8 @@ def fill_auxiliary(
132
133
  geom_plugin,
133
134
  number_of_color_bands,
134
135
  number_of_classification_bands,
135
- color_interpolator,
136
+ texture_bands,
137
+ texture_interpolator,
136
138
  not_interpolated_mask,
137
139
  use_mask=use_mask,
138
140
  return_all_points=False,
@@ -165,7 +167,8 @@ def fill_from_one_sensor( # noqa C901
165
167
  geom_plugin,
166
168
  number_of_color_bands,
167
169
  number_of_classification_bands,
168
- color_interpolator,
170
+ texture_bands,
171
+ texture_interpolator,
169
172
  not_interpolated_mask=None,
170
173
  use_mask=False,
171
174
  return_all_points=False,
@@ -194,9 +197,11 @@ def fill_from_one_sensor( # noqa C901
194
197
  :type number_of_color_bands: int
195
198
  :param number_of_classification_bands: number of bands in the color image
196
199
  :type number_of_classification_bands: int
197
- :param color_interpolator: scipy interpolator use to interpolate color
200
+ :param texture_bands: list of band names used for output texture
201
+ :type texture_bands: list
202
+ :param texture_interpolator: scipy interpolator use to interpolate color
198
203
  values
199
- :type color_interpolator: str
204
+ :type texture_interpolator: str
200
205
  :param not_interpolated_mask: use mask information in color computation
201
206
  :type not_interpolated_mask: numpy.array
202
207
  :param use_mask: use mask information in color computation
@@ -207,9 +212,7 @@ def fill_from_one_sensor( # noqa C901
207
212
  """
208
213
 
209
214
  # Check if the sensor has color or classification
210
- reference_sensor_image = sensor.get(
211
- "color", sensor.get("classification", None)
212
- )
215
+ reference_sensor_image = sensor["image"]["main_file"]
213
216
 
214
217
  output_not_interpolated_mask = np.ones(len(altitudes), dtype=bool)
215
218
  all_values = np.zeros((number_of_color_bands, len(altitudes)))
@@ -251,12 +254,12 @@ def fill_from_one_sensor( # noqa C901
251
254
  ):
252
255
  return output_not_interpolated_mask, all_values
253
256
 
254
- if color_interpolator in ("linear", "nearest"):
255
- color_interpolator_margin = 1
256
- elif color_interpolator == "cubic":
257
- color_interpolator_margin = 3
257
+ if texture_interpolator in ("linear", "nearest"):
258
+ texture_interpolator_margin = 1
259
+ elif texture_interpolator == "cubic":
260
+ texture_interpolator_margin = 3
258
261
  else:
259
- raise RuntimeError(f"Invalid interpolator {color_interpolator}")
262
+ raise RuntimeError(f"Invalid interpolator {texture_interpolator}")
260
263
 
261
264
  # Classification interpolator is always nearest
262
265
  classif_interpolator = "nearest"
@@ -308,100 +311,112 @@ def fill_from_one_sensor( # noqa C901
308
311
  validity_mask, not_interpolated_mask
309
312
  )
310
313
 
311
- if sensor.get("color"):
312
- with rio.open(sensor["color"]) as sensor_color_image:
313
- # Only fill color if the number of bands matches. For exemple do
314
- # not try to fill an output RGB image from a greyscale "color"
315
- # image.
316
- if sensor_color_image.count == number_of_color_bands:
314
+ if sensor.get("image"):
315
+ # Only fill color if all texture bands are present
316
+ if all(
317
+ band_name in sensor["image"]["bands"] for band_name in texture_bands
318
+ ):
319
+ with rio.open(sensor["image"]["main_file"]) as sensor_color_image:
317
320
  first_row = np.floor(
318
- max(np.min(ind_rows_sensor) - color_interpolator_margin, 0)
321
+ max(
322
+ np.min(ind_rows_sensor) - texture_interpolator_margin, 0
323
+ )
319
324
  )
320
325
  last_row = np.ceil(
321
326
  min(
322
- np.max(ind_rows_sensor) + color_interpolator_margin,
327
+ np.max(ind_rows_sensor) + texture_interpolator_margin,
323
328
  sensor_color_image.height,
324
329
  )
325
330
  )
326
331
  first_col = np.floor(
327
- max(np.min(ind_cols_sensor) - color_interpolator_margin, 0)
332
+ max(
333
+ np.min(ind_cols_sensor) - texture_interpolator_margin, 0
334
+ )
328
335
  )
329
336
  last_col = np.ceil(
330
337
  min(
331
- np.max(ind_cols_sensor) + color_interpolator_margin,
338
+ np.max(ind_cols_sensor) + texture_interpolator_margin,
332
339
  sensor_color_image.width,
333
340
  )
334
341
  )
335
342
 
336
- rio_window = rio.windows.Window.from_slices(
337
- (first_row, last_row),
338
- (first_col, last_col),
339
- )
343
+ rio_window = rio.windows.Window.from_slices(
344
+ (first_row, last_row),
345
+ (first_col, last_col),
346
+ )
340
347
 
341
- sensor_points = (
342
- np.arange(first_row, last_row),
343
- np.arange(first_col, last_col),
344
- )
348
+ sensor_points = (
349
+ np.arange(first_row, last_row),
350
+ np.arange(first_col, last_col),
351
+ )
345
352
 
346
- if validity_mask is not None:
347
- interpolated_mask = validity_mask
348
- else:
349
- interpolated_mask = np.ones(len(altitudes), dtype=bool)
353
+ if validity_mask is not None:
354
+ interpolated_mask = validity_mask
355
+ else:
356
+ interpolated_mask = np.ones(len(altitudes), dtype=bool)
350
357
 
351
- for band in range(sensor_color_image.count):
352
- # rio band convention
353
- sensor_data = sensor_color_image.read(
354
- band + 1, window=rio_window
355
- )
358
+ for output_band, band_name in enumerate(texture_bands):
359
+ # rio band convention
360
+ sensor_file = rio.open(
361
+ sensor["image"]["bands"][band_name]["path"]
362
+ )
363
+ input_band = sensor["image"]["bands"][band_name]["band"]
364
+ sensor_data = sensor_file.read(
365
+ input_band + 1, window=rio_window
366
+ )
356
367
 
357
- if validity_mask is not None:
358
- if return_all_points is True:
359
- all_values[band, :] = interpolate.interpn(
360
- sensor_points,
361
- sensor_data,
362
- (ind_rows_sensor, ind_cols_sensor),
363
- bounds_error=False,
364
- method=color_interpolator,
365
- )
366
- band_values = all_values[band, validity_mask]
367
- # No need to interpolate on every points
368
- else:
369
- band_values = interpolate.interpn(
370
- sensor_points,
371
- sensor_data,
372
- (
373
- ind_rows_sensor[validity_mask],
374
- ind_cols_sensor[validity_mask],
375
- ),
376
- bounds_error=False,
377
- method=color_interpolator,
378
- )
379
- nan_values = np.isnan(band_values)
380
- interpolated_mask[validity_mask] = np.logical_or(
381
- interpolated_mask[validity_mask], ~nan_values
368
+ if validity_mask is not None:
369
+ if return_all_points is True:
370
+ all_values[output_band, :] = interpolate.interpn(
371
+ sensor_points,
372
+ sensor_data,
373
+ (ind_rows_sensor, ind_cols_sensor),
374
+ bounds_error=False,
375
+ method=texture_interpolator,
382
376
  )
383
- filled_color[band, interpolated_mask] += band_values
384
-
377
+ band_values = all_values[output_band, validity_mask]
378
+ # No need to interpolate on every points
385
379
  else:
386
380
  band_values = interpolate.interpn(
387
381
  sensor_points,
388
382
  sensor_data,
389
- (ind_rows_sensor, ind_cols_sensor),
383
+ (
384
+ ind_rows_sensor[validity_mask],
385
+ ind_cols_sensor[validity_mask],
386
+ ),
390
387
  bounds_error=False,
391
- method=color_interpolator,
388
+ method=texture_interpolator,
392
389
  )
393
- interpolated_mask = np.logical_or(
394
- interpolated_mask, ~np.isnan(band_values)
395
- )
396
- filled_color[band, interpolated_mask] += band_values
397
- output_not_interpolated_mask = ~interpolated_mask
390
+ nan_values = np.isnan(band_values)
391
+ interpolated_mask[validity_mask] = np.logical_or(
392
+ interpolated_mask[validity_mask], ~nan_values
393
+ )
394
+ filled_color[output_band, interpolated_mask] += band_values
398
395
 
399
- weights[interpolated_mask] += 1
396
+ else:
397
+ band_values = interpolate.interpn(
398
+ sensor_points,
399
+ sensor_data,
400
+ (ind_rows_sensor, ind_cols_sensor),
401
+ bounds_error=False,
402
+ method=texture_interpolator,
403
+ )
404
+ interpolated_mask = np.logical_or(
405
+ interpolated_mask, ~np.isnan(band_values)
406
+ )
407
+ filled_color[output_band, interpolated_mask] += band_values
408
+ output_not_interpolated_mask = ~interpolated_mask
409
+
410
+ weights[interpolated_mask] += 1
400
411
 
401
412
  if filled_classif is not None and sensor.get("classification"):
402
- with rio.open(sensor["classification"]) as sensor_classif_image:
413
+ if number_of_classification_bands == len(
414
+ sensor["classification"]["bands"]
415
+ ):
416
+ with rio.open(
417
+ sensor["classification"]["main_file"]
418
+ ) as sensor_classif_image:
403
419
 
404
- if sensor_classif_image.count == number_of_classification_bands:
405
420
  first_row = np.floor(
406
421
  max(
407
422
  np.min(ind_rows_sensor) - classif_interpolator_margin, 0
@@ -425,95 +440,39 @@ def fill_from_one_sensor( # noqa C901
425
440
  )
426
441
  )
427
442
 
428
- rio_window = rio.windows.Window.from_slices(
429
- (first_row, last_row),
430
- (first_col, last_col),
431
- )
443
+ rio_window = rio.windows.Window.from_slices(
444
+ (first_row, last_row),
445
+ (first_col, last_col),
446
+ )
432
447
 
433
- sensor_points = (
434
- np.arange(first_row, last_row),
435
- np.arange(first_col, last_col),
436
- )
448
+ sensor_points = (
449
+ np.arange(first_row, last_row),
450
+ np.arange(first_col, last_col),
451
+ )
437
452
 
438
- for band in range(sensor_classif_image.count):
439
- # rio band convention
440
- sensor_data = sensor_classif_image.read(
441
- band + 1, window=rio_window, out_dtype=np.uint8
442
- )
453
+ for output_band, band_name in enumerate(
454
+ sensor["classification"]["bands"]
455
+ ):
456
+ # rio band convention
457
+ sensor_file = rio.open(
458
+ sensor["classification"]["bands"][band_name]["path"]
459
+ )
460
+ input_band = sensor["classification"]["bands"][band_name][
461
+ "band"
462
+ ]
463
+ sensor_data = sensor_file.read(
464
+ input_band + 1, window=rio_window
465
+ )
443
466
 
444
- filled_classif[band, :] = np.logical_or(
445
- filled_classif[band, :],
446
- interpolate.interpn(
447
- sensor_points,
448
- sensor_data,
449
- (ind_rows_sensor, ind_cols_sensor),
450
- bounds_error=False,
451
- method=classif_interpolator,
452
- ),
453
- )
467
+ filled_classif[output_band, :] = np.logical_or(
468
+ filled_classif[output_band, :],
469
+ interpolate.interpn(
470
+ sensor_points,
471
+ sensor_data,
472
+ (ind_rows_sensor, ind_cols_sensor),
473
+ bounds_error=False,
474
+ method=classif_interpolator,
475
+ ),
476
+ )
454
477
 
455
478
  return output_not_interpolated_mask, all_values
456
-
457
-
458
- def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
459
- """
460
- Compute bounds of each input sensor that have an associated color or
461
- classification image
462
-
463
- :param sensor_inputs: dictionary containing paths to input images and models
464
- :type sensor_inputs: dict
465
- :param geom_plugin: geometry plugin used for inverse locations
466
- :type geom_plugin: AbstractGeometry
467
- :param geom_plugin: geometry plugin used for inverse locations
468
- :type geom_plugin: AbstractGeometry
469
- :param output_epsg: epsg of the output polygons
470
- :type output_epsg: int
471
-
472
- :return: a dictionary containing a Polygon in output geometry for each
473
- valid input sensor
474
- """
475
-
476
- sensor_bounds = {}
477
-
478
- for sensor_name, sensor in sensor_inputs.items():
479
- reference_sensor_image = sensor.get(
480
- "color", sensor.get("classification", None)
481
- )
482
- # no data for this sensor, no need to compute its bounds
483
- if reference_sensor_image is None:
484
- continue
485
-
486
- u_l, u_r, l_r, l_l = geom_plugin.image_envelope(
487
- reference_sensor_image, sensor["geomodel"]
488
- )
489
-
490
- poly_geo = Polygon([u_l, u_r, l_r, l_l, u_l])
491
-
492
- sensor_bounds[sensor_name] = polygon_projection(
493
- poly_geo, 4326, output_epsg
494
- )
495
-
496
- return sensor_bounds
497
-
498
-
499
- def filter_sensor_inputs(sensor_inputs, sensor_bounds, ground_polygon):
500
- """
501
- Filter input sensors by comparing their bounds to a reference Polygon
502
-
503
- :param sensor_inputs: dictionary containing paths to input images and models
504
- :type sensor_inputs: dict
505
- :param sensor_bounds: dictionary containing bounds of input sensors
506
- :type sensor_bounds: dict
507
- :param ground_polygon: reference polygon, in ground geometry
508
- :type ground_polygon: Polygon
509
-
510
- :return: a fitlered version of sensor_inputs
511
- """
512
-
513
- filtered_sensor_inputs = sensor_inputs.copy()
514
-
515
- for sensor_name, bound in sensor_bounds.items():
516
- if not bound.intersects(ground_polygon):
517
- del filtered_sensor_inputs[sensor_name]
518
-
519
- return filtered_sensor_inputs
@@ -33,10 +33,13 @@ from json_checker import Checker
33
33
  from shapely.geometry import Polygon
34
34
 
35
35
  import cars.orchestrator.orchestrator as ocht
36
- from cars.applications.auxiliary_filling import auxiliary_filling_tools
36
+ from cars.applications.auxiliary_filling import (
37
+ auxiliary_filling_algo,
38
+ auxiliary_filling_wrappers,
39
+ )
37
40
 
38
41
  # CARS imports
39
- from cars.applications.auxiliary_filling.auxiliary_filling import (
42
+ from cars.applications.auxiliary_filling.abstract_auxiliary_filling_app import (
40
43
  AuxiliaryFilling,
41
44
  )
42
45
  from cars.core import constants as cst
@@ -96,8 +99,8 @@ class AuxiliaryFillingFromSensors(
96
99
  "and full"
97
100
  )
98
101
 
99
- overloaded_conf["color_interpolator"] = conf.get(
100
- "color_interpolator", "linear"
102
+ overloaded_conf["texture_interpolator"] = conf.get(
103
+ "texture_interpolator", "linear"
101
104
  )
102
105
  overloaded_conf["activated"] = conf.get("activated", False)
103
106
  overloaded_conf["use_mask"] = conf.get("use_mask", True)
@@ -112,7 +115,7 @@ class AuxiliaryFillingFromSensors(
112
115
  "activated": bool,
113
116
  "mode": str,
114
117
  "use_mask": bool,
115
- "color_interpolator": str,
118
+ "texture_interpolator": str,
116
119
  "save_intermediate_data": bool,
117
120
  }
118
121
 
@@ -131,6 +134,7 @@ class AuxiliaryFillingFromSensors(
131
134
  sensor_inputs,
132
135
  pairing,
133
136
  geom_plugin,
137
+ texture_bands,
134
138
  orchestrator=None,
135
139
  ):
136
140
  """
@@ -151,6 +155,8 @@ class AuxiliaryFillingFromSensors(
151
155
  :type pairing: list
152
156
  :param geom_plugin: geometry plugin used for inverse locations
153
157
  :type geom_plugin: AbstractGeometry
158
+ :param texture_bands: list of band names used for output texture
159
+ :type texture_bands: list
154
160
  :param orchestrator: orchestrator used
155
161
  :type orchestrator: Orchestrator
156
162
  """
@@ -180,7 +186,7 @@ class AuxiliaryFillingFromSensors(
180
186
  if not os.path.exists(dump_dir):
181
187
  os.makedirs(dump_dir)
182
188
 
183
- color_not_filled_file = os.path.join(dump_dir, "color_not_filled.tif")
189
+ color_not_filled_file = os.path.join(dump_dir, "texture_not_filled.tif")
184
190
  if os.path.exists(color_file):
185
191
  shutil.move(color_file, color_not_filled_file)
186
192
 
@@ -219,22 +225,22 @@ class AuxiliaryFillingFromSensors(
219
225
 
220
226
  # Initialize no data value
221
227
  classification_no_data_value = 0
222
- color_no_data_value = 0
228
+ texture_no_data_value = 0
223
229
  color_dtype = np.float32
224
230
  classif_dtype = np.uint8
225
231
 
226
232
  if os.path.exists(color_not_filled_file):
227
233
  with rio.open(color_not_filled_file, "r") as descriptor:
228
- color_no_data_value = descriptor.nodata
234
+ texture_no_data_value = descriptor.nodata
229
235
  color_dtype = descriptor.profile.get("dtype", np.float32)
230
236
 
231
237
  self.orchestrator.add_to_save_lists(
232
238
  os.path.join(dump_dir, color_file),
233
239
  cst.RASTER_COLOR_IMG,
234
240
  aux_filled_image,
235
- nodata=color_no_data_value,
241
+ nodata=texture_no_data_value,
236
242
  dtype=color_dtype,
237
- cars_ds_name="filled_color",
243
+ cars_ds_name="filled_texture",
238
244
  )
239
245
 
240
246
  if classif_file is not None:
@@ -262,7 +268,7 @@ class AuxiliaryFillingFromSensors(
262
268
 
263
269
  # Pre-compute sensor bounds of all sensors to filter sensors that do
264
270
  # not intersect with tile in tasks
265
- sensor_bounds = auxiliary_filling_tools.compute_sensor_bounds(
271
+ sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
266
272
  sensor_inputs, geom_plugin, reference_epsg
267
273
  )
268
274
 
@@ -293,8 +299,11 @@ class AuxiliaryFillingFromSensors(
293
299
  reference_epsg,
294
300
  full_saving_info,
295
301
  geom_plugin,
302
+ texture_bands,
296
303
  mode=self.used_config["mode"],
297
- color_interpolator=self.used_config["color_interpolator"],
304
+ texture_interpolator=self.used_config[
305
+ "texture_interpolator"
306
+ ],
298
307
  use_mask=self.used_config["use_mask"],
299
308
  )
300
309
 
@@ -318,12 +327,13 @@ def filling_from_sensor_wrapper(
318
327
  epsg,
319
328
  saving_info,
320
329
  geom_plugin,
330
+ texture_bands,
321
331
  mode,
322
- color_interpolator,
332
+ texture_interpolator,
323
333
  use_mask,
324
334
  ):
325
335
  """
326
- fill color and classifcation from sensor information for a terrain tile
336
+ Fill color and classification from sensor information for a terrain tile
327
337
 
328
338
  :param dsm_file: path to the filled dsm file
329
339
  :type dsm_file: str
@@ -347,11 +357,13 @@ def filling_from_sensor_wrapper(
347
357
  :type saving_info: dict
348
358
  :param geom_plugin: geometry plugin used for inverse locations
349
359
  :type geom_plugin: AbstractGeometry
360
+ :param texture_bands: list of band names used for output texture
361
+ :type texture_bands: list
350
362
  :param mode: geometry plugin used for inverse locations
351
363
  :type mode: str
352
- :param color_interpolator: scipy interpolator use to interpolate color
364
+ :param texture_interpolator: scipy interpolator use to interpolate color
353
365
  values
354
- :type color_interpolator: str
366
+ :type texture_interpolator: str
355
367
  :param use_mask: use mask information from sensors in color computation
356
368
  :type use_mask: bool
357
369
 
@@ -432,13 +444,13 @@ def filling_from_sensor_wrapper(
432
444
  else:
433
445
  profile = dsm_profile
434
446
  number_of_color_bands = inputs.rasterio_get_nb_bands(
435
- sensor_inputs[list(sensor_inputs.keys())[0]].get("color", None)
447
+ sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
436
448
  )
437
449
  color_values = np.full(
438
450
  (number_of_color_bands, *target_mask.shape), np.nan
439
451
  )
440
452
  color_band_names = inputs.get_descriptions_bands(
441
- sensor_inputs[list(sensor_inputs.keys())[0]].get("color", None)
453
+ sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
442
454
  )
443
455
  # update profile
444
456
  profile.update(count=number_of_color_bands)
@@ -481,14 +493,14 @@ def filling_from_sensor_wrapper(
481
493
  index_1d = target_mask.flatten().nonzero()[0]
482
494
 
483
495
  # Remove sensor that don't intesects with current tile
484
- filtered_sensor_inputs = auxiliary_filling_tools.filter_sensor_inputs(
496
+ filtered_sensor_inputs = auxiliary_filling_wrappers.filter_sensor_inputs(
485
497
  sensor_inputs, sensor_bounds, ground_polygon
486
498
  )
487
499
 
488
500
  if len(index_1d) > 0:
489
501
  # Fill required pixels
490
502
  color_values_filled, classification_values_filled = (
491
- auxiliary_filling_tools.fill_auxiliary(
503
+ auxiliary_filling_algo.fill_auxiliary(
492
504
  filtered_sensor_inputs,
493
505
  pairing,
494
506
  lon_lat[index_1d, 0],
@@ -497,7 +509,8 @@ def filling_from_sensor_wrapper(
497
509
  geom_plugin,
498
510
  number_of_color_bands,
499
511
  number_of_classification_bands,
500
- color_interpolator=color_interpolator,
512
+ texture_bands,
513
+ texture_interpolator=texture_interpolator,
501
514
  use_mask=use_mask,
502
515
  )
503
516
  )