cars 1.0.0a3__cp311-cp311-win_amd64.whl → 1.0.0a4__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.
- cars/__init__.py +3 -3
- 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.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-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 +115 -131
- 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.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-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/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
|
@@ -32,7 +32,6 @@ from __future__ import print_function
|
|
|
32
32
|
|
|
33
33
|
import copy
|
|
34
34
|
import logging
|
|
35
|
-
import math
|
|
36
35
|
import os
|
|
37
36
|
|
|
38
37
|
import numpy as np
|
|
@@ -49,10 +48,6 @@ from cars.applications.dem_generation import (
|
|
|
49
48
|
)
|
|
50
49
|
from cars.applications.grid_generation import grid_correction_app
|
|
51
50
|
from cars.applications.grid_generation.transform_grid import transform_grid_func
|
|
52
|
-
from cars.applications.point_cloud_fusion import (
|
|
53
|
-
pc_fusion_algo,
|
|
54
|
-
pc_fusion_wrappers,
|
|
55
|
-
)
|
|
56
51
|
from cars.core import preprocessing, projection, roi_tools
|
|
57
52
|
from cars.core.geometry.abstract_geometry import AbstractGeometry
|
|
58
53
|
from cars.core.inputs import (
|
|
@@ -68,13 +63,14 @@ from cars.orchestrator import orchestrator
|
|
|
68
63
|
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
69
64
|
from cars.pipelines.parameters import advanced_parameters
|
|
70
65
|
from cars.pipelines.parameters import advanced_parameters_constants as adv_cst
|
|
71
|
-
from cars.pipelines.parameters import
|
|
72
|
-
from cars.pipelines.parameters import depth_map_inputs_constants as depth_cst
|
|
73
|
-
from cars.pipelines.parameters import dsm_inputs
|
|
66
|
+
from cars.pipelines.parameters import application_parameters, dsm_inputs
|
|
74
67
|
from cars.pipelines.parameters import dsm_inputs_constants as dsm_cst
|
|
75
68
|
from cars.pipelines.parameters import output_constants as out_cst
|
|
76
69
|
from cars.pipelines.parameters import output_parameters, sensor_inputs
|
|
77
70
|
from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
|
|
71
|
+
from cars.pipelines.parameters.advanced_parameters_constants import (
|
|
72
|
+
USE_ENDOGENOUS_DEM,
|
|
73
|
+
)
|
|
78
74
|
from cars.pipelines.pipeline import Pipeline
|
|
79
75
|
from cars.pipelines.pipeline_constants import (
|
|
80
76
|
ADVANCED,
|
|
@@ -109,7 +105,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
109
105
|
save_output_point_clouds
|
|
110
106
|
geom_plugin_without_dem_and_geoid
|
|
111
107
|
geom_plugin_with_dem_and_geoid
|
|
112
|
-
dem_generation_roi
|
|
113
108
|
|
|
114
109
|
:param pipeline_name: name of the pipeline.
|
|
115
110
|
:type pipeline_name: str
|
|
@@ -121,6 +116,8 @@ class UnitPipeline(PipelineTemplate):
|
|
|
121
116
|
|
|
122
117
|
# Used conf
|
|
123
118
|
self.used_conf = {}
|
|
119
|
+
# refined conf
|
|
120
|
+
self.refined_conf = {}
|
|
124
121
|
|
|
125
122
|
# Transform relative path to absolute path
|
|
126
123
|
if config_dir is not None:
|
|
@@ -137,24 +134,35 @@ class UnitPipeline(PipelineTemplate):
|
|
|
137
134
|
# Check conf inputs
|
|
138
135
|
inputs = self.check_inputs(conf[INPUTS], config_dir=config_dir)
|
|
139
136
|
self.used_conf[INPUTS] = inputs
|
|
137
|
+
self.refined_conf[INPUTS] = copy.deepcopy(inputs)
|
|
140
138
|
|
|
141
139
|
# Check advanced parameters
|
|
142
140
|
# TODO static method in the base class
|
|
141
|
+
output_dem_dir = os.path.join(
|
|
142
|
+
conf[OUTPUT][out_cst.OUT_DIRECTORY], "dump_dir", "initial_elevation"
|
|
143
|
+
)
|
|
144
|
+
safe_makedirs(output_dem_dir)
|
|
143
145
|
(
|
|
144
146
|
inputs,
|
|
145
147
|
advanced,
|
|
146
148
|
self.geometry_plugin,
|
|
147
149
|
self.geom_plugin_without_dem_and_geoid,
|
|
148
150
|
self.geom_plugin_with_dem_and_geoid,
|
|
149
|
-
self.dem_generation_roi,
|
|
150
151
|
self.scaling_coeff,
|
|
151
152
|
self.land_cover_map,
|
|
152
153
|
self.classification_to_config_mapping,
|
|
153
154
|
) = advanced_parameters.check_advanced_parameters(
|
|
154
|
-
inputs,
|
|
155
|
+
inputs,
|
|
156
|
+
conf.get(ADVANCED, {}),
|
|
157
|
+
check_epipolar_a_priori=True,
|
|
158
|
+
output_dem_dir=output_dem_dir,
|
|
155
159
|
)
|
|
156
160
|
self.used_conf[ADVANCED] = advanced
|
|
157
161
|
|
|
162
|
+
self.refined_conf[ADVANCED] = copy.deepcopy(advanced)
|
|
163
|
+
# Refined conf: resolutions 1
|
|
164
|
+
self.refined_conf[ADVANCED][adv_cst.EPIPOLAR_RESOLUTIONS] = [1]
|
|
165
|
+
|
|
158
166
|
# Get ROI
|
|
159
167
|
(
|
|
160
168
|
self.input_roi_poly,
|
|
@@ -172,6 +180,10 @@ class UnitPipeline(PipelineTemplate):
|
|
|
172
180
|
) = self.check_output(conf[OUTPUT], self.scaling_coeff)
|
|
173
181
|
|
|
174
182
|
self.used_conf[OUTPUT] = output
|
|
183
|
+
self.out_dir = self.used_conf[OUTPUT][out_cst.OUT_DIRECTORY]
|
|
184
|
+
self.dump_dir = os.path.join(self.out_dir, "dump_dir")
|
|
185
|
+
|
|
186
|
+
self.refined_conf[OUTPUT] = copy.deepcopy(output)
|
|
175
187
|
|
|
176
188
|
prod_level = output[out_cst.PRODUCT_LEVEL]
|
|
177
189
|
|
|
@@ -186,11 +198,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
186
198
|
or self.save_output_point_cloud
|
|
187
199
|
)
|
|
188
200
|
self.sensors_in_inputs = sens_cst.SENSORS in self.used_conf[INPUTS]
|
|
189
|
-
self.depth_maps_in_inputs = (
|
|
190
|
-
depth_cst.DEPTH_MAPS in self.used_conf[INPUTS]
|
|
191
|
-
)
|
|
192
201
|
self.dsms_in_inputs = dsm_cst.DSMS in self.used_conf[INPUTS]
|
|
193
|
-
self.merging = self.used_conf[ADVANCED][adv_cst.MERGING]
|
|
194
202
|
|
|
195
203
|
self.phasing = self.used_conf[ADVANCED][adv_cst.PHASING]
|
|
196
204
|
|
|
@@ -198,7 +206,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
198
206
|
self.sensors_in_inputs
|
|
199
207
|
and (not self.output_level_none)
|
|
200
208
|
and not self.dsms_in_inputs
|
|
201
|
-
and not self.depth_maps_in_inputs
|
|
202
209
|
)
|
|
203
210
|
|
|
204
211
|
if self.output_level_none:
|
|
@@ -233,23 +240,15 @@ class UnitPipeline(PipelineTemplate):
|
|
|
233
240
|
# Check conf application
|
|
234
241
|
application_conf = self.check_applications(conf.get(APPLICATIONS, {}))
|
|
235
242
|
|
|
236
|
-
if
|
|
237
|
-
self.sensors_in_inputs
|
|
238
|
-
and not self.depth_maps_in_inputs
|
|
239
|
-
and not self.dsms_in_inputs
|
|
240
|
-
):
|
|
243
|
+
if self.sensors_in_inputs and not self.dsms_in_inputs:
|
|
241
244
|
# Check conf application vs inputs application
|
|
242
245
|
application_conf = self.check_applications_with_inputs(
|
|
243
|
-
self.used_conf[INPUTS], application_conf
|
|
246
|
+
self.used_conf[INPUTS], application_conf, self.res_resamp
|
|
244
247
|
)
|
|
245
248
|
|
|
246
249
|
self.used_conf[APPLICATIONS] = application_conf
|
|
247
250
|
|
|
248
|
-
self.
|
|
249
|
-
self.config_full_res.__delitem__("applications")
|
|
250
|
-
self.config_full_res[ADVANCED][adv_cst.EPIPOLAR_A_PRIORI] = {}
|
|
251
|
-
self.config_full_res[ADVANCED][adv_cst.TERRAIN_A_PRIORI] = {}
|
|
252
|
-
self.config_full_res[ADVANCED][adv_cst.USE_EPIPOLAR_A_PRIORI] = True
|
|
251
|
+
self.out_dir = self.used_conf[OUTPUT][out_cst.OUT_DIRECTORY]
|
|
253
252
|
|
|
254
253
|
def quit_on_app(self, app_name):
|
|
255
254
|
"""
|
|
@@ -278,34 +277,26 @@ class UnitPipeline(PipelineTemplate):
|
|
|
278
277
|
sensor_to_depth_apps = {
|
|
279
278
|
"grid_generation": 1, # and 5
|
|
280
279
|
"resampling": 2, # and 8
|
|
281
|
-
"
|
|
282
|
-
"sparse_matching.sift": 4,
|
|
280
|
+
"sparse_matching": 4,
|
|
283
281
|
"ground_truth_reprojection": 6,
|
|
284
282
|
"dense_matching": 8,
|
|
285
|
-
"dense_match_filling
|
|
286
|
-
"dense_match_filling.2": 10,
|
|
283
|
+
"dense_match_filling": 9,
|
|
287
284
|
"triangulation": 11,
|
|
288
285
|
"point_cloud_outlier_removal.1": 12,
|
|
289
286
|
"point_cloud_outlier_removal.2": 13,
|
|
290
287
|
}
|
|
291
288
|
|
|
292
|
-
depth_merge_apps = {
|
|
293
|
-
"point_cloud_fusion": 14,
|
|
294
|
-
}
|
|
295
|
-
|
|
296
289
|
depth_to_dsm_apps = {
|
|
297
|
-
"
|
|
298
|
-
"
|
|
299
|
-
"
|
|
300
|
-
"dsm_filling.
|
|
301
|
-
"dsm_filling.
|
|
302
|
-
"
|
|
303
|
-
"auxiliary_filling": 21,
|
|
290
|
+
"point_cloud_rasterization": 15,
|
|
291
|
+
"dem_generation": 16,
|
|
292
|
+
"dsm_filling.1": 17,
|
|
293
|
+
"dsm_filling.2": 18,
|
|
294
|
+
"dsm_filling.3": 19,
|
|
295
|
+
"auxiliary_filling": 20,
|
|
304
296
|
}
|
|
305
297
|
|
|
306
298
|
self.app_values = {}
|
|
307
299
|
self.app_values.update(sensor_to_depth_apps)
|
|
308
|
-
self.app_values.update(depth_merge_apps)
|
|
309
300
|
self.app_values.update(depth_to_dsm_apps)
|
|
310
301
|
|
|
311
302
|
app_conf = conf.get(APPLICATIONS, {})
|
|
@@ -327,11 +318,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
327
318
|
).format(key)
|
|
328
319
|
logging.warning(warn_msg)
|
|
329
320
|
|
|
330
|
-
elif
|
|
331
|
-
self.sensors_in_inputs
|
|
332
|
-
and not self.depth_maps_in_inputs
|
|
333
|
-
and not self.dsms_in_inputs
|
|
334
|
-
):
|
|
321
|
+
elif self.sensors_in_inputs and not self.dsms_in_inputs:
|
|
335
322
|
self.compute_depth_map = True
|
|
336
323
|
self.last_application_to_run = max(
|
|
337
324
|
self.last_application_to_run, self.app_values[key]
|
|
@@ -339,11 +326,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
339
326
|
|
|
340
327
|
elif key in depth_to_dsm_apps:
|
|
341
328
|
|
|
342
|
-
if not (
|
|
343
|
-
self.sensors_in_inputs
|
|
344
|
-
or self.depth_maps_in_inputs
|
|
345
|
-
or self.dsms_in_inputs
|
|
346
|
-
):
|
|
329
|
+
if not (self.sensors_in_inputs or self.dsms_in_inputs):
|
|
347
330
|
warn_msg = (
|
|
348
331
|
"The application {} can only be used when sensor "
|
|
349
332
|
"images or depth maps are given as an input. "
|
|
@@ -352,11 +335,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
352
335
|
logging.warning(warn_msg)
|
|
353
336
|
|
|
354
337
|
else:
|
|
355
|
-
if
|
|
356
|
-
self.sensors_in_inputs
|
|
357
|
-
and not self.depth_maps_in_inputs
|
|
358
|
-
and not self.dsms_in_inputs
|
|
359
|
-
):
|
|
338
|
+
if self.sensors_in_inputs and not self.dsms_in_inputs:
|
|
360
339
|
self.compute_depth_map = True
|
|
361
340
|
|
|
362
341
|
# enabled to start the depth map to dsm process
|
|
@@ -366,43 +345,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
366
345
|
self.last_application_to_run, self.app_values[key]
|
|
367
346
|
)
|
|
368
347
|
|
|
369
|
-
elif key in depth_merge_apps:
|
|
370
|
-
|
|
371
|
-
if not self.merging:
|
|
372
|
-
warn_msg = (
|
|
373
|
-
"The application {} can only be used when merging "
|
|
374
|
-
"is activated (this parameter is located in the "
|
|
375
|
-
"'advanced' config key). "
|
|
376
|
-
"The application's configuration will be ignored."
|
|
377
|
-
).format(key)
|
|
378
|
-
logging.warning(warn_msg)
|
|
379
|
-
|
|
380
|
-
elif not (
|
|
381
|
-
self.sensors_in_inputs
|
|
382
|
-
or self.depth_maps_in_inputs
|
|
383
|
-
or self.dsms_in_inputs
|
|
384
|
-
):
|
|
385
|
-
warn_msg = (
|
|
386
|
-
"The application {} can only be used when sensor "
|
|
387
|
-
"images or depth maps are given as an input. "
|
|
388
|
-
"Its configuration will be ignored."
|
|
389
|
-
).format(key)
|
|
390
|
-
logging.warning(warn_msg)
|
|
391
|
-
|
|
392
|
-
else:
|
|
393
|
-
if (
|
|
394
|
-
self.sensors_in_inputs
|
|
395
|
-
and not self.depth_maps_in_inputs
|
|
396
|
-
and not self.dsms_in_inputs
|
|
397
|
-
):
|
|
398
|
-
self.compute_depth_map = True
|
|
399
|
-
|
|
400
|
-
# enabled to start the depth map to dsm process
|
|
401
|
-
self.save_output_point_cloud = True
|
|
402
|
-
|
|
403
|
-
self.last_application_to_run = max(
|
|
404
|
-
self.last_application_to_run, self.app_values[key]
|
|
405
|
-
)
|
|
406
348
|
else:
|
|
407
349
|
warn_msg = (
|
|
408
350
|
"The application {} was not recognized. Its configuration"
|
|
@@ -445,30 +387,36 @@ class UnitPipeline(PipelineTemplate):
|
|
|
445
387
|
"""
|
|
446
388
|
|
|
447
389
|
output_config = {}
|
|
448
|
-
if
|
|
449
|
-
sens_cst.SENSORS in conf
|
|
450
|
-
and depth_cst.DEPTH_MAPS not in conf
|
|
451
|
-
and dsm_cst.DSMS not in conf
|
|
452
|
-
):
|
|
390
|
+
if sens_cst.SENSORS in conf and dsm_cst.DSMS not in conf:
|
|
453
391
|
output_config = sensor_inputs.sensors_check_inputs(
|
|
454
392
|
conf, config_dir=config_dir
|
|
455
393
|
)
|
|
456
|
-
elif
|
|
457
|
-
output_config = {
|
|
458
|
-
**output_config,
|
|
459
|
-
**depth_map_inputs.check_depth_maps_inputs(
|
|
460
|
-
conf, config_dir=config_dir
|
|
461
|
-
),
|
|
462
|
-
}
|
|
463
|
-
else:
|
|
394
|
+
elif dsm_cst.DSMS in conf:
|
|
464
395
|
output_config = {
|
|
465
396
|
**output_config,
|
|
466
397
|
**dsm_inputs.check_dsm_inputs(conf, config_dir=config_dir),
|
|
467
398
|
}
|
|
399
|
+
else:
|
|
400
|
+
raise RuntimeError("No sensors or dsms in inputs")
|
|
468
401
|
return output_config
|
|
469
402
|
|
|
470
|
-
|
|
471
|
-
|
|
403
|
+
def save_configurations(self):
|
|
404
|
+
"""
|
|
405
|
+
Save used_conf and refined_conf configurations
|
|
406
|
+
"""
|
|
407
|
+
|
|
408
|
+
cars_dataset.save_dict(
|
|
409
|
+
self.used_conf,
|
|
410
|
+
os.path.join(self.out_dir, "current_res_used_conf.json"),
|
|
411
|
+
safe_save=True,
|
|
412
|
+
)
|
|
413
|
+
cars_dataset.save_dict(
|
|
414
|
+
self.refined_conf,
|
|
415
|
+
os.path.join(self.out_dir, "refined_conf.json"),
|
|
416
|
+
safe_save=True,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
def check_output(self, conf, scaling_coeff):
|
|
472
420
|
"""
|
|
473
421
|
Check the output given
|
|
474
422
|
|
|
@@ -484,7 +432,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
484
432
|
def check_applications( # noqa: C901 : too complex
|
|
485
433
|
self,
|
|
486
434
|
conf,
|
|
487
|
-
key=None,
|
|
488
435
|
):
|
|
489
436
|
"""
|
|
490
437
|
Check the given configuration for applications,
|
|
@@ -495,42 +442,16 @@ class UnitPipeline(PipelineTemplate):
|
|
|
495
442
|
"""
|
|
496
443
|
scaling_coeff = self.scaling_coeff
|
|
497
444
|
|
|
445
|
+
needed_applications = application_parameters.get_needed_apps(
|
|
446
|
+
self.sensors_in_inputs,
|
|
447
|
+
self.save_output_dsm,
|
|
448
|
+
self.save_output_point_cloud,
|
|
449
|
+
conf,
|
|
450
|
+
)
|
|
451
|
+
|
|
498
452
|
# Check if all specified applications are used
|
|
499
453
|
# Application in terrain_application are note used in
|
|
500
454
|
# the sensors_to_dense_depth_maps pipeline
|
|
501
|
-
needed_applications = []
|
|
502
|
-
|
|
503
|
-
if self.sensors_in_inputs:
|
|
504
|
-
needed_applications += [
|
|
505
|
-
"grid_generation",
|
|
506
|
-
"resampling",
|
|
507
|
-
"ground_truth_reprojection",
|
|
508
|
-
"hole_detection",
|
|
509
|
-
"dense_match_filling.1",
|
|
510
|
-
"dense_match_filling.2",
|
|
511
|
-
"sparse_matching.sift",
|
|
512
|
-
"dense_matching",
|
|
513
|
-
"triangulation",
|
|
514
|
-
"dem_generation",
|
|
515
|
-
"point_cloud_outlier_removal.1",
|
|
516
|
-
"point_cloud_outlier_removal.2",
|
|
517
|
-
]
|
|
518
|
-
|
|
519
|
-
if self.save_output_dsm or self.save_output_point_cloud:
|
|
520
|
-
needed_applications += ["pc_denoising"]
|
|
521
|
-
|
|
522
|
-
if self.save_output_dsm:
|
|
523
|
-
needed_applications += [
|
|
524
|
-
"point_cloud_rasterization",
|
|
525
|
-
"dsm_filling.1",
|
|
526
|
-
"dsm_filling.2",
|
|
527
|
-
"dsm_filling.3",
|
|
528
|
-
"auxiliary_filling",
|
|
529
|
-
]
|
|
530
|
-
|
|
531
|
-
if self.merging: # we have to merge point clouds, add merging apps
|
|
532
|
-
needed_applications += ["point_cloud_fusion"]
|
|
533
|
-
|
|
534
455
|
for app_key in conf.keys():
|
|
535
456
|
if app_key not in needed_applications:
|
|
536
457
|
msg = (
|
|
@@ -543,28 +464,24 @@ class UnitPipeline(PipelineTemplate):
|
|
|
543
464
|
# Initialize used config
|
|
544
465
|
used_conf = {}
|
|
545
466
|
|
|
546
|
-
for app_key in [
|
|
547
|
-
"point_cloud_outlier_removal.1",
|
|
548
|
-
"point_cloud_outlier_removal.2",
|
|
549
|
-
"auxiliary_filling",
|
|
550
|
-
]:
|
|
551
|
-
if conf.get(app_key) is not None:
|
|
552
|
-
config_app = conf.get(app_key)
|
|
553
|
-
if "activated" not in config_app:
|
|
554
|
-
conf[app_key]["activated"] = True
|
|
555
|
-
|
|
556
467
|
for app_key in needed_applications:
|
|
557
468
|
used_conf[app_key] = conf.get(app_key, {})
|
|
469
|
+
if used_conf[app_key] is None:
|
|
470
|
+
continue
|
|
558
471
|
used_conf[app_key]["save_intermediate_data"] = (
|
|
559
472
|
self.save_all_intermediate_data
|
|
560
473
|
or used_conf[app_key].get("save_intermediate_data", False)
|
|
561
474
|
)
|
|
562
475
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
476
|
+
if app_key == "auxiliary_filling":
|
|
477
|
+
if used_conf[app_key] is not None:
|
|
478
|
+
used_conf[app_key]["activated"] = used_conf[app_key].get(
|
|
479
|
+
"activated", True
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
if app_key in [
|
|
483
|
+
"point_cloud_fusion",
|
|
484
|
+
]:
|
|
568
485
|
used_conf[app_key]["save_by_pair"] = used_conf[app_key].get(
|
|
569
486
|
"save_by_pair", self.save_all_point_clouds_by_pair
|
|
570
487
|
)
|
|
@@ -572,21 +489,18 @@ class UnitPipeline(PipelineTemplate):
|
|
|
572
489
|
self.epipolar_grid_generation_application = None
|
|
573
490
|
self.resampling_application = None
|
|
574
491
|
self.ground_truth_reprojection = None
|
|
575
|
-
self.
|
|
576
|
-
self.
|
|
577
|
-
self.dense_match_filling_2 = None
|
|
578
|
-
self.sparse_mtch_sift_app = None
|
|
492
|
+
self.dense_match_filling = None
|
|
493
|
+
self.sparse_mtch_app = None
|
|
579
494
|
self.dense_matching_app = None
|
|
580
495
|
self.triangulation_application = None
|
|
581
496
|
self.dem_generation_application = None
|
|
582
|
-
self.
|
|
583
|
-
self.pc_outlier_removal_1_app = None
|
|
584
|
-
self.pc_outlier_removal_2_app = None
|
|
497
|
+
self.pc_outlier_removal_apps = {}
|
|
585
498
|
self.rasterization_application = None
|
|
586
499
|
self.pc_fusion_application = None
|
|
587
500
|
self.dsm_filling_1_application = None
|
|
588
501
|
self.dsm_filling_2_application = None
|
|
589
502
|
self.dsm_filling_3_application = None
|
|
503
|
+
self.dsm_filling_apps = {}
|
|
590
504
|
|
|
591
505
|
if self.sensors_in_inputs:
|
|
592
506
|
# Epipolar grid generation
|
|
@@ -627,49 +541,27 @@ class UnitPipeline(PipelineTemplate):
|
|
|
627
541
|
cfg=used_conf.get("ground_truth_reprojection", {}),
|
|
628
542
|
scaling_coeff=scaling_coeff,
|
|
629
543
|
)
|
|
630
|
-
# holes detection
|
|
631
|
-
self.hole_detection_app = Application(
|
|
632
|
-
"hole_detection",
|
|
633
|
-
cfg=used_conf.get("hole_detection", {}),
|
|
634
|
-
scaling_coeff=scaling_coeff,
|
|
635
|
-
)
|
|
636
|
-
used_conf["hole_detection"] = self.hole_detection_app.get_conf()
|
|
637
544
|
|
|
638
|
-
# disparity filling
|
|
639
|
-
self.
|
|
545
|
+
# disparity filling
|
|
546
|
+
self.dense_match_filling = Application(
|
|
640
547
|
"dense_match_filling",
|
|
641
548
|
cfg=used_conf.get(
|
|
642
|
-
"dense_match_filling
|
|
643
|
-
{"method": "plane"},
|
|
644
|
-
),
|
|
645
|
-
scaling_coeff=scaling_coeff,
|
|
646
|
-
)
|
|
647
|
-
used_conf["dense_match_filling.1"] = (
|
|
648
|
-
self.dense_match_filling_1.get_conf()
|
|
649
|
-
)
|
|
650
|
-
|
|
651
|
-
# disparity filling 2
|
|
652
|
-
self.dense_match_filling_2 = Application(
|
|
653
|
-
"dense_match_filling",
|
|
654
|
-
cfg=used_conf.get(
|
|
655
|
-
"dense_match_filling.2",
|
|
549
|
+
"dense_match_filling",
|
|
656
550
|
{"method": "zero_padding"},
|
|
657
551
|
),
|
|
658
552
|
scaling_coeff=scaling_coeff,
|
|
659
553
|
)
|
|
660
|
-
used_conf["dense_match_filling
|
|
661
|
-
self.
|
|
554
|
+
used_conf["dense_match_filling"] = (
|
|
555
|
+
self.dense_match_filling.get_conf()
|
|
662
556
|
)
|
|
663
557
|
|
|
664
558
|
# Sparse Matching
|
|
665
|
-
self.
|
|
559
|
+
self.sparse_mtch_app = Application(
|
|
666
560
|
"sparse_matching",
|
|
667
|
-
cfg=used_conf.get("sparse_matching
|
|
561
|
+
cfg=used_conf.get("sparse_matching", {"method": "sift"}),
|
|
668
562
|
scaling_coeff=scaling_coeff,
|
|
669
563
|
)
|
|
670
|
-
used_conf["sparse_matching
|
|
671
|
-
self.sparse_mtch_sift_app.get_conf()
|
|
672
|
-
)
|
|
564
|
+
used_conf["sparse_matching"] = self.sparse_mtch_app.get_conf()
|
|
673
565
|
|
|
674
566
|
# Matching
|
|
675
567
|
generate_performance_map = (
|
|
@@ -692,6 +584,14 @@ class UnitPipeline(PipelineTemplate):
|
|
|
692
584
|
is None
|
|
693
585
|
):
|
|
694
586
|
dense_matching_config["performance_map_method"] = "risk"
|
|
587
|
+
|
|
588
|
+
# particular case for some epipolar resolutions
|
|
589
|
+
if not dense_matching_config:
|
|
590
|
+
used_conf["dense_matching"]["performance_map_method"] = [
|
|
591
|
+
"risk",
|
|
592
|
+
"intervals",
|
|
593
|
+
]
|
|
594
|
+
|
|
695
595
|
self.dense_matching_app = Application(
|
|
696
596
|
"dense_matching",
|
|
697
597
|
cfg=dense_matching_config,
|
|
@@ -719,47 +619,50 @@ class UnitPipeline(PipelineTemplate):
|
|
|
719
619
|
self.dem_generation_application.get_conf()
|
|
720
620
|
)
|
|
721
621
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
used_conf["point_cloud_outlier_removal.1"][
|
|
726
|
-
"method"
|
|
727
|
-
] = "small_components"
|
|
728
|
-
self.pc_outlier_removal_1_app = Application(
|
|
729
|
-
"point_cloud_outlier_removal",
|
|
730
|
-
cfg=used_conf.get(
|
|
731
|
-
"point_cloud_outlier_removal.1",
|
|
732
|
-
{"method": "small_components"},
|
|
733
|
-
),
|
|
734
|
-
scaling_coeff=scaling_coeff,
|
|
735
|
-
)
|
|
736
|
-
used_conf["point_cloud_outlier_removal.1"] = (
|
|
737
|
-
self.pc_outlier_removal_1_app.get_conf()
|
|
738
|
-
)
|
|
622
|
+
for app_key, app_conf in used_conf.items():
|
|
623
|
+
if not app_key.startswith("point_cloud_outlier_removal"):
|
|
624
|
+
continue
|
|
739
625
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
626
|
+
if app_conf is None:
|
|
627
|
+
self.pc_outlier_removal_apps = {}
|
|
628
|
+
# keep over multiple runs
|
|
629
|
+
used_conf["point_cloud_outlier_removal"] = None
|
|
630
|
+
break
|
|
631
|
+
|
|
632
|
+
if app_key in self.pc_outlier_removal_apps:
|
|
633
|
+
msg = (
|
|
634
|
+
f"The key {app_key} is defined twice in the input "
|
|
635
|
+
"configuration."
|
|
636
|
+
)
|
|
637
|
+
logging.error(msg)
|
|
638
|
+
raise NameError(msg)
|
|
639
|
+
|
|
640
|
+
if app_key[27:] == ".1":
|
|
641
|
+
app_conf.setdefault("method", "small_components")
|
|
642
|
+
if app_key[27:] == ".2":
|
|
643
|
+
app_conf.setdefault("method", "statistical")
|
|
644
|
+
|
|
645
|
+
self.pc_outlier_removal_apps[app_key] = Application(
|
|
646
|
+
"point_cloud_outlier_removal",
|
|
647
|
+
cfg=app_conf,
|
|
648
|
+
scaling_coeff=scaling_coeff,
|
|
649
|
+
)
|
|
650
|
+
used_conf[app_key] = self.pc_outlier_removal_apps[
|
|
651
|
+
app_key
|
|
652
|
+
].get_conf()
|
|
653
|
+
|
|
654
|
+
methods_str = "\n".join(
|
|
655
|
+
f" - {k}={a.used_method}"
|
|
656
|
+
for k, a in self.pc_outlier_removal_apps.items()
|
|
748
657
|
)
|
|
749
|
-
|
|
750
|
-
|
|
658
|
+
logging.info(
|
|
659
|
+
"{} point cloud outlier removal apps registered:\n{}".format(
|
|
660
|
+
len(self.pc_outlier_removal_apps), methods_str
|
|
661
|
+
)
|
|
751
662
|
)
|
|
752
663
|
|
|
753
664
|
if self.save_output_dsm or self.save_output_point_cloud:
|
|
754
665
|
|
|
755
|
-
# Point cloud denoising
|
|
756
|
-
self.pc_denoising_application = Application(
|
|
757
|
-
"pc_denoising",
|
|
758
|
-
cfg=used_conf.get("pc_denoising", {"method": "none"}),
|
|
759
|
-
scaling_coeff=scaling_coeff,
|
|
760
|
-
)
|
|
761
|
-
used_conf["pc_denoising"] = self.pc_denoising_application.get_conf()
|
|
762
|
-
|
|
763
666
|
if self.save_output_dsm:
|
|
764
667
|
|
|
765
668
|
# Rasterization
|
|
@@ -771,41 +674,51 @@ class UnitPipeline(PipelineTemplate):
|
|
|
771
674
|
used_conf["point_cloud_rasterization"] = (
|
|
772
675
|
self.rasterization_application.get_conf()
|
|
773
676
|
)
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
"dsm_filling"
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
"dsm_filling
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
677
|
+
|
|
678
|
+
for app_key, app_conf in used_conf.items():
|
|
679
|
+
if not app_key.startswith("dsm_filling"):
|
|
680
|
+
continue
|
|
681
|
+
|
|
682
|
+
if app_conf is None:
|
|
683
|
+
self.dsm_filling_apps = {}
|
|
684
|
+
# keep over multiple runs
|
|
685
|
+
used_conf["dsm_filling"] = None
|
|
686
|
+
break
|
|
687
|
+
|
|
688
|
+
if app_key in self.dsm_filling_apps:
|
|
689
|
+
msg = (
|
|
690
|
+
f"The key {app_key} is defined twice in the input "
|
|
691
|
+
"configuration."
|
|
692
|
+
)
|
|
693
|
+
logging.error(msg)
|
|
694
|
+
raise NameError(msg)
|
|
695
|
+
|
|
696
|
+
if app_key[11:] == ".1":
|
|
697
|
+
app_conf.setdefault("method", "exogenous_filling")
|
|
698
|
+
if app_key[11:] == ".2":
|
|
699
|
+
app_conf.setdefault("method", "bulldozer")
|
|
700
|
+
if app_key[11:] == ".3":
|
|
701
|
+
app_conf.setdefault("method", "border_interpolation")
|
|
702
|
+
|
|
703
|
+
self.dsm_filling_apps[app_key] = Application(
|
|
704
|
+
"dsm_filling",
|
|
705
|
+
cfg=app_conf,
|
|
706
|
+
scaling_coeff=scaling_coeff,
|
|
707
|
+
)
|
|
708
|
+
used_conf[app_key] = self.dsm_filling_apps[
|
|
709
|
+
app_key
|
|
710
|
+
].get_conf()
|
|
711
|
+
|
|
712
|
+
methods_str = "\n".join(
|
|
713
|
+
f" - {k}={a.used_method}"
|
|
714
|
+
for k, a in self.dsm_filling_apps.items()
|
|
805
715
|
)
|
|
806
|
-
|
|
807
|
-
|
|
716
|
+
logging.info(
|
|
717
|
+
"{} dsm filling apps registered:\n{}".format(
|
|
718
|
+
len(self.dsm_filling_apps), methods_str
|
|
719
|
+
)
|
|
808
720
|
)
|
|
721
|
+
|
|
809
722
|
# Auxiliary filling
|
|
810
723
|
self.auxiliary_filling_application = Application(
|
|
811
724
|
"auxiliary_filling",
|
|
@@ -816,29 +729,16 @@ class UnitPipeline(PipelineTemplate):
|
|
|
816
729
|
self.auxiliary_filling_application.get_conf()
|
|
817
730
|
)
|
|
818
731
|
|
|
819
|
-
if (
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
or self.dsm_filling_3_application.classification != ["nodata"]
|
|
732
|
+
if any(
|
|
733
|
+
app_obj.classification != ["nodata"]
|
|
734
|
+
for app_key, app_obj in self.dsm_filling_apps.items()
|
|
823
735
|
):
|
|
824
736
|
self.save_output_classif_for_filling = True
|
|
825
737
|
|
|
826
|
-
if self.merging:
|
|
827
|
-
|
|
828
|
-
# Point cloud fusion
|
|
829
|
-
self.pc_fusion_application = Application(
|
|
830
|
-
"point_cloud_fusion",
|
|
831
|
-
cfg=used_conf.get("point_cloud_fusion", {}),
|
|
832
|
-
scaling_coeff=scaling_coeff,
|
|
833
|
-
)
|
|
834
|
-
used_conf["point_cloud_fusion"] = (
|
|
835
|
-
self.pc_fusion_application.get_conf()
|
|
836
|
-
)
|
|
837
|
-
|
|
838
738
|
return used_conf
|
|
839
739
|
|
|
840
740
|
def check_applications_with_inputs( # noqa: C901 : too complex
|
|
841
|
-
self, inputs_conf, application_conf
|
|
741
|
+
self, inputs_conf, application_conf, epipolar_resolution
|
|
842
742
|
):
|
|
843
743
|
"""
|
|
844
744
|
Check for each application the input and output configuration
|
|
@@ -848,55 +748,34 @@ class UnitPipeline(PipelineTemplate):
|
|
|
848
748
|
:type inputs_conf: dict
|
|
849
749
|
:param application_conf: application checked configuration
|
|
850
750
|
:type application_conf: dict
|
|
751
|
+
:param epipolar_resolution: epipolar resolution
|
|
752
|
+
:type epipolar_resolution: int
|
|
851
753
|
"""
|
|
852
754
|
|
|
853
755
|
initial_elevation = (
|
|
854
756
|
inputs_conf[sens_cst.INITIAL_ELEVATION]["dem"] is not None
|
|
855
757
|
)
|
|
856
|
-
if self.
|
|
857
|
-
self.
|
|
858
|
-
|
|
859
|
-
] = (-500 if initial_elevation else -1000)
|
|
860
|
-
self.sparse_mtch_sift_app.elevation_delta_lower_bound = (
|
|
861
|
-
self.sparse_mtch_sift_app.used_config[
|
|
862
|
-
"elevation_delta_lower_bound"
|
|
863
|
-
]
|
|
758
|
+
if self.sparse_mtch_app.elevation_delta_lower_bound is None:
|
|
759
|
+
self.sparse_mtch_app.used_config["elevation_delta_lower_bound"] = (
|
|
760
|
+
-500 if initial_elevation else -1000
|
|
864
761
|
)
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
"elevation_delta_upper_bound"
|
|
868
|
-
] = (1000 if initial_elevation else 9000)
|
|
869
|
-
self.sparse_mtch_sift_app.elevation_delta_upper_bound = (
|
|
870
|
-
self.sparse_mtch_sift_app.used_config[
|
|
871
|
-
"elevation_delta_upper_bound"
|
|
872
|
-
]
|
|
762
|
+
self.sparse_mtch_app.elevation_delta_lower_bound = (
|
|
763
|
+
self.sparse_mtch_app.used_config["elevation_delta_lower_bound"]
|
|
873
764
|
)
|
|
874
|
-
|
|
875
|
-
self.
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
)
|
|
882
|
-
first_image_path = next(iter(inputs_conf["sensors"].values()))[
|
|
883
|
-
"image"
|
|
884
|
-
]["main_file"]
|
|
885
|
-
first_image_size = rasterio_get_size(first_image_path)
|
|
886
|
-
first_image_nb_pixels = math.prod(first_image_size)
|
|
887
|
-
dem_gen_used_mem = first_image_nb_pixels / 1e8
|
|
888
|
-
if dem_gen_used_mem > 8:
|
|
889
|
-
logging.warning(
|
|
890
|
-
"DEM generation method is 'bulldozer_on_raster'. "
|
|
891
|
-
f"This method can use up to {dem_gen_used_mem} Gb "
|
|
892
|
-
"of memory. If you think that it is too much for "
|
|
893
|
-
"your computer, you can re-lauch the run using "
|
|
894
|
-
"'dichotomic' method for DEM generation"
|
|
895
|
-
)
|
|
765
|
+
if self.sparse_mtch_app.elevation_delta_upper_bound is None:
|
|
766
|
+
self.sparse_mtch_app.used_config["elevation_delta_upper_bound"] = (
|
|
767
|
+
1000 if initial_elevation else 9000
|
|
768
|
+
)
|
|
769
|
+
self.sparse_mtch_app.elevation_delta_upper_bound = (
|
|
770
|
+
self.sparse_mtch_app.used_config["elevation_delta_upper_bound"]
|
|
771
|
+
)
|
|
772
|
+
application_conf["sparse_matching"] = self.sparse_mtch_app.get_conf()
|
|
896
773
|
|
|
897
774
|
# check classification application parameter compare
|
|
898
775
|
# to each sensors inputs classification list
|
|
899
776
|
for application_key in application_conf:
|
|
777
|
+
if application_conf[application_key] is None:
|
|
778
|
+
continue
|
|
900
779
|
if "classification" in application_conf[application_key]:
|
|
901
780
|
for item in inputs_conf["sensors"]:
|
|
902
781
|
if "classification" in inputs_conf["sensors"][item].keys():
|
|
@@ -931,44 +810,123 @@ class UnitPipeline(PipelineTemplate):
|
|
|
931
810
|
)
|
|
932
811
|
for key1, key2 in inputs_conf["pairing"]:
|
|
933
812
|
corr_cfg = self.dense_matching_app.loader.get_conf()
|
|
934
|
-
|
|
935
|
-
|
|
813
|
+
nodata_left = inputs_conf["sensors"][key2]["image"]["no_data"]
|
|
814
|
+
nodata_right = inputs_conf["sensors"][key2]["image"]["no_data"]
|
|
936
815
|
bands_left = list(
|
|
937
816
|
inputs_conf["sensors"][key1]["image"]["bands"].keys()
|
|
938
817
|
)
|
|
939
818
|
bands_right = list(
|
|
940
819
|
inputs_conf["sensors"][key2]["image"]["bands"].keys()
|
|
941
820
|
)
|
|
942
|
-
|
|
943
|
-
|
|
821
|
+
bands_classif_left = None
|
|
822
|
+
bands_classif_right = None
|
|
944
823
|
if (
|
|
945
824
|
"classification" in inputs_conf["sensors"][key1]
|
|
946
825
|
and inputs_conf["sensors"][key1]["classification"] is not None
|
|
947
826
|
):
|
|
948
|
-
|
|
949
|
-
"
|
|
950
|
-
]
|
|
827
|
+
bands_classif_left = inputs_conf["sensors"][key1][
|
|
828
|
+
"classification"
|
|
829
|
+
]["bands"].keys()
|
|
951
830
|
if (
|
|
952
831
|
"classification" in inputs_conf["sensors"][key2]
|
|
953
832
|
and inputs_conf["sensors"][key2]["classification"] is not None
|
|
954
833
|
):
|
|
955
|
-
|
|
956
|
-
"
|
|
957
|
-
]
|
|
834
|
+
bands_classif_right = inputs_conf["sensors"][key2][
|
|
835
|
+
"classification"
|
|
836
|
+
]["bands"].keys()
|
|
958
837
|
self.dense_matching_app.corr_config = (
|
|
959
838
|
self.dense_matching_app.loader.check_conf(
|
|
960
839
|
corr_cfg,
|
|
961
|
-
|
|
962
|
-
|
|
840
|
+
nodata_left,
|
|
841
|
+
nodata_right,
|
|
963
842
|
bands_left,
|
|
964
843
|
bands_right,
|
|
965
|
-
|
|
966
|
-
|
|
844
|
+
bands_classif_left,
|
|
845
|
+
bands_classif_right,
|
|
967
846
|
)
|
|
968
847
|
)
|
|
969
848
|
|
|
849
|
+
# Change the step regarding the resolution
|
|
850
|
+
# For the small resolution, the resampling perform better
|
|
851
|
+
# with a small step
|
|
852
|
+
# For the higher ones, a step at 30 should be better
|
|
853
|
+
first_image_path = next(iter(inputs_conf["sensors"].values()))["image"][
|
|
854
|
+
"main_file"
|
|
855
|
+
]
|
|
856
|
+
first_image_size = rasterio_get_size(first_image_path)
|
|
857
|
+
size_low_res_img_row = first_image_size[0] // epipolar_resolution
|
|
858
|
+
size_low_res_img_col = first_image_size[1] // epipolar_resolution
|
|
859
|
+
if epipolar_resolution > 1:
|
|
860
|
+
if size_low_res_img_row <= 900 and size_low_res_img_col <= 900:
|
|
861
|
+
application_conf["grid_generation"]["epi_step"] = (
|
|
862
|
+
epipolar_resolution * 5
|
|
863
|
+
)
|
|
864
|
+
else:
|
|
865
|
+
application_conf["grid_generation"]["epi_step"] = (
|
|
866
|
+
epipolar_resolution * 30
|
|
867
|
+
)
|
|
868
|
+
|
|
970
869
|
return application_conf
|
|
971
870
|
|
|
871
|
+
def generate_grid_correction_on_dem(self, pair_key, geo_plugin_on_dem):
|
|
872
|
+
"""
|
|
873
|
+
Generate the epipolar grid correction for a given pair, using given dem
|
|
874
|
+
"""
|
|
875
|
+
|
|
876
|
+
# Generate new grids with dem
|
|
877
|
+
# Generate rectification grids
|
|
878
|
+
(
|
|
879
|
+
grid_left_new_dem,
|
|
880
|
+
grid_right_new_dem,
|
|
881
|
+
) = self.epipolar_grid_generation_application.run(
|
|
882
|
+
self.pairs[pair_key]["sensor_image_left"],
|
|
883
|
+
self.pairs[pair_key]["sensor_image_right"],
|
|
884
|
+
geo_plugin_on_dem,
|
|
885
|
+
orchestrator=self.cars_orchestrator,
|
|
886
|
+
pair_folder=os.path.join(
|
|
887
|
+
self.dump_dir,
|
|
888
|
+
"epipolar_grid_generation",
|
|
889
|
+
"new_dem",
|
|
890
|
+
pair_key,
|
|
891
|
+
),
|
|
892
|
+
pair_key=pair_key,
|
|
893
|
+
)
|
|
894
|
+
|
|
895
|
+
if self.pairs[pair_key].get("sensor_matches_left", None) is None:
|
|
896
|
+
logging.error(
|
|
897
|
+
"No sensor matches available to compute grid correction"
|
|
898
|
+
)
|
|
899
|
+
return None
|
|
900
|
+
|
|
901
|
+
# Generate new matches with new grids
|
|
902
|
+
new_grid_matches_array = geo_plugin_on_dem.transform_matches_from_grids(
|
|
903
|
+
self.pairs[pair_key]["sensor_matches_left"],
|
|
904
|
+
self.pairs[pair_key]["sensor_matches_right"],
|
|
905
|
+
grid_left_new_dem,
|
|
906
|
+
grid_right_new_dem,
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
# Generate grid_correction
|
|
910
|
+
# Compute grid correction
|
|
911
|
+
(
|
|
912
|
+
new_grid_correction_coef,
|
|
913
|
+
_,
|
|
914
|
+
_,
|
|
915
|
+
_,
|
|
916
|
+
) = grid_correction_app.estimate_right_grid_correction(
|
|
917
|
+
new_grid_matches_array,
|
|
918
|
+
grid_right_new_dem,
|
|
919
|
+
save_matches=False,
|
|
920
|
+
minimum_nb_matches=0,
|
|
921
|
+
pair_folder=os.path.join(
|
|
922
|
+
self.dump_dir, "grid_correction", " new_dem", pair_key
|
|
923
|
+
),
|
|
924
|
+
pair_key=pair_key,
|
|
925
|
+
orchestrator=self.cars_orchestrator,
|
|
926
|
+
)
|
|
927
|
+
|
|
928
|
+
return new_grid_correction_coef
|
|
929
|
+
|
|
972
930
|
def sensor_to_depth_maps(self): # noqa: C901
|
|
973
931
|
"""
|
|
974
932
|
Creates the depth map from the sensor images given in the input,
|
|
@@ -992,7 +950,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
992
950
|
self.input_roi_poly, self.input_roi_epsg, self.epsg
|
|
993
951
|
)
|
|
994
952
|
|
|
995
|
-
self.resolution = output[out_cst.RESOLUTION]
|
|
953
|
+
self.resolution = output[out_cst.RESOLUTION]
|
|
996
954
|
|
|
997
955
|
# List of terrain roi corresponding to each epipolar pair
|
|
998
956
|
# Used to generate final terrain roi
|
|
@@ -1027,7 +985,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1027
985
|
# used in dem generation
|
|
1028
986
|
self.triangulated_matches_list = []
|
|
1029
987
|
|
|
1030
|
-
save_matches = self.
|
|
988
|
+
save_matches = self.sparse_mtch_app.get_save_matches()
|
|
1031
989
|
|
|
1032
990
|
save_corrected_grid = (
|
|
1033
991
|
self.epipolar_grid_generation_application.get_save_grids()
|
|
@@ -1050,21 +1008,10 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1050
1008
|
# We generate grids with dem if it is provided.
|
|
1051
1009
|
# If not provided, grid are generated without dem and a dem
|
|
1052
1010
|
# will be generated, to use later for a new grid generation**
|
|
1053
|
-
altitude_delta_min = inputs.get(sens_cst.INITIAL_ELEVATION, {}).get(
|
|
1054
|
-
sens_cst.ALTITUDE_DELTA_MIN, None
|
|
1055
|
-
)
|
|
1056
|
-
altitude_delta_max = inputs.get(sens_cst.INITIAL_ELEVATION, {}).get(
|
|
1057
|
-
sens_cst.ALTITUDE_DELTA_MAX, None
|
|
1058
|
-
)
|
|
1059
1011
|
|
|
1060
1012
|
if inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH] is None:
|
|
1061
1013
|
geom_plugin = self.geom_plugin_without_dem_and_geoid
|
|
1062
1014
|
|
|
1063
|
-
if None not in (altitude_delta_min, altitude_delta_max):
|
|
1064
|
-
raise RuntimeError(
|
|
1065
|
-
"Dem path is mandatory for "
|
|
1066
|
-
"the use of altitude deltas"
|
|
1067
|
-
)
|
|
1068
1015
|
else:
|
|
1069
1016
|
geom_plugin = self.geom_plugin_with_dem_and_geoid
|
|
1070
1017
|
|
|
@@ -1089,43 +1036,15 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1089
1036
|
if self.quit_on_app("grid_generation"):
|
|
1090
1037
|
continue # keep iterating over pairs, but don't go further
|
|
1091
1038
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
self.pairs[pair_key]["holes_classif"] = []
|
|
1097
|
-
self.pairs[pair_key]["holes_poly_margin"] = 0
|
|
1098
|
-
add_classif = False
|
|
1099
|
-
if self.dense_match_filling_1.used_method == "plane":
|
|
1100
|
-
self.pairs[pair_key][
|
|
1101
|
-
"holes_classif"
|
|
1102
|
-
] += self.dense_match_filling_1.get_classif()
|
|
1103
|
-
self.pairs[pair_key]["holes_poly_margin"] = max(
|
|
1104
|
-
self.pairs[pair_key]["holes_poly_margin"],
|
|
1105
|
-
self.dense_match_filling_1.get_poly_margin(),
|
|
1106
|
-
)
|
|
1107
|
-
add_classif = True
|
|
1108
|
-
if self.dense_match_filling_2.used_method == "plane":
|
|
1109
|
-
self.pairs[pair_key][
|
|
1110
|
-
"holes_classif"
|
|
1111
|
-
] += self.dense_match_filling_2.get_classif()
|
|
1112
|
-
self.pairs[pair_key]["holes_poly_margin"] = max(
|
|
1113
|
-
self.pairs[pair_key]["holes_poly_margin"],
|
|
1114
|
-
self.dense_match_filling_2.get_poly_margin(),
|
|
1115
|
-
)
|
|
1116
|
-
add_classif = True
|
|
1117
|
-
|
|
1118
|
-
self.pairs[pair_key]["holes_bbox_left"] = []
|
|
1119
|
-
self.pairs[pair_key]["holes_bbox_right"] = []
|
|
1120
|
-
|
|
1121
|
-
if self.used_conf[ADVANCED][
|
|
1122
|
-
adv_cst.USE_EPIPOLAR_A_PRIORI
|
|
1123
|
-
] is False or (len(self.pairs[pair_key]["holes_classif"]) > 0):
|
|
1039
|
+
if self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI] in (
|
|
1040
|
+
None,
|
|
1041
|
+
{},
|
|
1042
|
+
):
|
|
1124
1043
|
# Run resampling only if needed:
|
|
1125
|
-
# no a priori
|
|
1044
|
+
# no a priori
|
|
1126
1045
|
|
|
1127
1046
|
# Get required bands of first resampling
|
|
1128
|
-
required_bands = self.
|
|
1047
|
+
required_bands = self.sparse_mtch_app.get_required_bands()
|
|
1129
1048
|
|
|
1130
1049
|
# Run first epipolar resampling
|
|
1131
1050
|
(
|
|
@@ -1142,49 +1061,30 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1142
1061
|
self.dump_dir, "resampling", "initial", pair_key
|
|
1143
1062
|
),
|
|
1144
1063
|
pair_key=pair_key,
|
|
1145
|
-
margins_fun=self.
|
|
1064
|
+
margins_fun=self.sparse_mtch_app.get_margins_fun(),
|
|
1146
1065
|
tile_width=None,
|
|
1147
1066
|
tile_height=None,
|
|
1148
|
-
add_classif=add_classif,
|
|
1149
1067
|
required_bands=required_bands,
|
|
1150
1068
|
)
|
|
1151
1069
|
|
|
1152
1070
|
if self.quit_on_app("resampling"):
|
|
1153
1071
|
continue # keep iterating over pairs, but don't go further
|
|
1154
1072
|
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
self.pairs[pair_key]["holes_bbox_left"],
|
|
1160
|
-
self.pairs[pair_key]["holes_bbox_right"],
|
|
1161
|
-
) = self.hole_detection_app.run(
|
|
1162
|
-
self.pairs[pair_key]["epipolar_image_left"],
|
|
1163
|
-
self.pairs[pair_key]["epipolar_image_right"],
|
|
1164
|
-
classification=self.pairs[pair_key]["holes_classif"],
|
|
1165
|
-
margin=self.pairs[pair_key]["holes_poly_margin"],
|
|
1166
|
-
orchestrator=self.cars_orchestrator,
|
|
1167
|
-
pair_folder=os.path.join(
|
|
1168
|
-
self.dump_dir, "hole_detection", pair_key
|
|
1169
|
-
),
|
|
1170
|
-
pair_key=pair_key,
|
|
1171
|
-
)
|
|
1172
|
-
|
|
1173
|
-
if self.quit_on_app("hole_detection"):
|
|
1174
|
-
continue # keep iterating over pairs, but don't go further
|
|
1175
|
-
|
|
1176
|
-
if self.used_conf[ADVANCED][adv_cst.USE_EPIPOLAR_A_PRIORI] is False:
|
|
1073
|
+
if self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI] in (
|
|
1074
|
+
None,
|
|
1075
|
+
{},
|
|
1076
|
+
):
|
|
1177
1077
|
# Run epipolar sparse_matching application
|
|
1178
1078
|
(
|
|
1179
1079
|
self.pairs[pair_key]["epipolar_matches_left"],
|
|
1180
1080
|
_,
|
|
1181
|
-
) = self.
|
|
1081
|
+
) = self.sparse_mtch_app.run(
|
|
1182
1082
|
self.pairs[pair_key]["epipolar_image_left"],
|
|
1183
1083
|
self.pairs[pair_key]["epipolar_image_right"],
|
|
1184
1084
|
self.pairs[pair_key]["grid_left"]["disp_to_alt_ratio"],
|
|
1185
1085
|
orchestrator=self.cars_orchestrator,
|
|
1186
1086
|
pair_folder=os.path.join(
|
|
1187
|
-
self.dump_dir, "sparse_matching
|
|
1087
|
+
self.dump_dir, "sparse_matching", pair_key
|
|
1188
1088
|
),
|
|
1189
1089
|
pair_key=pair_key,
|
|
1190
1090
|
)
|
|
@@ -1192,16 +1092,14 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1192
1092
|
# Run cluster breakpoint to compute sifts: force computation
|
|
1193
1093
|
self.cars_orchestrator.breakpoint()
|
|
1194
1094
|
|
|
1195
|
-
minimum_nb_matches = (
|
|
1196
|
-
self.sparse_mtch_sift_app.get_minimum_nb_matches()
|
|
1197
|
-
)
|
|
1095
|
+
minimum_nb_matches = self.sparse_mtch_app.get_minimum_nb_matches()
|
|
1198
1096
|
|
|
1199
1097
|
# Run grid correction application
|
|
1200
|
-
if self.used_conf[ADVANCED][adv_cst.
|
|
1098
|
+
if self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI] in (None, {}):
|
|
1201
1099
|
# Estimate grid correction if no epipolar a priori
|
|
1202
1100
|
# Filter and save matches
|
|
1203
1101
|
self.pairs[pair_key]["matches_array"] = (
|
|
1204
|
-
self.
|
|
1102
|
+
self.sparse_mtch_app.filter_matches(
|
|
1205
1103
|
self.pairs[pair_key]["epipolar_matches_left"],
|
|
1206
1104
|
self.pairs[pair_key]["grid_left"],
|
|
1207
1105
|
self.pairs[pair_key]["grid_right"],
|
|
@@ -1209,11 +1107,9 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1209
1107
|
orchestrator=self.cars_orchestrator,
|
|
1210
1108
|
pair_key=pair_key,
|
|
1211
1109
|
pair_folder=os.path.join(
|
|
1212
|
-
self.dump_dir, "sparse_matching
|
|
1213
|
-
),
|
|
1214
|
-
save_matches=(
|
|
1215
|
-
self.sparse_mtch_sift_app.get_save_matches()
|
|
1110
|
+
self.dump_dir, "sparse_matching", pair_key
|
|
1216
1111
|
),
|
|
1112
|
+
save_matches=(self.sparse_mtch_app.get_save_matches()),
|
|
1217
1113
|
)
|
|
1218
1114
|
)
|
|
1219
1115
|
|
|
@@ -1253,7 +1149,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1253
1149
|
pair_key
|
|
1254
1150
|
]["grid_left"]
|
|
1255
1151
|
|
|
1256
|
-
if self.quit_on_app("sparse_matching
|
|
1152
|
+
if self.quit_on_app("sparse_matching"):
|
|
1257
1153
|
continue
|
|
1258
1154
|
|
|
1259
1155
|
# Shrink disparity intervals according to SIFT disparities
|
|
@@ -1261,7 +1157,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1261
1157
|
"disp_to_alt_ratio"
|
|
1262
1158
|
]
|
|
1263
1159
|
disp_bounds_params = (
|
|
1264
|
-
self.
|
|
1160
|
+
self.sparse_mtch_app.disparity_bounds_estimation
|
|
1265
1161
|
)
|
|
1266
1162
|
|
|
1267
1163
|
if disp_bounds_params["activated"]:
|
|
@@ -1289,11 +1185,11 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1289
1185
|
)
|
|
1290
1186
|
else:
|
|
1291
1187
|
disp_min = (
|
|
1292
|
-
-self.
|
|
1188
|
+
-self.sparse_mtch_app.elevation_delta_upper_bound
|
|
1293
1189
|
/ disp_to_alt_ratio
|
|
1294
1190
|
)
|
|
1295
1191
|
disp_max = (
|
|
1296
|
-
-self.
|
|
1192
|
+
-self.sparse_mtch_app.elevation_delta_lower_bound
|
|
1297
1193
|
/ disp_to_alt_ratio
|
|
1298
1194
|
)
|
|
1299
1195
|
logging.info(
|
|
@@ -1336,12 +1232,11 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1336
1232
|
if (
|
|
1337
1233
|
self.quit_on_app("grid_generation")
|
|
1338
1234
|
or self.quit_on_app("resampling")
|
|
1339
|
-
or self.quit_on_app("
|
|
1340
|
-
or self.quit_on_app("sparse_matching.sift")
|
|
1235
|
+
or self.quit_on_app("sparse_matching")
|
|
1341
1236
|
):
|
|
1342
1237
|
return True
|
|
1343
1238
|
|
|
1344
|
-
if self.used_conf[ADVANCED][adv_cst.
|
|
1239
|
+
if not self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI] in (None, {}):
|
|
1345
1240
|
# Use a priori
|
|
1346
1241
|
dem_median = self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI][
|
|
1347
1242
|
adv_cst.DEM_MEDIAN
|
|
@@ -1352,50 +1247,10 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1352
1247
|
dem_max = self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI][
|
|
1353
1248
|
adv_cst.DEM_MAX
|
|
1354
1249
|
]
|
|
1355
|
-
altitude_delta_min = self.used_conf[ADVANCED][
|
|
1356
|
-
adv_cst.TERRAIN_A_PRIORI
|
|
1357
|
-
][adv_cst.ALTITUDE_DELTA_MIN]
|
|
1358
|
-
altitude_delta_max = self.used_conf[ADVANCED][
|
|
1359
|
-
adv_cst.TERRAIN_A_PRIORI
|
|
1360
|
-
][adv_cst.ALTITUDE_DELTA_MAX]
|
|
1361
|
-
|
|
1362
|
-
# update used configuration with terrain a priori
|
|
1363
|
-
if None not in (altitude_delta_min, altitude_delta_max):
|
|
1364
|
-
advanced_parameters.update_conf(
|
|
1365
|
-
self.used_conf,
|
|
1366
|
-
dem_median=dem_median,
|
|
1367
|
-
altitude_delta_min=altitude_delta_min,
|
|
1368
|
-
altitude_delta_max=altitude_delta_max,
|
|
1369
|
-
)
|
|
1370
|
-
else:
|
|
1371
|
-
advanced_parameters.update_conf(
|
|
1372
|
-
self.used_conf,
|
|
1373
|
-
dem_median=dem_median,
|
|
1374
|
-
dem_min=dem_min,
|
|
1375
|
-
dem_max=dem_max,
|
|
1376
|
-
)
|
|
1377
|
-
|
|
1378
|
-
advanced_parameters.update_conf(
|
|
1379
|
-
self.config_full_res,
|
|
1380
|
-
dem_median=dem_median,
|
|
1381
|
-
dem_min=dem_min,
|
|
1382
|
-
dem_max=dem_max,
|
|
1383
|
-
)
|
|
1384
|
-
|
|
1385
|
-
# quit only after the configuration was updated
|
|
1386
|
-
if self.quit_on_app("dem_generation"):
|
|
1387
|
-
return True
|
|
1388
1250
|
|
|
1389
1251
|
# Define param
|
|
1390
1252
|
use_global_disp_range = self.dense_matching_app.use_global_disp_range
|
|
1391
1253
|
|
|
1392
|
-
if self.pc_denoising_application is not None:
|
|
1393
|
-
denoising_overload_fun = (
|
|
1394
|
-
self.pc_denoising_application.get_triangulation_overload()
|
|
1395
|
-
)
|
|
1396
|
-
else:
|
|
1397
|
-
denoising_overload_fun = None
|
|
1398
|
-
|
|
1399
1254
|
self.pairs_names = [
|
|
1400
1255
|
pair_name for pair_name, _, _ in self.list_sensor_pairs
|
|
1401
1256
|
]
|
|
@@ -1404,7 +1259,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1404
1259
|
# Geometry plugin with dem will be used for the grid generation
|
|
1405
1260
|
geom_plugin = self.geom_plugin_with_dem_and_geoid
|
|
1406
1261
|
|
|
1407
|
-
if self.used_conf[ADVANCED][adv_cst.
|
|
1262
|
+
if self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI] in (None, {}):
|
|
1408
1263
|
save_matches = True
|
|
1409
1264
|
|
|
1410
1265
|
(
|
|
@@ -1420,7 +1275,8 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1420
1275
|
save_matches=save_matches,
|
|
1421
1276
|
)
|
|
1422
1277
|
elif (
|
|
1423
|
-
self.used_conf[ADVANCED][adv_cst.
|
|
1278
|
+
not self.used_conf[ADVANCED][adv_cst.TERRAIN_A_PRIORI]
|
|
1279
|
+
in (None, {})
|
|
1424
1280
|
and not self.use_sift_a_priori
|
|
1425
1281
|
):
|
|
1426
1282
|
# Use epipolar a priori
|
|
@@ -1431,7 +1287,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1431
1287
|
][pair_key][adv_cst.DISPARITY_RANGE]
|
|
1432
1288
|
|
|
1433
1289
|
advanced_parameters.update_conf(
|
|
1434
|
-
self.
|
|
1290
|
+
self.refined_conf,
|
|
1435
1291
|
dmin=dmin,
|
|
1436
1292
|
dmax=dmax,
|
|
1437
1293
|
pair_key=pair_key,
|
|
@@ -1470,7 +1326,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1470
1326
|
# Correct grids with former matches
|
|
1471
1327
|
# Transform matches to new grids
|
|
1472
1328
|
|
|
1473
|
-
save_matches = self.
|
|
1329
|
+
save_matches = self.sparse_mtch_app.get_save_matches()
|
|
1474
1330
|
|
|
1475
1331
|
self.sensor_matches_left = os.path.join(
|
|
1476
1332
|
self.first_res_out_dir,
|
|
@@ -1552,28 +1408,19 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1552
1408
|
right=True,
|
|
1553
1409
|
)
|
|
1554
1410
|
|
|
1555
|
-
# Update
|
|
1556
|
-
# Add global min and max computed with grids
|
|
1557
|
-
advanced_parameters.update_conf(
|
|
1558
|
-
self.used_conf,
|
|
1559
|
-
grid_correction_coef=self.pairs[pair_key][
|
|
1560
|
-
"grid_correction_coef"
|
|
1561
|
-
],
|
|
1562
|
-
pair_key=pair_key,
|
|
1563
|
-
)
|
|
1411
|
+
# Update refined_conf configuration with epipolar a priori
|
|
1564
1412
|
advanced_parameters.update_conf(
|
|
1565
|
-
self.
|
|
1413
|
+
self.refined_conf,
|
|
1566
1414
|
grid_correction_coef=self.pairs[pair_key][
|
|
1567
1415
|
"grid_correction_coef"
|
|
1568
1416
|
],
|
|
1569
1417
|
pair_key=pair_key,
|
|
1418
|
+
reference_dem=self.used_conf[INPUTS][
|
|
1419
|
+
sens_cst.INITIAL_ELEVATION
|
|
1420
|
+
][sens_cst.DEM_PATH],
|
|
1570
1421
|
)
|
|
1571
1422
|
# saved used configuration
|
|
1572
|
-
|
|
1573
|
-
self.used_conf,
|
|
1574
|
-
os.path.join(self.out_dir, "used_conf.json"),
|
|
1575
|
-
safe_save=True,
|
|
1576
|
-
)
|
|
1423
|
+
self.save_configurations()
|
|
1577
1424
|
|
|
1578
1425
|
# Generate min and max disp grids
|
|
1579
1426
|
# Global disparity min and max will be computed from
|
|
@@ -1582,11 +1429,9 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1582
1429
|
self.dump_dir, "dense_matching", pair_key
|
|
1583
1430
|
)
|
|
1584
1431
|
|
|
1585
|
-
if (
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
is False
|
|
1589
|
-
):
|
|
1432
|
+
if self.which_resolution in ("first", "single") and self.used_conf[
|
|
1433
|
+
ADVANCED
|
|
1434
|
+
][adv_cst.TERRAIN_A_PRIORI] in (None, {}):
|
|
1590
1435
|
dmin = disp_min / self.res_resamp
|
|
1591
1436
|
dmax = disp_max / self.res_resamp
|
|
1592
1437
|
# generate_disparity_grids runs orchestrator.breakpoint()
|
|
@@ -1602,7 +1447,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1602
1447
|
)
|
|
1603
1448
|
)
|
|
1604
1449
|
|
|
1605
|
-
dsp_marg = self.
|
|
1450
|
+
dsp_marg = self.sparse_mtch_app.get_disparity_margin()
|
|
1606
1451
|
updating_infos = {
|
|
1607
1452
|
application_constants.APPLICATION_TAG: {
|
|
1608
1453
|
sm_cst.DISPARITY_RANGE_COMPUTATION_TAG: {
|
|
@@ -1617,42 +1462,26 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1617
1462
|
self.cars_orchestrator.update_out_info(updating_infos)
|
|
1618
1463
|
|
|
1619
1464
|
advanced_parameters.update_conf(
|
|
1620
|
-
self.
|
|
1465
|
+
self.refined_conf,
|
|
1621
1466
|
dmin=dmin,
|
|
1622
1467
|
dmax=dmax,
|
|
1623
1468
|
pair_key=pair_key,
|
|
1624
1469
|
)
|
|
1625
1470
|
else:
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
self.
|
|
1630
|
-
self.
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
orchestrator=self.cars_orchestrator,
|
|
1639
|
-
)
|
|
1640
|
-
)
|
|
1641
|
-
else:
|
|
1642
|
-
# Generate min and max disp grids from deltas
|
|
1643
|
-
# generate_disparity_grids runs orchestrator.breakpoint()
|
|
1644
|
-
self.pairs[pair_key]["disp_range_grid"] = (
|
|
1645
|
-
self.dense_matching_app.generate_disparity_grids(
|
|
1646
|
-
self.pairs[pair_key]["sensor_image_right"],
|
|
1647
|
-
self.pairs[pair_key]["corrected_grid_right"],
|
|
1648
|
-
self.geom_plugin_with_dem_and_geoid,
|
|
1649
|
-
altitude_delta_min=altitude_delta_min,
|
|
1650
|
-
altitude_delta_max=altitude_delta_max,
|
|
1651
|
-
dem_median=dem_median,
|
|
1652
|
-
pair_folder=dense_matching_pair_folder,
|
|
1653
|
-
orchestrator=self.cars_orchestrator,
|
|
1654
|
-
)
|
|
1471
|
+
# Generate min and max disp grids from dems
|
|
1472
|
+
# generate_disparity_grids runs orchestrator.breakpoint()
|
|
1473
|
+
self.pairs[pair_key]["disp_range_grid"] = (
|
|
1474
|
+
self.dense_matching_app.generate_disparity_grids(
|
|
1475
|
+
self.pairs[pair_key]["sensor_image_right"],
|
|
1476
|
+
self.pairs[pair_key]["corrected_grid_right"],
|
|
1477
|
+
self.geom_plugin_with_dem_and_geoid,
|
|
1478
|
+
dem_min=dem_min,
|
|
1479
|
+
dem_max=dem_max,
|
|
1480
|
+
dem_median=dem_median,
|
|
1481
|
+
pair_folder=dense_matching_pair_folder,
|
|
1482
|
+
orchestrator=self.cars_orchestrator,
|
|
1655
1483
|
)
|
|
1484
|
+
)
|
|
1656
1485
|
|
|
1657
1486
|
if use_global_disp_range:
|
|
1658
1487
|
# Generate min and max disp grids from constants
|
|
@@ -1668,7 +1497,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1668
1497
|
]
|
|
1669
1498
|
|
|
1670
1499
|
# update orchestrator_out_json
|
|
1671
|
-
marg = self.
|
|
1500
|
+
marg = self.sparse_mtch_app.get_disparity_margin()
|
|
1672
1501
|
updating_infos = {
|
|
1673
1502
|
application_constants.APPLICATION_TAG: {
|
|
1674
1503
|
sm_cst.DISPARITY_RANGE_COMPUTATION_TAG: {
|
|
@@ -1683,7 +1512,7 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1683
1512
|
self.cars_orchestrator.update_out_info(updating_infos)
|
|
1684
1513
|
|
|
1685
1514
|
advanced_parameters.update_conf(
|
|
1686
|
-
self.
|
|
1515
|
+
self.refined_conf,
|
|
1687
1516
|
dmin=dmin,
|
|
1688
1517
|
dmax=dmax,
|
|
1689
1518
|
pair_key=pair_key,
|
|
@@ -1706,24 +1535,20 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1706
1535
|
# Update used_conf configuration with epipolar a priori
|
|
1707
1536
|
# Add global min and max computed with grids
|
|
1708
1537
|
advanced_parameters.update_conf(
|
|
1709
|
-
self.
|
|
1538
|
+
self.refined_conf,
|
|
1710
1539
|
dmin=self.pairs[pair_key]["disp_range_grid"]["global_min"],
|
|
1711
1540
|
dmax=self.pairs[pair_key]["disp_range_grid"]["global_max"],
|
|
1712
1541
|
pair_key=pair_key,
|
|
1713
1542
|
)
|
|
1714
1543
|
advanced_parameters.update_conf(
|
|
1715
|
-
self.
|
|
1544
|
+
self.refined_conf,
|
|
1716
1545
|
dmin=self.pairs[pair_key]["disp_range_grid"]["global_min"],
|
|
1717
1546
|
dmax=self.pairs[pair_key]["disp_range_grid"]["global_max"],
|
|
1718
1547
|
pair_key=pair_key,
|
|
1719
1548
|
)
|
|
1720
1549
|
|
|
1721
1550
|
# saved used configuration
|
|
1722
|
-
|
|
1723
|
-
self.used_conf,
|
|
1724
|
-
os.path.join(self.out_dir, "used_conf.json"),
|
|
1725
|
-
safe_save=True,
|
|
1726
|
-
)
|
|
1551
|
+
self.save_configurations()
|
|
1727
1552
|
|
|
1728
1553
|
# end of for loop, to finish computing disparity range grids
|
|
1729
1554
|
|
|
@@ -1780,6 +1605,10 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1780
1605
|
)
|
|
1781
1606
|
)
|
|
1782
1607
|
|
|
1608
|
+
# Quick fix to reduce memory usage
|
|
1609
|
+
if self.res_resamp >= 16:
|
|
1610
|
+
optimum_tile_size = 200
|
|
1611
|
+
|
|
1783
1612
|
# Run third epipolar resampling
|
|
1784
1613
|
(
|
|
1785
1614
|
new_epipolar_image_left,
|
|
@@ -1913,28 +1742,11 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1913
1742
|
)
|
|
1914
1743
|
|
|
1915
1744
|
if self.which_resolution not in ("final", "single"):
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
self.
|
|
1920
|
-
|
|
1921
|
-
self.dem_generation_roi.bounds,
|
|
1922
|
-
4326,
|
|
1923
|
-
self.epsg,
|
|
1924
|
-
self.dem_generation_application.margin,
|
|
1925
|
-
)
|
|
1926
|
-
)
|
|
1927
|
-
else:
|
|
1928
|
-
# ROI has not been computed
|
|
1929
|
-
self.terrain_bounds = (
|
|
1930
|
-
dem_wrappers.modify_terrain_bounds(
|
|
1931
|
-
self.terrain_bounds,
|
|
1932
|
-
self.epsg,
|
|
1933
|
-
self.epsg,
|
|
1934
|
-
self.dem_generation_application.margin,
|
|
1935
|
-
0.7,
|
|
1936
|
-
)
|
|
1937
|
-
)
|
|
1745
|
+
self.terrain_bounds = dem_wrappers.modify_terrain_bounds(
|
|
1746
|
+
self.terrain_bounds,
|
|
1747
|
+
self.dem_generation_application.margin[0],
|
|
1748
|
+
self.dem_generation_application.margin[1],
|
|
1749
|
+
)
|
|
1938
1750
|
|
|
1939
1751
|
if self.dense_matching_app.get_method() == "auto":
|
|
1940
1752
|
# Copy the initial corr_config in order to keep
|
|
@@ -1953,9 +1765,12 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1953
1765
|
# the dense matching app
|
|
1954
1766
|
# Because we kept the information regarding the ambiguity,
|
|
1955
1767
|
# performance_map calculus..
|
|
1956
|
-
self.used_conf["applications"]["dense_matching"][
|
|
1957
|
-
"
|
|
1958
|
-
] = conf
|
|
1768
|
+
self.used_conf["applications"]["dense_matching"][
|
|
1769
|
+
"loader_conf"
|
|
1770
|
+
] = conf
|
|
1771
|
+
self.used_conf["applications"]["dense_matching"][
|
|
1772
|
+
"method"
|
|
1773
|
+
] = "custom"
|
|
1959
1774
|
|
|
1960
1775
|
# Re initialization of the dense matching application
|
|
1961
1776
|
self.dense_matching_app = Application(
|
|
@@ -1979,9 +1794,9 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1979
1794
|
pair_key=pair_key,
|
|
1980
1795
|
disp_range_grid=self.pairs[pair_key]["disp_range_grid"],
|
|
1981
1796
|
compute_disparity_masks=False,
|
|
1982
|
-
margins_to_keep=(
|
|
1983
|
-
|
|
1984
|
-
|
|
1797
|
+
margins_to_keep=sum(
|
|
1798
|
+
app.get_epipolar_margin()
|
|
1799
|
+
for _, app in self.pc_outlier_removal_apps.items()
|
|
1985
1800
|
),
|
|
1986
1801
|
texture_bands=texture_bands_indices,
|
|
1987
1802
|
)
|
|
@@ -1989,81 +1804,17 @@ class UnitPipeline(PipelineTemplate):
|
|
|
1989
1804
|
if self.quit_on_app("dense_matching"):
|
|
1990
1805
|
continue # keep iterating over pairs, but don't go further
|
|
1991
1806
|
|
|
1992
|
-
#
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
"global_min"
|
|
2002
|
-
],
|
|
2003
|
-
disp_max=np.max(
|
|
2004
|
-
self.pairs[pair_key]["disp_range_grid"][
|
|
2005
|
-
"global_max"
|
|
2006
|
-
]
|
|
2007
|
-
),
|
|
2008
|
-
orchestrator=self.cars_orchestrator,
|
|
2009
|
-
pair_folder=os.path.join(
|
|
2010
|
-
self.dump_dir, "dense_match_filling_1", pair_key
|
|
2011
|
-
),
|
|
2012
|
-
pair_key=pair_key,
|
|
2013
|
-
)
|
|
2014
|
-
)
|
|
2015
|
-
else:
|
|
2016
|
-
# Fill with zeros
|
|
2017
|
-
(filled_with_1_epipolar_disparity_map) = (
|
|
2018
|
-
self.dense_match_filling_1.run(
|
|
2019
|
-
epipolar_disparity_map,
|
|
2020
|
-
orchestrator=self.cars_orchestrator,
|
|
2021
|
-
pair_folder=os.path.join(
|
|
2022
|
-
self.dump_dir, "dense_match_filling_1", pair_key
|
|
2023
|
-
),
|
|
2024
|
-
pair_key=pair_key,
|
|
2025
|
-
)
|
|
2026
|
-
)
|
|
2027
|
-
|
|
2028
|
-
if self.quit_on_app("dense_match_filling.1"):
|
|
2029
|
-
continue # keep iterating over pairs, but don't go further
|
|
2030
|
-
|
|
2031
|
-
if self.dense_match_filling_2.used_method == "plane":
|
|
2032
|
-
# Fill holes in disparity map
|
|
2033
|
-
(filled_with_2_epipolar_disparity_map) = (
|
|
2034
|
-
self.dense_match_filling_2.run(
|
|
2035
|
-
filled_with_1_epipolar_disparity_map,
|
|
2036
|
-
self.pairs[pair_key]["holes_bbox_left"],
|
|
2037
|
-
self.pairs[pair_key]["holes_bbox_right"],
|
|
2038
|
-
disp_min=self.pairs[pair_key]["disp_range_grid"][
|
|
2039
|
-
"global_min"
|
|
2040
|
-
],
|
|
2041
|
-
disp_max=np.max(
|
|
2042
|
-
self.pairs[pair_key]["disp_range_grid"][
|
|
2043
|
-
"global_max"
|
|
2044
|
-
]
|
|
2045
|
-
),
|
|
2046
|
-
orchestrator=self.cars_orchestrator,
|
|
2047
|
-
pair_folder=os.path.join(
|
|
2048
|
-
self.dump_dir, "dense_match_filling_2", pair_key
|
|
2049
|
-
),
|
|
2050
|
-
pair_key=pair_key,
|
|
2051
|
-
)
|
|
2052
|
-
)
|
|
2053
|
-
else:
|
|
2054
|
-
# Fill with zeros
|
|
2055
|
-
(filled_with_2_epipolar_disparity_map) = (
|
|
2056
|
-
self.dense_match_filling_2.run(
|
|
2057
|
-
filled_with_1_epipolar_disparity_map,
|
|
2058
|
-
orchestrator=self.cars_orchestrator,
|
|
2059
|
-
pair_folder=os.path.join(
|
|
2060
|
-
self.dump_dir, "dense_match_filling_2", pair_key
|
|
2061
|
-
),
|
|
2062
|
-
pair_key=pair_key,
|
|
2063
|
-
)
|
|
2064
|
-
)
|
|
1807
|
+
# Fill with zeros
|
|
1808
|
+
(filled_epipolar_disparity_map) = self.dense_match_filling.run(
|
|
1809
|
+
epipolar_disparity_map,
|
|
1810
|
+
orchestrator=self.cars_orchestrator,
|
|
1811
|
+
pair_folder=os.path.join(
|
|
1812
|
+
self.dump_dir, "dense_match_filling", pair_key
|
|
1813
|
+
),
|
|
1814
|
+
pair_key=pair_key,
|
|
1815
|
+
)
|
|
2065
1816
|
|
|
2066
|
-
if self.quit_on_app("dense_match_filling
|
|
1817
|
+
if self.quit_on_app("dense_match_filling"):
|
|
2067
1818
|
continue # keep iterating over pairs, but don't go further
|
|
2068
1819
|
|
|
2069
1820
|
if isinstance(output[sens_cst.GEOID], str):
|
|
@@ -2085,7 +1836,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2085
1836
|
output_geoid_path = None
|
|
2086
1837
|
|
|
2087
1838
|
depth_map_dir = None
|
|
2088
|
-
last_depth_map_application = None
|
|
2089
1839
|
if self.save_output_depth_map:
|
|
2090
1840
|
depth_map_dir = os.path.join(
|
|
2091
1841
|
self.out_dir, "depth_map", pair_key
|
|
@@ -2099,33 +1849,9 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2099
1849
|
)
|
|
2100
1850
|
safe_makedirs(point_cloud_dir)
|
|
2101
1851
|
|
|
2102
|
-
if self.save_output_depth_map or self.save_output_point_cloud:
|
|
2103
|
-
if (
|
|
2104
|
-
self.pc_outlier_removal_2_app.used_config.get(
|
|
2105
|
-
"activated", False
|
|
2106
|
-
)
|
|
2107
|
-
is True
|
|
2108
|
-
and self.merging is False
|
|
2109
|
-
):
|
|
2110
|
-
last_depth_map_application = "pc_outlier_removal_2"
|
|
2111
|
-
elif (
|
|
2112
|
-
self.pc_outlier_removal_1_app.used_config.get(
|
|
2113
|
-
"activated", False
|
|
2114
|
-
)
|
|
2115
|
-
is True
|
|
2116
|
-
and self.merging is False
|
|
2117
|
-
):
|
|
2118
|
-
last_depth_map_application = "pc_outlier_removal_1"
|
|
2119
|
-
else:
|
|
2120
|
-
last_depth_map_application = "triangulation"
|
|
2121
|
-
|
|
2122
1852
|
triangulation_point_cloud_dir = (
|
|
2123
1853
|
point_cloud_dir
|
|
2124
|
-
if (
|
|
2125
|
-
point_cloud_dir
|
|
2126
|
-
and last_depth_map_application == "triangulation"
|
|
2127
|
-
and self.merging is False
|
|
2128
|
-
)
|
|
1854
|
+
if (point_cloud_dir and len(self.pc_outlier_removal_apps) == 0)
|
|
2129
1855
|
else None
|
|
2130
1856
|
)
|
|
2131
1857
|
|
|
@@ -2135,11 +1861,11 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2135
1861
|
self.pairs[pair_key]["sensor_image_right"],
|
|
2136
1862
|
self.pairs[pair_key]["corrected_grid_left"],
|
|
2137
1863
|
self.pairs[pair_key]["corrected_grid_right"],
|
|
2138
|
-
|
|
1864
|
+
filled_epipolar_disparity_map,
|
|
2139
1865
|
self.geom_plugin_without_dem_and_geoid,
|
|
2140
1866
|
new_epipolar_image_left,
|
|
2141
1867
|
epsg=self.epsg,
|
|
2142
|
-
denoising_overload_fun=
|
|
1868
|
+
denoising_overload_fun=None,
|
|
2143
1869
|
source_pc_names=self.pairs_names,
|
|
2144
1870
|
orchestrator=self.cars_orchestrator,
|
|
2145
1871
|
pair_dump_dir=os.path.join(
|
|
@@ -2154,8 +1880,10 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2154
1880
|
),
|
|
2155
1881
|
depth_map_dir=depth_map_dir,
|
|
2156
1882
|
point_cloud_dir=triangulation_point_cloud_dir,
|
|
2157
|
-
save_output_coordinates=
|
|
2158
|
-
|
|
1883
|
+
save_output_coordinates=(len(self.pc_outlier_removal_apps) == 0)
|
|
1884
|
+
and (
|
|
1885
|
+
self.save_output_depth_map or self.save_output_point_cloud
|
|
1886
|
+
),
|
|
2159
1887
|
save_output_color=bool(depth_map_dir)
|
|
2160
1888
|
and self.auxiliary[out_cst.AUX_TEXTURE],
|
|
2161
1889
|
save_output_classification=bool(depth_map_dir)
|
|
@@ -2173,104 +1901,49 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2173
1901
|
if self.quit_on_app("triangulation"):
|
|
2174
1902
|
continue # keep iterating over pairs, but don't go further
|
|
2175
1903
|
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
else:
|
|
2179
|
-
filtering_depth_map_dir = (
|
|
2180
|
-
depth_map_dir
|
|
2181
|
-
if (
|
|
2182
|
-
depth_map_dir
|
|
2183
|
-
and last_depth_map_application == "pc_outlier_removal_1"
|
|
2184
|
-
)
|
|
2185
|
-
else None
|
|
2186
|
-
)
|
|
2187
|
-
filtering_point_cloud_dir = (
|
|
2188
|
-
point_cloud_dir
|
|
2189
|
-
if (
|
|
2190
|
-
point_cloud_dir
|
|
2191
|
-
and last_depth_map_application == "pc_outlier_removal_1"
|
|
2192
|
-
and self.merging is False
|
|
2193
|
-
)
|
|
2194
|
-
else None
|
|
2195
|
-
)
|
|
1904
|
+
filtered_epipolar_point_cloud = epipolar_point_cloud
|
|
1905
|
+
for app_key, app in self.pc_outlier_removal_apps.items():
|
|
2196
1906
|
|
|
2197
|
-
|
|
2198
|
-
self.
|
|
2199
|
-
epipolar_point_cloud,
|
|
2200
|
-
depth_map_dir=filtering_depth_map_dir,
|
|
2201
|
-
point_cloud_dir=filtering_point_cloud_dir,
|
|
2202
|
-
dump_dir=os.path.join(
|
|
2203
|
-
self.dump_dir, "pc_outlier_removal_1", pair_key
|
|
2204
|
-
),
|
|
2205
|
-
epsg=self.epsg,
|
|
2206
|
-
orchestrator=self.cars_orchestrator,
|
|
2207
|
-
)
|
|
1907
|
+
app_key_is_last = (
|
|
1908
|
+
app_key == list(self.pc_outlier_removal_apps)[-1]
|
|
2208
1909
|
)
|
|
2209
|
-
if self.quit_on_app("point_cloud_outlier_removal.1"):
|
|
2210
|
-
continue # keep iterating over pairs, but don't go further
|
|
2211
1910
|
filtering_depth_map_dir = (
|
|
2212
|
-
depth_map_dir
|
|
2213
|
-
if (
|
|
2214
|
-
depth_map_dir
|
|
2215
|
-
and last_depth_map_application == "pc_outlier_removal_2"
|
|
2216
|
-
)
|
|
2217
|
-
else None
|
|
1911
|
+
depth_map_dir if app_key_is_last else None
|
|
2218
1912
|
)
|
|
2219
1913
|
filtering_point_cloud_dir = (
|
|
2220
|
-
point_cloud_dir
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
point_cloud_dir=filtering_point_cloud_dir,
|
|
2233
|
-
dump_dir=os.path.join(
|
|
2234
|
-
self.dump_dir, "pc_outlier_removal_2", pair_key
|
|
1914
|
+
point_cloud_dir if app_key_is_last else None
|
|
1915
|
+
)
|
|
1916
|
+
|
|
1917
|
+
filtered_epipolar_point_cloud = app.run(
|
|
1918
|
+
filtered_epipolar_point_cloud,
|
|
1919
|
+
depth_map_dir=filtering_depth_map_dir,
|
|
1920
|
+
point_cloud_dir=filtering_point_cloud_dir,
|
|
1921
|
+
dump_dir=os.path.join(
|
|
1922
|
+
self.dump_dir,
|
|
1923
|
+
( # pylint: disable=inconsistent-quotes
|
|
1924
|
+
f"pc_outlier_removal"
|
|
1925
|
+
f"{str(app_key[27:]).replace('.', '_')}"
|
|
2235
1926
|
),
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
1927
|
+
pair_key,
|
|
1928
|
+
),
|
|
1929
|
+
epsg=self.epsg,
|
|
1930
|
+
orchestrator=self.cars_orchestrator,
|
|
2239
1931
|
)
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
# denoising available only if we'll go further in the pipeline
|
|
2244
|
-
if self.save_output_dsm or self.save_output_point_cloud:
|
|
2245
|
-
denoised_epipolar_point_clouds = (
|
|
2246
|
-
self.pc_denoising_application.run(
|
|
2247
|
-
filtered_epipolar_point_cloud_2,
|
|
2248
|
-
orchestrator=self.cars_orchestrator,
|
|
2249
|
-
pair_folder=os.path.join(
|
|
2250
|
-
self.dump_dir, "denoising", pair_key
|
|
2251
|
-
),
|
|
2252
|
-
pair_key=pair_key,
|
|
2253
|
-
)
|
|
2254
|
-
)
|
|
2255
|
-
|
|
2256
|
-
self.list_epipolar_point_clouds.append(
|
|
2257
|
-
denoised_epipolar_point_clouds
|
|
2258
|
-
)
|
|
1932
|
+
if self.quit_on_app("point_cloud_outlier_removal"):
|
|
1933
|
+
continue # keep iterating over pairs, but don't go further
|
|
2259
1934
|
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
1935
|
+
self.list_epipolar_point_clouds.append(
|
|
1936
|
+
filtered_epipolar_point_cloud
|
|
1937
|
+
)
|
|
2263
1938
|
|
|
2264
1939
|
# quit if any app in the loop over the pairs was the last one
|
|
2265
1940
|
# pylint:disable=too-many-boolean-expressions
|
|
2266
1941
|
if (
|
|
2267
1942
|
self.quit_on_app("dense_matching")
|
|
2268
|
-
or self.quit_on_app("dense_match_filling
|
|
2269
|
-
or self.quit_on_app("dense_match_filling.2")
|
|
1943
|
+
or self.quit_on_app("dense_match_filling")
|
|
2270
1944
|
or self.quit_on_app("triangulation")
|
|
2271
1945
|
or self.quit_on_app("point_cloud_outlier_removal.1")
|
|
2272
1946
|
or self.quit_on_app("point_cloud_outlier_removal.2")
|
|
2273
|
-
or self.quit_on_app("pc_denoising")
|
|
2274
1947
|
):
|
|
2275
1948
|
return True
|
|
2276
1949
|
|
|
@@ -2512,17 +2185,56 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2512
2185
|
cars_orchestrator=self.cars_orchestrator,
|
|
2513
2186
|
)
|
|
2514
2187
|
|
|
2188
|
+
# Update refined conf configuration with dem paths
|
|
2515
2189
|
dem_median = paths["dem_median"]
|
|
2516
2190
|
dem_min = paths["dem_min"]
|
|
2517
2191
|
dem_max = paths["dem_max"]
|
|
2518
2192
|
|
|
2519
2193
|
advanced_parameters.update_conf(
|
|
2520
|
-
self.
|
|
2194
|
+
self.refined_conf,
|
|
2521
2195
|
dem_median=dem_median,
|
|
2522
2196
|
dem_min=dem_min,
|
|
2523
2197
|
dem_max=dem_max,
|
|
2524
2198
|
)
|
|
2525
2199
|
|
|
2200
|
+
if self.used_conf[ADVANCED][USE_ENDOGENOUS_DEM]:
|
|
2201
|
+
# Generate new geom plugin with dem
|
|
2202
|
+
output_dem_dir = os.path.join(
|
|
2203
|
+
self.dump_dir, "initial_elevation"
|
|
2204
|
+
)
|
|
2205
|
+
new_geom_plugin = (
|
|
2206
|
+
sensor_inputs.generate_geometry_plugin_with_dem(
|
|
2207
|
+
self.geometry_plugin,
|
|
2208
|
+
self.used_conf[INPUTS],
|
|
2209
|
+
dem=dem_median,
|
|
2210
|
+
output_dem_dir=output_dem_dir,
|
|
2211
|
+
)
|
|
2212
|
+
)
|
|
2213
|
+
|
|
2214
|
+
for (
|
|
2215
|
+
pair_key,
|
|
2216
|
+
_,
|
|
2217
|
+
_,
|
|
2218
|
+
) in self.list_sensor_pairs:
|
|
2219
|
+
new_grid_correction_coef = (
|
|
2220
|
+
self.generate_grid_correction_on_dem(
|
|
2221
|
+
pair_key,
|
|
2222
|
+
new_geom_plugin,
|
|
2223
|
+
)
|
|
2224
|
+
)
|
|
2225
|
+
if new_grid_correction_coef is not None:
|
|
2226
|
+
# Update refined_conf configuration with epipolar
|
|
2227
|
+
# a priori
|
|
2228
|
+
advanced_parameters.update_conf(
|
|
2229
|
+
self.refined_conf,
|
|
2230
|
+
grid_correction_coef=new_grid_correction_coef,
|
|
2231
|
+
pair_key=pair_key,
|
|
2232
|
+
reference_dem=dem_median,
|
|
2233
|
+
)
|
|
2234
|
+
|
|
2235
|
+
# saved used configuration
|
|
2236
|
+
self.save_configurations()
|
|
2237
|
+
|
|
2526
2238
|
return False
|
|
2527
2239
|
|
|
2528
2240
|
def filling(self): # noqa: C901 : too complex
|
|
@@ -2530,10 +2242,6 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2530
2242
|
Fill the dsm
|
|
2531
2243
|
"""
|
|
2532
2244
|
|
|
2533
|
-
dsm_filling_1_dump_dir = os.path.join(self.dump_dir, "dsm_filling_1")
|
|
2534
|
-
dsm_filling_2_dump_dir = os.path.join(self.dump_dir, "dsm_filling_2")
|
|
2535
|
-
dsm_filling_3_dump_dir = os.path.join(self.dump_dir, "dsm_filling_3")
|
|
2536
|
-
|
|
2537
2245
|
dsm_file_name = (
|
|
2538
2246
|
os.path.join(
|
|
2539
2247
|
self.out_dir,
|
|
@@ -2778,38 +2486,47 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2778
2486
|
else:
|
|
2779
2487
|
self.list_intersection_poly = None
|
|
2780
2488
|
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2489
|
+
dtm_file_name = None
|
|
2490
|
+
for app_key, app in self.dsm_filling_apps.items():
|
|
2491
|
+
|
|
2492
|
+
app_dump_dir = os.path.join(
|
|
2493
|
+
self.dump_dir, app_key.replace(".", "_")
|
|
2494
|
+
)
|
|
2495
|
+
|
|
2496
|
+
if app.get_conf()["method"] == "exogenous_filling":
|
|
2497
|
+
_ = app.run(
|
|
2498
|
+
dsm_file=dsm_file_name,
|
|
2499
|
+
classif_file=classif_file_name,
|
|
2500
|
+
filling_file=filling_file_name,
|
|
2501
|
+
dump_dir=app_dump_dir,
|
|
2502
|
+
roi_polys=self.list_intersection_poly,
|
|
2503
|
+
roi_epsg=self.epsg,
|
|
2504
|
+
output_geoid=self.used_conf[OUTPUT][sens_cst.GEOID],
|
|
2505
|
+
geom_plugin=self.geom_plugin_with_dem_and_geoid,
|
|
2506
|
+
)
|
|
2507
|
+
elif app.get_conf()["method"] == "bulldozer":
|
|
2508
|
+
dtm_file_name = app.run(
|
|
2509
|
+
dsm_file=dsm_file_name,
|
|
2510
|
+
classif_file=classif_file_name,
|
|
2511
|
+
filling_file=filling_file_name,
|
|
2512
|
+
dump_dir=app_dump_dir,
|
|
2513
|
+
roi_polys=self.list_intersection_poly,
|
|
2514
|
+
roi_epsg=self.epsg,
|
|
2515
|
+
orchestrator=self.cars_orchestrator,
|
|
2516
|
+
)
|
|
2517
|
+
elif app.get_conf()["method"] == "border_interpolation":
|
|
2518
|
+
_ = app.run(
|
|
2519
|
+
dsm_file=dsm_file_name,
|
|
2520
|
+
classif_file=classif_file_name,
|
|
2521
|
+
filling_file=filling_file_name,
|
|
2522
|
+
dtm_file=dtm_file_name,
|
|
2523
|
+
dump_dir=app_dump_dir,
|
|
2524
|
+
roi_polys=self.list_intersection_poly,
|
|
2525
|
+
roi_epsg=self.epsg,
|
|
2526
|
+
)
|
|
2810
2527
|
|
|
2811
|
-
|
|
2812
|
-
|
|
2528
|
+
if not app.save_intermediate_data:
|
|
2529
|
+
self.cars_orchestrator.add_to_clean(app_dump_dir)
|
|
2813
2530
|
|
|
2814
2531
|
_ = self.auxiliary_filling_application.run(
|
|
2815
2532
|
dsm_file=dsm_file_name,
|
|
@@ -2820,203 +2537,31 @@ class UnitPipeline(PipelineTemplate):
|
|
|
2820
2537
|
pairing=self.used_conf[INPUTS].get("pairing"),
|
|
2821
2538
|
geom_plugin=self.geom_plugin_with_dem_and_geoid,
|
|
2822
2539
|
texture_bands=self.texture_bands,
|
|
2540
|
+
output_geoid=self.used_conf[OUTPUT][sens_cst.GEOID],
|
|
2823
2541
|
orchestrator=self.cars_orchestrator,
|
|
2824
2542
|
)
|
|
2825
|
-
|
|
2826
|
-
if self.quit_on_app("auxiliary_filling"):
|
|
2827
|
-
return True
|
|
2828
|
-
|
|
2829
2543
|
self.cars_orchestrator.breakpoint()
|
|
2830
2544
|
|
|
2831
|
-
|
|
2832
|
-
dsm_file=dsm_file_name,
|
|
2833
|
-
classif_file=classif_file_name,
|
|
2834
|
-
filling_file=filling_file_name,
|
|
2835
|
-
dtm_file=dtm_file_name,
|
|
2836
|
-
dump_dir=dsm_filling_3_dump_dir,
|
|
2837
|
-
roi_polys=self.list_intersection_poly,
|
|
2838
|
-
roi_epsg=self.epsg,
|
|
2839
|
-
)
|
|
2840
|
-
|
|
2841
|
-
if not self.dsm_filling_3_application.save_intermediate_data:
|
|
2842
|
-
self.cars_orchestrator.add_to_clean(dsm_filling_3_dump_dir)
|
|
2843
|
-
|
|
2844
|
-
return self.quit_on_app("dsm_filling.3")
|
|
2545
|
+
return self.quit_on_app("auxiliary_filling")
|
|
2845
2546
|
|
|
2547
|
+
@cars_profile(name="Preprocess depth maps", interval=0.5)
|
|
2846
2548
|
def preprocess_depth_maps(self):
|
|
2847
2549
|
"""
|
|
2848
2550
|
Adds multiple processing steps to the depth maps :
|
|
2849
|
-
Merging
|
|
2551
|
+
Merging.
|
|
2850
2552
|
Creates the point cloud that will be rasterized in
|
|
2851
2553
|
the last step of the pipeline.
|
|
2852
2554
|
"""
|
|
2853
2555
|
|
|
2854
|
-
|
|
2855
|
-
self.
|
|
2856
|
-
|
|
2857
|
-
self.terrain_bounds,
|
|
2858
|
-
)
|
|
2859
|
-
self.color_type = self.point_cloud_to_rasterize[0][
|
|
2860
|
-
0
|
|
2861
|
-
].attributes.get("color_type", None)
|
|
2862
|
-
else:
|
|
2863
|
-
# find which application produce the final version of the
|
|
2864
|
-
# point cloud. The last generated point cloud will be saved
|
|
2865
|
-
# as official point cloud product if save_output_point_cloud
|
|
2866
|
-
# is True.
|
|
2867
|
-
|
|
2868
|
-
last_pc_application = None
|
|
2869
|
-
# denoising application will produce a point cloud, unless
|
|
2870
|
-
# it uses the 'none' method.
|
|
2871
|
-
if self.pc_denoising_application.used_method != "none":
|
|
2872
|
-
last_pc_application = "denoising"
|
|
2873
|
-
else:
|
|
2874
|
-
last_pc_application = "fusion"
|
|
2875
|
-
|
|
2876
|
-
raster_app_margin = 0
|
|
2877
|
-
if self.rasterization_application is not None:
|
|
2878
|
-
raster_app_margin = self.rasterization_application.get_margins(
|
|
2879
|
-
self.resolution
|
|
2880
|
-
)
|
|
2881
|
-
|
|
2882
|
-
merged_point_clouds = self.pc_fusion_application.run(
|
|
2883
|
-
self.list_epipolar_point_clouds,
|
|
2884
|
-
self.terrain_bounds,
|
|
2885
|
-
self.epsg,
|
|
2886
|
-
source_pc_names=(
|
|
2887
|
-
self.pairs_names if self.compute_depth_map else None
|
|
2888
|
-
),
|
|
2889
|
-
orchestrator=self.cars_orchestrator,
|
|
2890
|
-
margins=raster_app_margin,
|
|
2891
|
-
optimal_terrain_tile_width=self.optimal_terrain_tile_width,
|
|
2892
|
-
roi=(self.roi_poly if self.debug_with_roi else None),
|
|
2893
|
-
save_laz_output=self.save_output_point_cloud
|
|
2894
|
-
and last_pc_application == "fusion",
|
|
2895
|
-
)
|
|
2896
|
-
|
|
2897
|
-
if self.quit_on_app("point_cloud_fusion"):
|
|
2898
|
-
return True
|
|
2899
|
-
|
|
2900
|
-
# denoise point cloud
|
|
2901
|
-
denoised_merged_point_clouds = self.pc_denoising_application.run(
|
|
2902
|
-
merged_point_clouds,
|
|
2903
|
-
orchestrator=self.cars_orchestrator,
|
|
2904
|
-
save_laz_output=self.save_output_point_cloud
|
|
2905
|
-
and last_pc_application == "denoising",
|
|
2906
|
-
)
|
|
2907
|
-
|
|
2908
|
-
if self.quit_on_app("pc_denoising"):
|
|
2909
|
-
return True
|
|
2910
|
-
|
|
2911
|
-
# Rasterize merged and filtered point cloud
|
|
2912
|
-
self.point_cloud_to_rasterize = denoised_merged_point_clouds
|
|
2913
|
-
|
|
2914
|
-
# try getting the color type from multiple sources
|
|
2915
|
-
self.color_type = self.list_epipolar_point_clouds[0].attributes.get(
|
|
2916
|
-
"color_type",
|
|
2917
|
-
self.point_cloud_to_rasterize.attributes.get(
|
|
2918
|
-
"color_type", None
|
|
2919
|
-
),
|
|
2920
|
-
)
|
|
2921
|
-
|
|
2922
|
-
return False
|
|
2923
|
-
|
|
2924
|
-
def load_input_depth_maps(self):
|
|
2925
|
-
"""
|
|
2926
|
-
Loads all the data and creates all the variables used
|
|
2927
|
-
later when processing a depth map, as if it was just computed.
|
|
2928
|
-
"""
|
|
2929
|
-
# get epsg
|
|
2930
|
-
self.epsg = self.used_conf[OUTPUT][out_cst.EPSG]
|
|
2931
|
-
|
|
2932
|
-
output_parameters.intialize_product_index(
|
|
2933
|
-
self.cars_orchestrator,
|
|
2934
|
-
self.used_conf[OUTPUT]["product_level"],
|
|
2935
|
-
self.used_conf[INPUTS][depth_cst.DEPTH_MAPS].keys(),
|
|
2936
|
-
)
|
|
2937
|
-
|
|
2938
|
-
# compute epsg
|
|
2939
|
-
epsg_cloud = pc_fusion_wrappers.compute_epsg_from_point_cloud(
|
|
2940
|
-
self.used_conf[INPUTS][depth_cst.DEPTH_MAPS]
|
|
2556
|
+
self.point_cloud_to_rasterize = (
|
|
2557
|
+
self.list_epipolar_point_clouds,
|
|
2558
|
+
self.terrain_bounds,
|
|
2941
2559
|
)
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
self.vertical_crs = projection.get_output_crs(
|
|
2946
|
-
self.epsg, self.used_conf[OUTPUT]
|
|
2560
|
+
self.color_type = self.point_cloud_to_rasterize[0][0].attributes.get(
|
|
2561
|
+
"color_type", None
|
|
2947
2562
|
)
|
|
2948
2563
|
|
|
2949
|
-
|
|
2950
|
-
self.used_conf[OUTPUT][out_cst.RESOLUTION] * self.res_resamp
|
|
2951
|
-
)
|
|
2952
|
-
|
|
2953
|
-
# Compute roi polygon, in input EPSG
|
|
2954
|
-
self.roi_poly = preprocessing.compute_roi_poly(
|
|
2955
|
-
self.input_roi_poly, self.input_roi_epsg, self.epsg
|
|
2956
|
-
)
|
|
2957
|
-
|
|
2958
|
-
if not self.merging:
|
|
2959
|
-
# compute bounds
|
|
2960
|
-
self.terrain_bounds = pc_fusion_wrappers.get_bounds(
|
|
2961
|
-
self.used_conf[INPUTS][depth_cst.DEPTH_MAPS],
|
|
2962
|
-
self.epsg,
|
|
2963
|
-
roi_poly=self.roi_poly,
|
|
2964
|
-
)
|
|
2965
|
-
|
|
2966
|
-
self.list_epipolar_point_clouds = (
|
|
2967
|
-
pc_fusion_algo.generate_point_clouds(
|
|
2968
|
-
self.used_conf[INPUTS][depth_cst.DEPTH_MAPS],
|
|
2969
|
-
self.cars_orchestrator,
|
|
2970
|
-
tile_size=1000,
|
|
2971
|
-
)
|
|
2972
|
-
)
|
|
2973
|
-
else:
|
|
2974
|
-
# Compute terrain bounds and transform point clouds
|
|
2975
|
-
(
|
|
2976
|
-
self.terrain_bounds,
|
|
2977
|
-
self.list_epipolar_point_clouds,
|
|
2978
|
-
) = pc_fusion_algo.transform_input_pc(
|
|
2979
|
-
self.used_conf[INPUTS][depth_cst.DEPTH_MAPS],
|
|
2980
|
-
self.epsg,
|
|
2981
|
-
roi_poly=self.roi_poly,
|
|
2982
|
-
epipolar_tile_size=1000, # TODO change it
|
|
2983
|
-
orchestrator=self.cars_orchestrator,
|
|
2984
|
-
)
|
|
2985
|
-
|
|
2986
|
-
# Compute number of superposing point cloud for density
|
|
2987
|
-
max_number_superposing_point_clouds = (
|
|
2988
|
-
pc_fusion_wrappers.compute_max_nb_point_clouds(
|
|
2989
|
-
self.list_epipolar_point_clouds
|
|
2990
|
-
)
|
|
2991
|
-
)
|
|
2992
|
-
|
|
2993
|
-
# Compute average distance between two points
|
|
2994
|
-
average_distance_point_cloud = (
|
|
2995
|
-
pc_fusion_wrappers.compute_average_distance(
|
|
2996
|
-
self.list_epipolar_point_clouds
|
|
2997
|
-
)
|
|
2998
|
-
)
|
|
2999
|
-
self.optimal_terrain_tile_width = (
|
|
3000
|
-
self.rasterization_application.get_optimal_tile_size(
|
|
3001
|
-
self.cars_orchestrator.cluster.checked_conf_cluster[
|
|
3002
|
-
"max_ram_per_worker"
|
|
3003
|
-
],
|
|
3004
|
-
superposing_point_clouds=(
|
|
3005
|
-
max_number_superposing_point_clouds
|
|
3006
|
-
),
|
|
3007
|
-
point_cloud_resolution=average_distance_point_cloud,
|
|
3008
|
-
)
|
|
3009
|
-
)
|
|
3010
|
-
# epsg_cloud and optimal_terrain_tile_width have the same epsg
|
|
3011
|
-
self.optimal_terrain_tile_width = (
|
|
3012
|
-
preprocessing.convert_optimal_tile_size_with_epsg(
|
|
3013
|
-
self.terrain_bounds,
|
|
3014
|
-
self.optimal_terrain_tile_width,
|
|
3015
|
-
self.epsg,
|
|
3016
|
-
epsg_cloud,
|
|
3017
|
-
)
|
|
3018
|
-
)
|
|
3019
|
-
|
|
2564
|
+
@cars_profile(name="Final cleanup", interval=0.5)
|
|
3020
2565
|
def final_cleanup(self):
|
|
3021
2566
|
"""
|
|
3022
2567
|
Clean temporary files and directory at the end of cars processing
|
|
@@ -3034,28 +2579,30 @@ class UnitPipeline(PipelineTemplate):
|
|
|
3034
2579
|
not any(
|
|
3035
2580
|
app.get("save_intermediate_data", False) is True
|
|
3036
2581
|
for app in self.used_conf[APPLICATIONS].values()
|
|
2582
|
+
if app is not None
|
|
3037
2583
|
)
|
|
3038
2584
|
and not self.dsms_in_inputs
|
|
3039
2585
|
):
|
|
3040
2586
|
self.cars_orchestrator.add_to_clean(self.dump_dir)
|
|
3041
2587
|
|
|
3042
|
-
@cars_profile(name="
|
|
3043
|
-
def run(
|
|
2588
|
+
@cars_profile(name="run_unit_pipeline", interval=0.5)
|
|
2589
|
+
def run( # pylint: disable=too-many-positional-arguments
|
|
3044
2590
|
self,
|
|
3045
|
-
orchestrator_conf=None,
|
|
3046
2591
|
generate_dems=False,
|
|
3047
2592
|
which_resolution="single",
|
|
3048
2593
|
use_sift_a_priori=False,
|
|
3049
2594
|
first_res_out_dir=None,
|
|
3050
|
-
|
|
2595
|
+
log_dir=None,
|
|
3051
2596
|
): # noqa C901
|
|
3052
2597
|
"""
|
|
3053
2598
|
Run pipeline
|
|
3054
2599
|
|
|
3055
2600
|
"""
|
|
2601
|
+
if log_dir is not None:
|
|
2602
|
+
self.log_dir = log_dir
|
|
2603
|
+
else:
|
|
2604
|
+
self.log_dir = os.path.join(self.out_dir, "logs")
|
|
3056
2605
|
|
|
3057
|
-
self.out_dir = self.used_conf[OUTPUT][out_cst.OUT_DIRECTORY]
|
|
3058
|
-
self.dump_dir = os.path.join(self.out_dir, "dump_dir")
|
|
3059
2606
|
self.first_res_out_dir = first_res_out_dir
|
|
3060
2607
|
self.texture_bands = self.used_conf[ADVANCED][adv_cst.TEXTURE_BANDS]
|
|
3061
2608
|
|
|
@@ -3067,65 +2614,29 @@ class UnitPipeline(PipelineTemplate):
|
|
|
3067
2614
|
|
|
3068
2615
|
self.which_resolution = which_resolution
|
|
3069
2616
|
|
|
3070
|
-
#
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
)
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
safe_save=True,
|
|
3085
|
-
)
|
|
3086
|
-
|
|
3087
|
-
if orchestrator_conf is None:
|
|
3088
|
-
# start cars orchestrator
|
|
3089
|
-
with orchestrator.Orchestrator(
|
|
3090
|
-
orchestrator_conf=self.used_conf[ORCHESTRATOR],
|
|
3091
|
-
out_dir=self.out_dir,
|
|
3092
|
-
out_json_path=os.path.join(
|
|
3093
|
-
self.out_dir,
|
|
3094
|
-
out_cst.INFO_FILENAME,
|
|
3095
|
-
),
|
|
3096
|
-
) as self.cars_orchestrator:
|
|
3097
|
-
# initialize out_json
|
|
3098
|
-
self.cars_orchestrator.update_out_info({"version": __version__})
|
|
3099
|
-
|
|
3100
|
-
if not self.dsms_in_inputs:
|
|
3101
|
-
if self.compute_depth_map:
|
|
3102
|
-
self.sensor_to_depth_maps()
|
|
3103
|
-
else:
|
|
3104
|
-
self.load_input_depth_maps()
|
|
3105
|
-
|
|
3106
|
-
if self.save_output_dsm or self.save_output_point_cloud:
|
|
3107
|
-
end_pipeline = self.preprocess_depth_maps()
|
|
3108
|
-
|
|
3109
|
-
if self.save_output_dsm and not end_pipeline:
|
|
3110
|
-
self.rasterize_point_cloud()
|
|
3111
|
-
self.filling()
|
|
3112
|
-
else:
|
|
3113
|
-
self.filling()
|
|
3114
|
-
|
|
3115
|
-
self.final_cleanup()
|
|
3116
|
-
else:
|
|
3117
|
-
self.cars_orchestrator = orchestrator_conf
|
|
2617
|
+
# saved used configuration
|
|
2618
|
+
self.save_configurations()
|
|
2619
|
+
# start cars orchestrator
|
|
2620
|
+
with orchestrator.Orchestrator(
|
|
2621
|
+
orchestrator_conf=self.used_conf[ORCHESTRATOR],
|
|
2622
|
+
out_dir=self.out_dir,
|
|
2623
|
+
log_dir=self.log_dir,
|
|
2624
|
+
out_json_path=os.path.join(
|
|
2625
|
+
self.out_dir,
|
|
2626
|
+
out_cst.INFO_FILENAME,
|
|
2627
|
+
),
|
|
2628
|
+
) as self.cars_orchestrator:
|
|
2629
|
+
# initialize out_json
|
|
2630
|
+
self.cars_orchestrator.update_out_info({"version": __version__})
|
|
3118
2631
|
|
|
3119
2632
|
if not self.dsms_in_inputs:
|
|
3120
2633
|
if self.compute_depth_map:
|
|
3121
2634
|
self.sensor_to_depth_maps()
|
|
3122
|
-
else:
|
|
3123
|
-
self.load_input_depth_maps()
|
|
3124
2635
|
|
|
3125
2636
|
if self.save_output_dsm or self.save_output_point_cloud:
|
|
3126
|
-
|
|
2637
|
+
self.preprocess_depth_maps()
|
|
3127
2638
|
|
|
3128
|
-
if self.save_output_dsm
|
|
2639
|
+
if self.save_output_dsm:
|
|
3129
2640
|
self.rasterize_point_cloud()
|
|
3130
2641
|
self.filling()
|
|
3131
2642
|
else:
|