cars 1.0.0a3__cp39-cp39-win_amd64.whl → 1.0.0a4__cp39-cp39-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 +5 -5
- cars/applications/__init__.py +0 -3
- cars/applications/application_template.py +20 -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 +80 -36
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +23 -57
- cars/applications/dem_generation/dichotomic_generation_app.py +3 -3
- cars/applications/dem_generation/rasterization_app.py +100 -41
- 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 +38 -39
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-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 +84 -62
- cars/applications/dense_matching/loaders/pandora_loader.py +91 -33
- cars/applications/dsm_filling/border_interpolation_app.py +1 -7
- cars/applications/dsm_filling/bulldozer_filling_app.py +2 -8
- cars/applications/dsm_filling/exogenous_filling_app.py +4 -9
- 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 +2 -1
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +96 -267
- cars/applications/point_cloud_outlier_removal/statistical_app.py +116 -275
- cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +60 -113
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +16 -4
- 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 +3 -3
- 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 +256 -25
- cars/core/geometry/shareloc_geometry.py +110 -82
- cars/core/inputs.py +57 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +9 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +5 -5
- 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 +148 -21
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +11 -3
- 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 +14 -3
- 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 +462 -1073
- cars/pipelines/parameters/advanced_parameters.py +74 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +2 -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 +2 -2
- cars/pipelines/parameters/sensor_inputs.py +30 -75
- 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 +527 -1016
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/RECORD +116 -132
- cars.libs/.load-order-cars-1.0.0a4 +3 -0
- 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.cp39-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp39-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.0a3.dist-info/DELVEWHEEL +0 -2
- cars.libs/.load-order-cars-1.0.0a3 +0 -3
- cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
- cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
- cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -144,7 +144,7 @@ def compute_disparity_grid(
|
|
|
144
144
|
return disp_min_grid, disp_max_grid
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
def compute_disparity(
|
|
147
|
+
def compute_disparity( # pylint: disable=too-many-positional-arguments
|
|
148
148
|
left_dataset,
|
|
149
149
|
right_dataset,
|
|
150
150
|
corr_cfg,
|
|
@@ -257,19 +257,53 @@ def compute_disparity(
|
|
|
257
257
|
right_dataset = right_dataset.drop_vars([cst.EPI_MSK])
|
|
258
258
|
right_dataset[cst.EPI_MSK] = right_msk
|
|
259
259
|
|
|
260
|
-
#
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
260
|
+
# Check that the datasets are not full of nan (would crash later)
|
|
261
|
+
if left_dataset["msk"].all() or right_dataset["msk"].all():
|
|
262
|
+
height = left_dataset.sizes["row"]
|
|
263
|
+
width = left_dataset.sizes["col"]
|
|
264
|
+
ref = xr.Dataset(
|
|
265
|
+
coords={
|
|
266
|
+
"row": left_dataset.coords["row"],
|
|
267
|
+
"col": left_dataset.coords["col"],
|
|
268
|
+
"indicator": [
|
|
269
|
+
"confidence_from_ambiguity.cars_1",
|
|
270
|
+
"confidence_from_risk_max.cars_2",
|
|
271
|
+
"confidence_from_risk_min.cars_2",
|
|
272
|
+
"confidence_from_disp_sup_from_risk.cars_2",
|
|
273
|
+
"confidence_from_disp_inf_from_risk.cars_2",
|
|
274
|
+
"confidence_from_interval_bounds_inf.cars_3",
|
|
275
|
+
"confidence_from_interval_bounds_sup.cars_3",
|
|
276
|
+
"confidence_from_left_right_consistency",
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
data_vars={
|
|
280
|
+
"disparity_map": (
|
|
281
|
+
("row", "col"),
|
|
282
|
+
np.full((height, width), np.nan, dtype=np.float32),
|
|
283
|
+
),
|
|
284
|
+
"validity_mask": (
|
|
285
|
+
("row", "col"),
|
|
286
|
+
np.ones((height, width), dtype=np.int64),
|
|
287
|
+
),
|
|
288
|
+
"confidence_measure": (
|
|
289
|
+
("row", "col", "indicator"),
|
|
290
|
+
np.full((height, width, 8), np.nan, dtype=np.float32),
|
|
291
|
+
),
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
else:
|
|
295
|
+
# Instantiate pandora state machine
|
|
296
|
+
pandora_machine = PandoraMachine()
|
|
297
|
+
# check datasets
|
|
298
|
+
check_datasets(left_dataset, right_dataset)
|
|
299
|
+
|
|
300
|
+
# Run the Pandora pipeline
|
|
301
|
+
ref, _ = pandora.run(
|
|
302
|
+
pandora_machine,
|
|
303
|
+
left_dataset,
|
|
304
|
+
right_dataset,
|
|
305
|
+
corr_cfg,
|
|
306
|
+
)
|
|
273
307
|
|
|
274
308
|
disp_dataset = dm_wrap.create_disp_dataset(
|
|
275
309
|
ref,
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
This module is responsible for the dense matching algorithms:
|
|
22
22
|
- thus it creates a disparity map from a pair of images
|
|
23
23
|
"""
|
|
24
|
-
# pylint: disable=
|
|
24
|
+
# pylint: disable=C0302
|
|
25
25
|
|
|
26
26
|
# Standard imports
|
|
27
27
|
import logging
|
|
28
|
+
import math
|
|
28
29
|
import warnings
|
|
29
30
|
from typing import Dict
|
|
30
31
|
|
|
@@ -281,6 +282,7 @@ def compute_cropped_roi(
|
|
|
281
282
|
)
|
|
282
283
|
|
|
283
284
|
|
|
285
|
+
# pylint: disable=too-many-positional-arguments
|
|
284
286
|
def create_disp_dataset( # noqa: C901
|
|
285
287
|
disp: xr.Dataset,
|
|
286
288
|
ref_dataset: xr.Dataset,
|
|
@@ -513,6 +515,7 @@ def add_crop_info(disp_ds, cropped_range):
|
|
|
513
515
|
return disp_ds
|
|
514
516
|
|
|
515
517
|
|
|
518
|
+
# pylint: disable=too-many-positional-arguments
|
|
516
519
|
def estimate_right_classif_on_left(
|
|
517
520
|
right_classif,
|
|
518
521
|
disp_map,
|
|
@@ -752,6 +755,7 @@ def estimate_right_grid_disp(disp_min_grid, disp_max_grid):
|
|
|
752
755
|
)
|
|
753
756
|
|
|
754
757
|
|
|
758
|
+
# pylint: disable=too-many-positional-arguments
|
|
755
759
|
def optimal_tile_size_pandora_plugin_libsgm(
|
|
756
760
|
disp_min: int,
|
|
757
761
|
disp_max: int,
|
|
@@ -779,7 +783,7 @@ def optimal_tile_size_pandora_plugin_libsgm(
|
|
|
779
783
|
"""
|
|
780
784
|
|
|
781
785
|
memory = max_ram_per_worker
|
|
782
|
-
disp = disp_max - disp_min
|
|
786
|
+
disp = max(3, abs(disp_max - disp_min))
|
|
783
787
|
|
|
784
788
|
image = 32 * 2
|
|
785
789
|
disp_ref = 32
|
|
@@ -809,13 +813,17 @@ def optimal_tile_size_pandora_plugin_libsgm(
|
|
|
809
813
|
# but sqrt(nb_pixels + (disp/2)**2) - disp/2
|
|
810
814
|
tile_size = np.sqrt(row_or_col + (disp / 2) ** 2) - disp / 2
|
|
811
815
|
tile_size = (1.0 - margin / 100.0) * tile_size
|
|
812
|
-
|
|
816
|
+
|
|
817
|
+
if math.isinf(tile_size):
|
|
818
|
+
logging.warning("Tile size infinite")
|
|
813
819
|
|
|
814
820
|
if tile_size > max_tile_size:
|
|
815
821
|
tile_size = max_tile_size
|
|
816
822
|
elif tile_size < min_tile_size:
|
|
817
823
|
tile_size = min_tile_size
|
|
818
824
|
|
|
825
|
+
tile_size = tile_size_rounding * int(tile_size / tile_size_rounding)
|
|
826
|
+
|
|
819
827
|
return tile_size
|
|
820
828
|
|
|
821
829
|
|
|
@@ -27,7 +27,6 @@ import itertools
|
|
|
27
27
|
import logging
|
|
28
28
|
|
|
29
29
|
# Third party imports
|
|
30
|
-
import affine
|
|
31
30
|
import numpy as np
|
|
32
31
|
import rasterio
|
|
33
32
|
import xarray as xr
|
|
@@ -45,6 +44,7 @@ from cars.core.projection import point_cloud_conversion
|
|
|
45
44
|
from cars.data_structures import cars_dataset, cars_dict
|
|
46
45
|
|
|
47
46
|
|
|
47
|
+
# pylint: disable=too-many-positional-arguments
|
|
48
48
|
def generate_disp_grids_dataset(
|
|
49
49
|
grid_min,
|
|
50
50
|
grid_max,
|
|
@@ -103,6 +103,7 @@ def generate_disp_grids_dataset(
|
|
|
103
103
|
return disp_range_tile
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
# pylint: disable=too-many-positional-arguments
|
|
106
107
|
def generate_disp_range_const_tile_wrapper(
|
|
107
108
|
row_range,
|
|
108
109
|
col_range,
|
|
@@ -152,6 +153,7 @@ def generate_disp_range_const_tile_wrapper(
|
|
|
152
153
|
return disp_range, global_infos
|
|
153
154
|
|
|
154
155
|
|
|
156
|
+
# pylint: disable=too-many-positional-arguments
|
|
155
157
|
def generate_disp_range_from_dem_wrapper(
|
|
156
158
|
epipolar_grid_array_window,
|
|
157
159
|
full_epi_row_range,
|
|
@@ -162,8 +164,6 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
162
164
|
dem_median,
|
|
163
165
|
dem_min,
|
|
164
166
|
dem_max,
|
|
165
|
-
altitude_delta_min,
|
|
166
|
-
altitude_delta_max,
|
|
167
167
|
raster_profile,
|
|
168
168
|
saving_info,
|
|
169
169
|
saving_info_global_infos,
|
|
@@ -193,10 +193,6 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
193
193
|
:type dem_min: str
|
|
194
194
|
:param dem_max: Path of dem max.
|
|
195
195
|
:type dem_max: srt
|
|
196
|
-
:param altitude_delta_min: The minimum altitude delta.
|
|
197
|
-
:type altitude_delta_min: float
|
|
198
|
-
:param altitude_delta_max: The maximum altitude delta.
|
|
199
|
-
:type altitude_delta_max: float
|
|
200
196
|
:param raster_profile: The raster profile.
|
|
201
197
|
:type raster_profile: dict
|
|
202
198
|
:param saving_info: The disp range grid saving information.
|
|
@@ -217,23 +213,11 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
217
213
|
"""
|
|
218
214
|
|
|
219
215
|
# compute reverse matrix
|
|
220
|
-
transform_sensor =
|
|
221
|
-
|
|
222
|
-
inputs.rasterio_get_transform(
|
|
223
|
-
sensor_image_right["image"]["main_file"]
|
|
224
|
-
)
|
|
225
|
-
)
|
|
216
|
+
transform_sensor = inputs.rasterio_get_transform(
|
|
217
|
+
sensor_image_right["image"]["main_file"], convention="north"
|
|
226
218
|
)
|
|
227
219
|
|
|
228
220
|
trans_inv_sensor = ~transform_sensor
|
|
229
|
-
# Transform to positive values
|
|
230
|
-
trans_inv_sensor = np.array(trans_inv_sensor)
|
|
231
|
-
trans_inv_sensor = np.reshape(trans_inv_sensor, (3, 3))
|
|
232
|
-
if trans_inv_sensor[0, 0] < 0:
|
|
233
|
-
trans_inv_sensor[0, :] *= -1
|
|
234
|
-
if trans_inv_sensor[1, 1] < 0:
|
|
235
|
-
trans_inv_sensor[1, :] *= -1
|
|
236
|
-
trans_inv_sensor = affine.Affine(*list(trans_inv_sensor.flatten()))
|
|
237
221
|
|
|
238
222
|
# Geometry plugin
|
|
239
223
|
geo_plugin = geom_plugin_with_dem_and_geoid
|
|
@@ -294,7 +278,9 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
294
278
|
(np.max(col_range_with_margin), np.min(row_range_with_margin)),
|
|
295
279
|
(np.max(col_range_with_margin), np.max(row_range_with_margin)),
|
|
296
280
|
]
|
|
297
|
-
sensor_bbox = geo_plugin.sensor_position_from_grid(
|
|
281
|
+
sensor_bbox = geo_plugin.sensor_position_from_grid(
|
|
282
|
+
grid_right, epi_bbox, interpolation_method="linear"
|
|
283
|
+
)
|
|
298
284
|
row_sensor_bbox, col_sensor_bbox = transform_physical_point_to_index(
|
|
299
285
|
trans_inv_sensor, sensor_bbox[:, 1], sensor_bbox[:, 0]
|
|
300
286
|
)
|
|
@@ -356,18 +342,26 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
356
342
|
lon_mean = terrain_position_lon_lat[:, 0]
|
|
357
343
|
lat_mean = terrain_position_lon_lat[:, 1]
|
|
358
344
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
345
|
+
# dem min and max are in 4326
|
|
346
|
+
dem_min_list = inputs.rasterio_get_values(
|
|
347
|
+
dem_min, lon_mean, lat_mean, point_cloud_conversion
|
|
348
|
+
)
|
|
349
|
+
dem_max_list = inputs.rasterio_get_values(
|
|
350
|
+
dem_max, lon_mean, lat_mean, point_cloud_conversion
|
|
351
|
+
)
|
|
352
|
+
if dem_min_list is None or dem_max_list is None:
|
|
353
|
+
logging.warning("DEM min and DEM max does not cover this tile")
|
|
354
|
+
disp_range, global_infos = empty_disparity_grids(
|
|
355
|
+
row_range_no_margin,
|
|
356
|
+
col_range_no_margin,
|
|
357
|
+
epipolar_grid_array_window,
|
|
358
|
+
raster_profile,
|
|
359
|
+
saving_info,
|
|
360
|
+
saving_info_global_infos,
|
|
366
361
|
)
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
dem_max_list = dem_median_list + altitude_delta_max
|
|
362
|
+
return disp_range, global_infos
|
|
363
|
+
|
|
364
|
+
nan_mask = nan_mask & ~np.isnan(dem_min_list) & ~np.isnan(dem_max_list)
|
|
371
365
|
|
|
372
366
|
# filter nan value from input points
|
|
373
367
|
lon_mean = lon_mean[nan_mask]
|
|
@@ -410,6 +404,7 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
410
404
|
2,
|
|
411
405
|
),
|
|
412
406
|
),
|
|
407
|
+
interpolation_method="linear",
|
|
413
408
|
)
|
|
414
409
|
)
|
|
415
410
|
|
|
@@ -422,37 +417,14 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
422
417
|
|
|
423
418
|
if len(ind_rows_sensor) < 5:
|
|
424
419
|
# QH6214 needs at least 4 points for interpolation
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
grid_max = np.empty(
|
|
430
|
-
(len(row_range_no_margin), len(col_range_no_margin))
|
|
431
|
-
)
|
|
432
|
-
grid_min[:, :] = 0
|
|
433
|
-
grid_max[:, :] = 0
|
|
434
|
-
|
|
435
|
-
disp_range = generate_disp_grids_dataset(
|
|
436
|
-
grid_min,
|
|
437
|
-
grid_max,
|
|
438
|
-
saving_info,
|
|
420
|
+
disp_range, global_infos = empty_disparity_grids(
|
|
421
|
+
row_range_no_margin,
|
|
422
|
+
col_range_no_margin,
|
|
423
|
+
epipolar_grid_array_window,
|
|
439
424
|
raster_profile,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
col_coords=col_range_no_margin,
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
# Generate infos on global min and max
|
|
446
|
-
global_infos = cars_dict.CarsDict(
|
|
447
|
-
{
|
|
448
|
-
"global_min": 0,
|
|
449
|
-
"global_max": 0,
|
|
450
|
-
}
|
|
451
|
-
)
|
|
452
|
-
cars_dataset.fill_dict(
|
|
453
|
-
global_infos, saving_info=saving_info_global_infos
|
|
425
|
+
saving_info,
|
|
426
|
+
saving_info_global_infos,
|
|
454
427
|
)
|
|
455
|
-
|
|
456
428
|
return disp_range, global_infos
|
|
457
429
|
|
|
458
430
|
# Interpolate disparity
|
|
@@ -542,6 +514,56 @@ def generate_disp_range_from_dem_wrapper(
|
|
|
542
514
|
return disp_range, global_infos
|
|
543
515
|
|
|
544
516
|
|
|
517
|
+
def empty_disparity_grids( # pylint: disable=too-many-positional-arguments
|
|
518
|
+
row_range_no_margin,
|
|
519
|
+
col_range_no_margin,
|
|
520
|
+
epipolar_grid_array_window,
|
|
521
|
+
raster_profile,
|
|
522
|
+
saving_info,
|
|
523
|
+
saving_info_global_infos,
|
|
524
|
+
):
|
|
525
|
+
"""
|
|
526
|
+
Return empty disparity grids
|
|
527
|
+
:param row_range_no_margin: Rows id in grid
|
|
528
|
+
:type row_range_no_margin: int
|
|
529
|
+
:param col_range_no_margin: Cols id in grid
|
|
530
|
+
:type col_range_no_margin: int
|
|
531
|
+
:param epipolar_grid_array_window: ROI of grid
|
|
532
|
+
:type epipolar_grid_array_window: dict
|
|
533
|
+
:param raster_profile: The raster profile.
|
|
534
|
+
:type raster_profile: dict
|
|
535
|
+
:param saving_info: The disp range grid saving information.
|
|
536
|
+
:type saving_info: dict
|
|
537
|
+
:param saving_info_global_infos: Global info saving infos.
|
|
538
|
+
:type saving_info_global_infos: dict
|
|
539
|
+
"""
|
|
540
|
+
grid_min = np.empty((len(row_range_no_margin), len(col_range_no_margin)))
|
|
541
|
+
grid_max = np.empty((len(row_range_no_margin), len(col_range_no_margin)))
|
|
542
|
+
grid_min[:, :] = 0
|
|
543
|
+
grid_max[:, :] = 0
|
|
544
|
+
|
|
545
|
+
disp_range = generate_disp_grids_dataset(
|
|
546
|
+
grid_min,
|
|
547
|
+
grid_max,
|
|
548
|
+
saving_info,
|
|
549
|
+
raster_profile,
|
|
550
|
+
window=epipolar_grid_array_window,
|
|
551
|
+
row_coords=row_range_no_margin,
|
|
552
|
+
col_coords=col_range_no_margin,
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# Generate infos on global min and max
|
|
556
|
+
global_infos = cars_dict.CarsDict(
|
|
557
|
+
{
|
|
558
|
+
"global_min": 0,
|
|
559
|
+
"global_max": 0,
|
|
560
|
+
}
|
|
561
|
+
)
|
|
562
|
+
cars_dataset.fill_dict(global_infos, saving_info=saving_info_global_infos)
|
|
563
|
+
|
|
564
|
+
return disp_range, global_infos
|
|
565
|
+
|
|
566
|
+
|
|
545
567
|
def create_circular_mask(height, width):
|
|
546
568
|
"""
|
|
547
569
|
Create a circular mask for footprint around pixel
|
|
@@ -32,6 +32,7 @@ from typing import Dict
|
|
|
32
32
|
import numpy as np
|
|
33
33
|
import pandora
|
|
34
34
|
import rasterio
|
|
35
|
+
import xarray as xr
|
|
35
36
|
from json_checker import Checker, Or
|
|
36
37
|
from pandora.check_configuration import (
|
|
37
38
|
check_pipeline_section,
|
|
@@ -39,12 +40,12 @@ from pandora.check_configuration import (
|
|
|
39
40
|
get_config_pipeline,
|
|
40
41
|
update_conf,
|
|
41
42
|
)
|
|
42
|
-
from pandora.img_tools import get_metadata
|
|
43
43
|
from pandora.state_machine import PandoraMachine
|
|
44
44
|
from rasterio.mask import mask
|
|
45
45
|
from shapely.geometry import mapping
|
|
46
46
|
|
|
47
47
|
from cars.core.projection import polygon_projection
|
|
48
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
48
49
|
|
|
49
50
|
|
|
50
51
|
class PandoraLoader:
|
|
@@ -53,7 +54,7 @@ class PandoraLoader:
|
|
|
53
54
|
|
|
54
55
|
"""
|
|
55
56
|
|
|
56
|
-
def __init__( # noqa: C901
|
|
57
|
+
def __init__( # pylint: disable=too-many-positional-arguments # noqa: C901
|
|
57
58
|
self,
|
|
58
59
|
conf=None,
|
|
59
60
|
method_name=None,
|
|
@@ -271,26 +272,6 @@ class PandoraLoader:
|
|
|
271
272
|
if "band" not in filter_conf:
|
|
272
273
|
conf["pipeline"]["filter"]["band"] = used_band
|
|
273
274
|
|
|
274
|
-
for key in list(conf.get("pipeline")):
|
|
275
|
-
if key.startswith("filter"):
|
|
276
|
-
if (
|
|
277
|
-
conf["pipeline"][key]["filter_method"]
|
|
278
|
-
== "median_for_intervals"
|
|
279
|
-
and "validation" in conf["pipeline"]
|
|
280
|
-
):
|
|
281
|
-
if (
|
|
282
|
-
conf["pipeline"]["validation"]["validation_method"]
|
|
283
|
-
== "cross_checking_fast"
|
|
284
|
-
):
|
|
285
|
-
conf["pipeline"]["validation"][
|
|
286
|
-
"validation_method"
|
|
287
|
-
] = "cross_checking_accurate"
|
|
288
|
-
logging.warning(
|
|
289
|
-
"You can not use median_for_intervals with "
|
|
290
|
-
"the fast cross checking validation for now. "
|
|
291
|
-
"It therefore has been overrided to accurate"
|
|
292
|
-
)
|
|
293
|
-
|
|
294
275
|
# Check conf
|
|
295
276
|
self.pandora_config = conf
|
|
296
277
|
|
|
@@ -305,6 +286,35 @@ class PandoraLoader:
|
|
|
305
286
|
|
|
306
287
|
return self.pandora_config
|
|
307
288
|
|
|
289
|
+
def get_classif_bands(self):
|
|
290
|
+
"""
|
|
291
|
+
Get the classification bands used in the pandora configuration
|
|
292
|
+
|
|
293
|
+
:return: list of classification bands
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
classif_bands = []
|
|
297
|
+
|
|
298
|
+
def search_classes_recursive(obj):
|
|
299
|
+
"""
|
|
300
|
+
Recursive search of keys containing 'classes' in the configuration
|
|
301
|
+
"""
|
|
302
|
+
if isinstance(obj, dict):
|
|
303
|
+
for key, value in obj.items():
|
|
304
|
+
if "classes" in key.lower():
|
|
305
|
+
if isinstance(value, list):
|
|
306
|
+
classif_bands.extend(value)
|
|
307
|
+
elif value is not None:
|
|
308
|
+
classif_bands.append(value)
|
|
309
|
+
# Continue recursive search
|
|
310
|
+
search_classes_recursive(value)
|
|
311
|
+
|
|
312
|
+
search_classes_recursive(self.pandora_config)
|
|
313
|
+
|
|
314
|
+
# Remove duplicates and return the list
|
|
315
|
+
return list(set(classif_bands))
|
|
316
|
+
|
|
317
|
+
@cars_profile(name="Find auto conf")
|
|
308
318
|
def find_auto_conf(
|
|
309
319
|
self, intersection_poly, land_cover_map, classif_to_config_mapping, epsg
|
|
310
320
|
):
|
|
@@ -377,15 +387,15 @@ class PandoraLoader:
|
|
|
377
387
|
|
|
378
388
|
return conf
|
|
379
389
|
|
|
380
|
-
def check_conf(
|
|
390
|
+
def check_conf( # pylint: disable=too-many-positional-arguments
|
|
381
391
|
self,
|
|
382
392
|
user_cfg,
|
|
383
|
-
|
|
384
|
-
|
|
393
|
+
nodata_left,
|
|
394
|
+
nodata_right,
|
|
385
395
|
bands_left,
|
|
386
396
|
bands_right,
|
|
387
|
-
|
|
388
|
-
|
|
397
|
+
bands_classif_left=None,
|
|
398
|
+
bands_classif_right=None,
|
|
389
399
|
):
|
|
390
400
|
"""
|
|
391
401
|
Check configuration
|
|
@@ -397,15 +407,18 @@ class PandoraLoader:
|
|
|
397
407
|
:rtype: dict
|
|
398
408
|
|
|
399
409
|
"""
|
|
400
|
-
|
|
401
410
|
# Import plugins before checking configuration
|
|
402
411
|
pandora.import_plugin()
|
|
403
412
|
# Check configuration and update the configuration with default values
|
|
404
413
|
# Instantiate pandora state machine
|
|
405
414
|
pandora_machine = PandoraMachine()
|
|
406
415
|
# check pipeline
|
|
407
|
-
metadata_left =
|
|
408
|
-
|
|
416
|
+
metadata_left = overide_pandora_get_metadata(
|
|
417
|
+
bands_left, classif_bands=bands_classif_left
|
|
418
|
+
)
|
|
419
|
+
metadata_right = overide_pandora_get_metadata(
|
|
420
|
+
bands_right, classif_bands=bands_classif_right
|
|
421
|
+
)
|
|
409
422
|
|
|
410
423
|
metadata_left = metadata_left.assign_coords(band_im=bands_left)
|
|
411
424
|
metadata_right = metadata_right.assign_coords(band_im=bands_right)
|
|
@@ -422,7 +435,9 @@ class PandoraLoader:
|
|
|
422
435
|
saved_schema
|
|
423
436
|
)
|
|
424
437
|
# check a part of input section
|
|
425
|
-
user_cfg_input = get_config_input_custom_cars(
|
|
438
|
+
user_cfg_input = get_config_input_custom_cars(
|
|
439
|
+
user_cfg, nodata_left, nodata_right
|
|
440
|
+
)
|
|
426
441
|
cfg_input = check_input_section_custom_cars(user_cfg_input)
|
|
427
442
|
# concatenate updated config
|
|
428
443
|
cfg = concat_conf([cfg_input, cfg_pipeline])
|
|
@@ -447,7 +462,46 @@ default_short_configuration_input_custom_cars = {
|
|
|
447
462
|
}
|
|
448
463
|
|
|
449
464
|
|
|
450
|
-
def
|
|
465
|
+
def overide_pandora_get_metadata(
|
|
466
|
+
im_bands: list, classif_bands: list = None
|
|
467
|
+
) -> xr.Dataset:
|
|
468
|
+
"""
|
|
469
|
+
Read metadata from image, and return the corresponding xarray.DataSet
|
|
470
|
+
|
|
471
|
+
:param im_bands: list of band names
|
|
472
|
+
:param classif_bands: list of classification band names
|
|
473
|
+
:return: partial xarray.DataSet (attributes and coordinates)
|
|
474
|
+
:rtype: xarray.DataSet
|
|
475
|
+
"""
|
|
476
|
+
|
|
477
|
+
coords = {
|
|
478
|
+
"band_im": list(im_bands),
|
|
479
|
+
"row": np.arange(10),
|
|
480
|
+
"col": np.arange(10),
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
data_vars = {
|
|
484
|
+
"image": (["row", "col"], np.zeros((10, 10))),
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if classif_bands is not None:
|
|
488
|
+
coords["band_classif"] = list(classif_bands)
|
|
489
|
+
data_vars["classif"] = (
|
|
490
|
+
["row", "col", "band_classif"],
|
|
491
|
+
np.zeros((10, 10, len(classif_bands)), dtype=np.int32),
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
# create the dataset
|
|
495
|
+
dataset = xr.Dataset(data_vars=data_vars, coords=coords)
|
|
496
|
+
|
|
497
|
+
dataset.attrs["disparity_source"] = None
|
|
498
|
+
|
|
499
|
+
return dataset
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def get_config_input_custom_cars(
|
|
503
|
+
user_cfg: Dict[str, dict], nodata_left, nodata_right
|
|
504
|
+
) -> Dict[str, dict]:
|
|
451
505
|
"""
|
|
452
506
|
Get the input configuration
|
|
453
507
|
|
|
@@ -464,9 +518,13 @@ def get_config_input_custom_cars(user_cfg: Dict[str, dict]) -> Dict[str, dict]:
|
|
|
464
518
|
|
|
465
519
|
if "nodata_left" in user_cfg["input"]:
|
|
466
520
|
cfg["input"]["nodata_left"] = user_cfg["input"]["nodata_left"]
|
|
521
|
+
else:
|
|
522
|
+
cfg["input"]["nodata_left"] = nodata_left
|
|
467
523
|
|
|
468
524
|
if "nodata_right" in user_cfg["input"]:
|
|
469
525
|
cfg["input"]["nodata_right"] = user_cfg["input"]["nodata_right"]
|
|
526
|
+
else:
|
|
527
|
+
cfg["input"]["nodata_right"] = nodata_right
|
|
470
528
|
|
|
471
529
|
return cfg
|
|
472
530
|
|
|
@@ -516,7 +574,7 @@ def overload_pandora_conf_with_confidence(conf, confidence_conf):
|
|
|
516
574
|
|
|
517
575
|
for key in confidence_conf_keys:
|
|
518
576
|
if key in conf_keys:
|
|
519
|
-
logging.
|
|
577
|
+
logging.info("{} pandora key already in configuration".format(key))
|
|
520
578
|
|
|
521
579
|
# update confidence
|
|
522
580
|
out_dict.update(confidence_conf)
|
|
@@ -56,7 +56,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
56
56
|
|
|
57
57
|
# check conf
|
|
58
58
|
self.used_method = self.used_config["method"]
|
|
59
|
-
self.activated = self.used_config["activated"]
|
|
60
59
|
self.classification = self.used_config["classification"]
|
|
61
60
|
self.component_min_size = self.used_config["component_min_size"]
|
|
62
61
|
self.border_size = self.used_config["border_size"]
|
|
@@ -74,7 +73,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
74
73
|
|
|
75
74
|
# Overload conf
|
|
76
75
|
overloaded_conf["method"] = conf.get("method", "bulldozer")
|
|
77
|
-
overloaded_conf["activated"] = conf.get("activated", False)
|
|
78
76
|
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
79
77
|
if isinstance(overloaded_conf["classification"], str):
|
|
80
78
|
overloaded_conf["classification"] = [
|
|
@@ -91,7 +89,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
91
89
|
|
|
92
90
|
rectification_schema = {
|
|
93
91
|
"method": str,
|
|
94
|
-
"activated": bool,
|
|
95
92
|
"classification": Or(None, [str]),
|
|
96
93
|
"component_min_size": int,
|
|
97
94
|
"border_size": int,
|
|
@@ -106,7 +103,7 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
106
103
|
return overloaded_conf
|
|
107
104
|
|
|
108
105
|
@cars_profile(name="Border interpolation filling")
|
|
109
|
-
def run( # noqa C901
|
|
106
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
110
107
|
self,
|
|
111
108
|
dsm_file,
|
|
112
109
|
classif_file,
|
|
@@ -127,9 +124,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
127
124
|
- a Shapely Polygon
|
|
128
125
|
"""
|
|
129
126
|
|
|
130
|
-
if not self.activated:
|
|
131
|
-
return
|
|
132
|
-
|
|
133
127
|
if self.classification is None:
|
|
134
128
|
self.classification = ["nodata"]
|
|
135
129
|
logging.error(
|
|
@@ -57,7 +57,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
57
57
|
|
|
58
58
|
# check conf
|
|
59
59
|
self.used_method = self.used_config["method"]
|
|
60
|
-
self.activated = self.used_config["activated"]
|
|
61
60
|
self.classification = self.used_config["classification"]
|
|
62
61
|
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
63
62
|
|
|
@@ -72,7 +71,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
72
71
|
|
|
73
72
|
# Overload conf
|
|
74
73
|
overloaded_conf["method"] = conf.get("method", "bulldozer")
|
|
75
|
-
overloaded_conf["activated"] = conf.get("activated", False)
|
|
76
74
|
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
77
75
|
|
|
78
76
|
if isinstance(overloaded_conf["classification"], str):
|
|
@@ -86,7 +84,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
86
84
|
|
|
87
85
|
rectification_schema = {
|
|
88
86
|
"method": str,
|
|
89
|
-
"activated": bool,
|
|
90
87
|
"classification": Or(None, [str]),
|
|
91
88
|
"save_intermediate_data": bool,
|
|
92
89
|
}
|
|
@@ -98,7 +95,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
98
95
|
return overloaded_conf
|
|
99
96
|
|
|
100
97
|
@cars_profile(name="Bulldozer filling")
|
|
101
|
-
def run( # noqa C901
|
|
98
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
102
99
|
self,
|
|
103
100
|
dsm_file,
|
|
104
101
|
classif_file,
|
|
@@ -119,9 +116,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
119
116
|
- a Shapely Polygon
|
|
120
117
|
"""
|
|
121
118
|
|
|
122
|
-
if not self.activated:
|
|
123
|
-
return None
|
|
124
|
-
|
|
125
119
|
if self.classification is None:
|
|
126
120
|
self.classification = ["nodata"]
|
|
127
121
|
|
|
@@ -206,7 +200,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
206
200
|
):
|
|
207
201
|
dsm_to_dtm(bull_conf_path)
|
|
208
202
|
except Exception:
|
|
209
|
-
logging.
|
|
203
|
+
logging.warning(
|
|
210
204
|
"Bulldozer failed on its second execution."
|
|
211
205
|
+ " The DSM could not be filled."
|
|
212
206
|
)
|