cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a4__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cars might be problematic. Click here for more details.
- cars/__init__.py +3 -3
- cars/applications/__init__.py +0 -3
- cars/applications/application.py +14 -6
- cars/applications/application_template.py +42 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
- cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
- cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
- cars/applications/dem_generation/rasterization_app.py +112 -43
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +48 -14
- cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
- cars/applications/dense_matching/disparity_grid_algo.py +95 -79
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
- cars/applications/dsm_filling/border_interpolation_app.py +11 -12
- cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
- cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
- cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
- cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +88 -116
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +60 -53
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +5 -25
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +364 -22
- cars/core/geometry/shareloc_geometry.py +112 -82
- cars/core/inputs.py +72 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +126 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +12 -10
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +149 -22
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +15 -4
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +461 -1052
- cars/pipelines/parameters/advanced_parameters.py +91 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +122 -73
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +676 -1070
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
- cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
- cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
- cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
- cars/applications/dense_match_filling/cpp/__init__.py +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
- cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
- cars/applications/dense_match_filling/cpp/meson.build +0 -9
- cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
- cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
- cars/applications/dense_match_filling/plane_app.py +0 -556
- cars/applications/hole_detection/__init__.py +0 -30
- cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
- cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
- cars/applications/hole_detection/hole_detection_algo.py +0 -144
- cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
- cars/applications/point_cloud_denoising/__init__.py +0 -29
- cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
- cars/applications/point_cloud_fusion/__init__.py +0 -30
- cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
- cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
- cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
- cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
- cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -31,6 +31,8 @@ from typing import Dict
|
|
|
31
31
|
|
|
32
32
|
import numpy as np
|
|
33
33
|
import pandora
|
|
34
|
+
import rasterio
|
|
35
|
+
import xarray as xr
|
|
34
36
|
from json_checker import Checker, Or
|
|
35
37
|
from pandora.check_configuration import (
|
|
36
38
|
check_pipeline_section,
|
|
@@ -38,8 +40,12 @@ from pandora.check_configuration import (
|
|
|
38
40
|
get_config_pipeline,
|
|
39
41
|
update_conf,
|
|
40
42
|
)
|
|
41
|
-
from pandora.img_tools import get_metadata
|
|
42
43
|
from pandora.state_machine import PandoraMachine
|
|
44
|
+
from rasterio.mask import mask
|
|
45
|
+
from shapely.geometry import mapping
|
|
46
|
+
|
|
47
|
+
from cars.core.projection import polygon_projection
|
|
48
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
43
49
|
|
|
44
50
|
|
|
45
51
|
class PandoraLoader:
|
|
@@ -48,7 +54,7 @@ class PandoraLoader:
|
|
|
48
54
|
|
|
49
55
|
"""
|
|
50
56
|
|
|
51
|
-
def __init__( # noqa: C901
|
|
57
|
+
def __init__( # pylint: disable=too-many-positional-arguments # noqa: C901
|
|
52
58
|
self,
|
|
53
59
|
conf=None,
|
|
54
60
|
method_name=None,
|
|
@@ -135,7 +141,7 @@ class PandoraLoader:
|
|
|
135
141
|
# read conf
|
|
136
142
|
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
137
143
|
conf = json.load(fstream)
|
|
138
|
-
elif method_name
|
|
144
|
+
elif method_name in ("census_sgm_default", "auto"):
|
|
139
145
|
# Use census sgm conf
|
|
140
146
|
conf_file_path = os.path.join(
|
|
141
147
|
package_path, "config_census_sgm_default.json"
|
|
@@ -266,26 +272,6 @@ class PandoraLoader:
|
|
|
266
272
|
if "band" not in filter_conf:
|
|
267
273
|
conf["pipeline"]["filter"]["band"] = used_band
|
|
268
274
|
|
|
269
|
-
for key in list(conf.get("pipeline")):
|
|
270
|
-
if key.startswith("filter"):
|
|
271
|
-
if (
|
|
272
|
-
conf["pipeline"][key]["filter_method"]
|
|
273
|
-
== "median_for_intervals"
|
|
274
|
-
and "validation" in conf["pipeline"]
|
|
275
|
-
):
|
|
276
|
-
if (
|
|
277
|
-
conf["pipeline"]["validation"]["validation_method"]
|
|
278
|
-
== "cross_checking_fast"
|
|
279
|
-
):
|
|
280
|
-
conf["pipeline"]["validation"][
|
|
281
|
-
"validation_method"
|
|
282
|
-
] = "cross_checking_accurate"
|
|
283
|
-
logging.warning(
|
|
284
|
-
"You can not use median_for_intervals with "
|
|
285
|
-
"the fast cross checking validation for now. "
|
|
286
|
-
"It therefore has been overrided to accurate"
|
|
287
|
-
)
|
|
288
|
-
|
|
289
275
|
# Check conf
|
|
290
276
|
self.pandora_config = conf
|
|
291
277
|
|
|
@@ -300,15 +286,116 @@ class PandoraLoader:
|
|
|
300
286
|
|
|
301
287
|
return self.pandora_config
|
|
302
288
|
|
|
303
|
-
def
|
|
289
|
+
def get_classif_bands(self):
|
|
290
|
+
"""
|
|
291
|
+
Get the classification bands used in the pandora configuration
|
|
292
|
+
|
|
293
|
+
:return: list of classification bands
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
classif_bands = []
|
|
297
|
+
|
|
298
|
+
def search_classes_recursive(obj):
|
|
299
|
+
"""
|
|
300
|
+
Recursive search of keys containing 'classes' in the configuration
|
|
301
|
+
"""
|
|
302
|
+
if isinstance(obj, dict):
|
|
303
|
+
for key, value in obj.items():
|
|
304
|
+
if "classes" in key.lower():
|
|
305
|
+
if isinstance(value, list):
|
|
306
|
+
classif_bands.extend(value)
|
|
307
|
+
elif value is not None:
|
|
308
|
+
classif_bands.append(value)
|
|
309
|
+
# Continue recursive search
|
|
310
|
+
search_classes_recursive(value)
|
|
311
|
+
|
|
312
|
+
search_classes_recursive(self.pandora_config)
|
|
313
|
+
|
|
314
|
+
# Remove duplicates and return the list
|
|
315
|
+
return list(set(classif_bands))
|
|
316
|
+
|
|
317
|
+
@cars_profile(name="Find auto conf")
|
|
318
|
+
def find_auto_conf(
|
|
319
|
+
self, intersection_poly, land_cover_map, classif_to_config_mapping, epsg
|
|
320
|
+
):
|
|
321
|
+
"""
|
|
322
|
+
Find the configuration that suits the most on the
|
|
323
|
+
land cover map based on the roi
|
|
324
|
+
"""
|
|
325
|
+
package_path = os.path.dirname(__file__)
|
|
326
|
+
|
|
327
|
+
# construct the path to the land_cover_map
|
|
328
|
+
if os.path.dirname(land_cover_map) == "":
|
|
329
|
+
land_cover_map_path = os.path.join(package_path, land_cover_map)
|
|
330
|
+
else:
|
|
331
|
+
land_cover_map_path = land_cover_map
|
|
332
|
+
|
|
333
|
+
with rasterio.open(land_cover_map_path) as src:
|
|
334
|
+
# Project the polygon to the right epsg
|
|
335
|
+
if src.crs != epsg:
|
|
336
|
+
poly = polygon_projection(
|
|
337
|
+
intersection_poly, epsg, src.crs.to_epsg()
|
|
338
|
+
)
|
|
339
|
+
else:
|
|
340
|
+
poly = intersection_poly
|
|
341
|
+
|
|
342
|
+
# Use a buffer because the land_cover_map resolution is coarse
|
|
343
|
+
data_land_cover, _ = mask(
|
|
344
|
+
src, [mapping(poly)], crop=True, all_touched=True
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Find the most common class in the roi
|
|
348
|
+
data_squeeze = data_land_cover.squeeze()
|
|
349
|
+
valid_data = data_squeeze[data_squeeze != src.nodata]
|
|
350
|
+
|
|
351
|
+
most_common_class = None
|
|
352
|
+
if valid_data.size > 0:
|
|
353
|
+
classes, counts = np.unique(valid_data, return_counts=True)
|
|
354
|
+
max_index = np.argmax(counts)
|
|
355
|
+
most_common_class = classes[max_index]
|
|
356
|
+
|
|
357
|
+
# Construct the path to the classification to configuration mapping
|
|
358
|
+
if os.path.dirname(classif_to_config_mapping) == "":
|
|
359
|
+
conf_file_path = os.path.join(
|
|
360
|
+
package_path, classif_to_config_mapping
|
|
361
|
+
)
|
|
362
|
+
else:
|
|
363
|
+
conf_file_path = classif_to_config_mapping
|
|
364
|
+
|
|
365
|
+
# read conf
|
|
366
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
367
|
+
conf_mapping = json.load(fstream)
|
|
368
|
+
|
|
369
|
+
# Find the configuration that corresponds to the most common class
|
|
370
|
+
corresponding_conf_name = conf_mapping.get(str(most_common_class), None)
|
|
371
|
+
|
|
372
|
+
# If no equivalence has been found, we use the default configuration
|
|
373
|
+
if corresponding_conf_name is None:
|
|
374
|
+
corresponding_conf_name = "census_sgm_default"
|
|
375
|
+
|
|
376
|
+
logging.info(
|
|
377
|
+
"The conf that has been chosen regarding the "
|
|
378
|
+
"world classification map is {}".format(corresponding_conf_name)
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
# We return the corresponding configuration
|
|
382
|
+
json_conf_name = os.path.join(
|
|
383
|
+
package_path, "config_" + corresponding_conf_name + ".json"
|
|
384
|
+
)
|
|
385
|
+
with open(json_conf_name, "r", encoding="utf8") as fstream:
|
|
386
|
+
conf = json.load(fstream)
|
|
387
|
+
|
|
388
|
+
return conf
|
|
389
|
+
|
|
390
|
+
def check_conf( # pylint: disable=too-many-positional-arguments
|
|
304
391
|
self,
|
|
305
392
|
user_cfg,
|
|
306
|
-
|
|
307
|
-
|
|
393
|
+
nodata_left,
|
|
394
|
+
nodata_right,
|
|
308
395
|
bands_left,
|
|
309
396
|
bands_right,
|
|
310
|
-
|
|
311
|
-
|
|
397
|
+
bands_classif_left=None,
|
|
398
|
+
bands_classif_right=None,
|
|
312
399
|
):
|
|
313
400
|
"""
|
|
314
401
|
Check configuration
|
|
@@ -320,15 +407,18 @@ class PandoraLoader:
|
|
|
320
407
|
:rtype: dict
|
|
321
408
|
|
|
322
409
|
"""
|
|
323
|
-
|
|
324
410
|
# Import plugins before checking configuration
|
|
325
411
|
pandora.import_plugin()
|
|
326
412
|
# Check configuration and update the configuration with default values
|
|
327
413
|
# Instantiate pandora state machine
|
|
328
414
|
pandora_machine = PandoraMachine()
|
|
329
415
|
# check pipeline
|
|
330
|
-
metadata_left =
|
|
331
|
-
|
|
416
|
+
metadata_left = overide_pandora_get_metadata(
|
|
417
|
+
bands_left, classif_bands=bands_classif_left
|
|
418
|
+
)
|
|
419
|
+
metadata_right = overide_pandora_get_metadata(
|
|
420
|
+
bands_right, classif_bands=bands_classif_right
|
|
421
|
+
)
|
|
332
422
|
|
|
333
423
|
metadata_left = metadata_left.assign_coords(band_im=bands_left)
|
|
334
424
|
metadata_right = metadata_right.assign_coords(band_im=bands_right)
|
|
@@ -345,7 +435,9 @@ class PandoraLoader:
|
|
|
345
435
|
saved_schema
|
|
346
436
|
)
|
|
347
437
|
# check a part of input section
|
|
348
|
-
user_cfg_input = get_config_input_custom_cars(
|
|
438
|
+
user_cfg_input = get_config_input_custom_cars(
|
|
439
|
+
user_cfg, nodata_left, nodata_right
|
|
440
|
+
)
|
|
349
441
|
cfg_input = check_input_section_custom_cars(user_cfg_input)
|
|
350
442
|
# concatenate updated config
|
|
351
443
|
cfg = concat_conf([cfg_input, cfg_pipeline])
|
|
@@ -370,7 +462,46 @@ default_short_configuration_input_custom_cars = {
|
|
|
370
462
|
}
|
|
371
463
|
|
|
372
464
|
|
|
373
|
-
def
|
|
465
|
+
def overide_pandora_get_metadata(
|
|
466
|
+
im_bands: list, classif_bands: list = None
|
|
467
|
+
) -> xr.Dataset:
|
|
468
|
+
"""
|
|
469
|
+
Read metadata from image, and return the corresponding xarray.DataSet
|
|
470
|
+
|
|
471
|
+
:param im_bands: list of band names
|
|
472
|
+
:param classif_bands: list of classification band names
|
|
473
|
+
:return: partial xarray.DataSet (attributes and coordinates)
|
|
474
|
+
:rtype: xarray.DataSet
|
|
475
|
+
"""
|
|
476
|
+
|
|
477
|
+
coords = {
|
|
478
|
+
"band_im": list(im_bands),
|
|
479
|
+
"row": np.arange(10),
|
|
480
|
+
"col": np.arange(10),
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
data_vars = {
|
|
484
|
+
"image": (["row", "col"], np.zeros((10, 10))),
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if classif_bands is not None:
|
|
488
|
+
coords["band_classif"] = list(classif_bands)
|
|
489
|
+
data_vars["classif"] = (
|
|
490
|
+
["row", "col", "band_classif"],
|
|
491
|
+
np.zeros((10, 10, len(classif_bands)), dtype=np.int32),
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
# create the dataset
|
|
495
|
+
dataset = xr.Dataset(data_vars=data_vars, coords=coords)
|
|
496
|
+
|
|
497
|
+
dataset.attrs["disparity_source"] = None
|
|
498
|
+
|
|
499
|
+
return dataset
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
def get_config_input_custom_cars(
|
|
503
|
+
user_cfg: Dict[str, dict], nodata_left, nodata_right
|
|
504
|
+
) -> Dict[str, dict]:
|
|
374
505
|
"""
|
|
375
506
|
Get the input configuration
|
|
376
507
|
|
|
@@ -387,9 +518,13 @@ def get_config_input_custom_cars(user_cfg: Dict[str, dict]) -> Dict[str, dict]:
|
|
|
387
518
|
|
|
388
519
|
if "nodata_left" in user_cfg["input"]:
|
|
389
520
|
cfg["input"]["nodata_left"] = user_cfg["input"]["nodata_left"]
|
|
521
|
+
else:
|
|
522
|
+
cfg["input"]["nodata_left"] = nodata_left
|
|
390
523
|
|
|
391
524
|
if "nodata_right" in user_cfg["input"]:
|
|
392
525
|
cfg["input"]["nodata_right"] = user_cfg["input"]["nodata_right"]
|
|
526
|
+
else:
|
|
527
|
+
cfg["input"]["nodata_right"] = nodata_right
|
|
393
528
|
|
|
394
529
|
return cfg
|
|
395
530
|
|
|
@@ -439,7 +574,7 @@ def overload_pandora_conf_with_confidence(conf, confidence_conf):
|
|
|
439
574
|
|
|
440
575
|
for key in confidence_conf_keys:
|
|
441
576
|
if key in conf_keys:
|
|
442
|
-
logging.
|
|
577
|
+
logging.info("{} pandora key already in configuration".format(key))
|
|
443
578
|
|
|
444
579
|
# update confidence
|
|
445
580
|
out_dict.update(confidence_conf)
|
|
@@ -31,6 +31,7 @@ import rasterio as rio
|
|
|
31
31
|
import scipy
|
|
32
32
|
import skimage
|
|
33
33
|
from json_checker import Checker, Or
|
|
34
|
+
from pyproj import CRS
|
|
34
35
|
from shapely import Polygon
|
|
35
36
|
|
|
36
37
|
from cars.core import inputs, projection
|
|
@@ -55,7 +56,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
55
56
|
|
|
56
57
|
# check conf
|
|
57
58
|
self.used_method = self.used_config["method"]
|
|
58
|
-
self.activated = self.used_config["activated"]
|
|
59
59
|
self.classification = self.used_config["classification"]
|
|
60
60
|
self.component_min_size = self.used_config["component_min_size"]
|
|
61
61
|
self.border_size = self.used_config["border_size"]
|
|
@@ -73,8 +73,11 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
73
73
|
|
|
74
74
|
# Overload conf
|
|
75
75
|
overloaded_conf["method"] = conf.get("method", "bulldozer")
|
|
76
|
-
overloaded_conf["
|
|
77
|
-
overloaded_conf["classification"]
|
|
76
|
+
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
77
|
+
if isinstance(overloaded_conf["classification"], str):
|
|
78
|
+
overloaded_conf["classification"] = [
|
|
79
|
+
overloaded_conf["classification"]
|
|
80
|
+
]
|
|
78
81
|
overloaded_conf["component_min_size"] = conf.get(
|
|
79
82
|
"component_min_size", 5
|
|
80
83
|
)
|
|
@@ -86,7 +89,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
86
89
|
|
|
87
90
|
rectification_schema = {
|
|
88
91
|
"method": str,
|
|
89
|
-
"activated": bool,
|
|
90
92
|
"classification": Or(None, [str]),
|
|
91
93
|
"component_min_size": int,
|
|
92
94
|
"border_size": int,
|
|
@@ -101,7 +103,7 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
101
103
|
return overloaded_conf
|
|
102
104
|
|
|
103
105
|
@cars_profile(name="Border interpolation filling")
|
|
104
|
-
def run( # noqa C901
|
|
106
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
105
107
|
self,
|
|
106
108
|
dsm_file,
|
|
107
109
|
classif_file,
|
|
@@ -122,9 +124,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
122
124
|
- a Shapely Polygon
|
|
123
125
|
"""
|
|
124
126
|
|
|
125
|
-
if not self.activated:
|
|
126
|
-
return
|
|
127
|
-
|
|
128
127
|
if self.classification is None:
|
|
129
128
|
self.classification = ["nodata"]
|
|
130
129
|
logging.error(
|
|
@@ -151,8 +150,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
151
150
|
roi_polys_outepsg = []
|
|
152
151
|
for poly in roi_polys:
|
|
153
152
|
if isinstance(poly, Polygon):
|
|
154
|
-
roi_poly_outepsg = projection.
|
|
155
|
-
poly, roi_epsg, dsm_crs
|
|
153
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
154
|
+
poly, CRS(roi_epsg), dsm_crs
|
|
156
155
|
)
|
|
157
156
|
roi_polys_outepsg.append(roi_poly_outepsg)
|
|
158
157
|
|
|
@@ -160,8 +159,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
|
|
|
160
159
|
roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
|
|
161
160
|
)
|
|
162
161
|
elif isinstance(roi_polys, Polygon):
|
|
163
|
-
roi_poly_outepsg = projection.
|
|
164
|
-
roi_polys, roi_epsg, dsm_crs
|
|
162
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
163
|
+
roi_polys, CRS(roi_epsg), dsm_crs
|
|
165
164
|
)
|
|
166
165
|
roi_raster = rio.features.rasterize(
|
|
167
166
|
[roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
|
|
@@ -32,6 +32,7 @@ import rasterio as rio
|
|
|
32
32
|
import yaml
|
|
33
33
|
from bulldozer.pipeline.bulldozer_pipeline import dsm_to_dtm
|
|
34
34
|
from json_checker import Checker, Or
|
|
35
|
+
from pyproj import CRS
|
|
35
36
|
from shapely import Polygon
|
|
36
37
|
|
|
37
38
|
from cars.core import inputs, projection
|
|
@@ -56,7 +57,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
56
57
|
|
|
57
58
|
# check conf
|
|
58
59
|
self.used_method = self.used_config["method"]
|
|
59
|
-
self.activated = self.used_config["activated"]
|
|
60
60
|
self.classification = self.used_config["classification"]
|
|
61
61
|
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
62
62
|
|
|
@@ -71,15 +71,19 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
71
71
|
|
|
72
72
|
# Overload conf
|
|
73
73
|
overloaded_conf["method"] = conf.get("method", "bulldozer")
|
|
74
|
-
overloaded_conf["
|
|
75
|
-
|
|
74
|
+
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
75
|
+
|
|
76
|
+
if isinstance(overloaded_conf["classification"], str):
|
|
77
|
+
overloaded_conf["classification"] = [
|
|
78
|
+
overloaded_conf["classification"]
|
|
79
|
+
]
|
|
80
|
+
|
|
76
81
|
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
77
82
|
"save_intermediate_data", False
|
|
78
83
|
)
|
|
79
84
|
|
|
80
85
|
rectification_schema = {
|
|
81
86
|
"method": str,
|
|
82
|
-
"activated": bool,
|
|
83
87
|
"classification": Or(None, [str]),
|
|
84
88
|
"save_intermediate_data": bool,
|
|
85
89
|
}
|
|
@@ -91,7 +95,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
91
95
|
return overloaded_conf
|
|
92
96
|
|
|
93
97
|
@cars_profile(name="Bulldozer filling")
|
|
94
|
-
def run( # noqa C901
|
|
98
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
95
99
|
self,
|
|
96
100
|
dsm_file,
|
|
97
101
|
classif_file,
|
|
@@ -112,9 +116,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
112
116
|
- a Shapely Polygon
|
|
113
117
|
"""
|
|
114
118
|
|
|
115
|
-
if not self.activated:
|
|
116
|
-
return None
|
|
117
|
-
|
|
118
119
|
if self.classification is None:
|
|
119
120
|
self.classification = ["nodata"]
|
|
120
121
|
|
|
@@ -162,8 +163,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
162
163
|
roi_polys_outepsg = []
|
|
163
164
|
for poly in roi_polys:
|
|
164
165
|
if isinstance(poly, Polygon):
|
|
165
|
-
roi_poly_outepsg = projection.
|
|
166
|
-
poly, roi_epsg, dsm_crs
|
|
166
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
167
|
+
poly, CRS(roi_epsg), dsm_crs
|
|
167
168
|
)
|
|
168
169
|
roi_polys_outepsg.append(roi_poly_outepsg)
|
|
169
170
|
|
|
@@ -171,8 +172,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
171
172
|
roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
|
|
172
173
|
)
|
|
173
174
|
elif isinstance(roi_polys, Polygon):
|
|
174
|
-
roi_poly_outepsg = projection.
|
|
175
|
-
roi_polys, roi_epsg, dsm_crs
|
|
175
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
176
|
+
roi_polys, CRS(roi_epsg), dsm_crs
|
|
176
177
|
)
|
|
177
178
|
roi_raster = rio.features.rasterize(
|
|
178
179
|
[roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
|
|
@@ -199,7 +200,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
199
200
|
):
|
|
200
201
|
dsm_to_dtm(bull_conf_path)
|
|
201
202
|
except Exception:
|
|
202
|
-
logging.
|
|
203
|
+
logging.warning(
|
|
203
204
|
"Bulldozer failed on its second execution."
|
|
204
205
|
+ " The DSM could not be filled."
|
|
205
206
|
)
|
|
@@ -211,7 +212,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
211
212
|
with rio.open(old_dsm_path, "w", **dsm_meta) as out_dsm:
|
|
212
213
|
out_dsm.write(dsm, 1)
|
|
213
214
|
|
|
214
|
-
if classif_file is not None:
|
|
215
|
+
if classif_file is not None and os.path.exists(classif_file):
|
|
215
216
|
classif_descriptions = inputs.get_descriptions_bands(classif_file)
|
|
216
217
|
else:
|
|
217
218
|
classif_descriptions = []
|
|
@@ -225,7 +226,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
|
|
|
225
226
|
classif[classif_msk == 0] = 0
|
|
226
227
|
filling_mask = np.logical_and(classif, roi_raster > 0)
|
|
227
228
|
elif label == "nodata":
|
|
228
|
-
if classif_file is not None:
|
|
229
|
+
if classif_file is not None and os.path.exists(classif_file):
|
|
229
230
|
with rio.open(classif_file) as in_classif:
|
|
230
231
|
classif_msk = in_classif.read_masks(1)
|
|
231
232
|
classif = ~classif_msk
|
|
@@ -29,6 +29,7 @@ import shutil
|
|
|
29
29
|
import numpy as np
|
|
30
30
|
import rasterio as rio
|
|
31
31
|
from json_checker import Checker, Or
|
|
32
|
+
from pyproj import CRS
|
|
32
33
|
from rasterio.enums import Resampling
|
|
33
34
|
from rasterio.warp import reproject
|
|
34
35
|
from shapely import Polygon
|
|
@@ -55,7 +56,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
55
56
|
|
|
56
57
|
# check conf
|
|
57
58
|
self.used_method = self.used_config["method"]
|
|
58
|
-
self.activated = self.used_config["activated"]
|
|
59
59
|
self.classification = self.used_config["classification"]
|
|
60
60
|
self.fill_with_geoid = self.used_config["fill_with_geoid"]
|
|
61
61
|
self.interpolation_method = self.used_config["interpolation_method"]
|
|
@@ -72,18 +72,22 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
72
72
|
|
|
73
73
|
# Overload conf
|
|
74
74
|
overloaded_conf["method"] = conf.get("method", "bulldozer")
|
|
75
|
-
overloaded_conf["
|
|
76
|
-
overloaded_conf["classification"]
|
|
75
|
+
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
76
|
+
if isinstance(overloaded_conf["classification"], str):
|
|
77
|
+
overloaded_conf["classification"] = [
|
|
78
|
+
overloaded_conf["classification"]
|
|
79
|
+
]
|
|
77
80
|
overloaded_conf["fill_with_geoid"] = conf.get("fill_with_geoid", None)
|
|
78
81
|
overloaded_conf["interpolation_method"] = conf.get(
|
|
79
82
|
"interpolation_method", "bilinear"
|
|
80
83
|
)
|
|
81
84
|
|
|
82
85
|
if overloaded_conf["interpolation_method"] not in ["bilinear", "cubic"]:
|
|
86
|
+
# pylint: disable=inconsistent-quotes
|
|
83
87
|
raise RuntimeError(
|
|
84
|
-
"Invalid interpolation method"
|
|
88
|
+
f"Invalid interpolation method"
|
|
85
89
|
f"{overloaded_conf['interpolation_method']}, "
|
|
86
|
-
"supported modes are bilinear and cubic."
|
|
90
|
+
f"supported modes are bilinear and cubic."
|
|
87
91
|
)
|
|
88
92
|
|
|
89
93
|
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
@@ -92,7 +96,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
92
96
|
|
|
93
97
|
rectification_schema = {
|
|
94
98
|
"method": str,
|
|
95
|
-
"activated": bool,
|
|
96
99
|
"classification": Or(None, [str]),
|
|
97
100
|
"fill_with_geoid": Or(None, [str]),
|
|
98
101
|
"interpolation_method": str,
|
|
@@ -106,7 +109,7 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
106
109
|
return overloaded_conf
|
|
107
110
|
|
|
108
111
|
@cars_profile(name="Exogeneous filling")
|
|
109
|
-
def run( # noqa C901
|
|
112
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
110
113
|
self,
|
|
111
114
|
dsm_file,
|
|
112
115
|
classif_file,
|
|
@@ -128,9 +131,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
128
131
|
- a Shapely Polygon
|
|
129
132
|
"""
|
|
130
133
|
|
|
131
|
-
if not self.activated:
|
|
132
|
-
return
|
|
133
|
-
|
|
134
134
|
if self.classification is None:
|
|
135
135
|
self.classification = ["nodata"]
|
|
136
136
|
|
|
@@ -170,8 +170,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
170
170
|
roi_polys_outepsg = []
|
|
171
171
|
for poly in roi_polys:
|
|
172
172
|
if isinstance(poly, Polygon):
|
|
173
|
-
roi_poly_outepsg = projection.
|
|
174
|
-
poly, roi_epsg, dsm_crs
|
|
173
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
174
|
+
poly, CRS(roi_epsg), dsm_crs
|
|
175
175
|
)
|
|
176
176
|
roi_polys_outepsg.append(roi_poly_outepsg)
|
|
177
177
|
|
|
@@ -179,8 +179,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
|
179
179
|
roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
|
|
180
180
|
)
|
|
181
181
|
elif isinstance(roi_polys, Polygon):
|
|
182
|
-
roi_poly_outepsg = projection.
|
|
183
|
-
roi_polys, roi_epsg, dsm_crs
|
|
182
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
183
|
+
roi_polys, CRS(roi_epsg), dsm_crs
|
|
184
184
|
)
|
|
185
185
|
roi_raster = rio.features.rasterize(
|
|
186
186
|
[roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
|
|
@@ -31,7 +31,9 @@ from json_checker import And, Checker
|
|
|
31
31
|
|
|
32
32
|
import cars.orchestrator.orchestrator as ocht
|
|
33
33
|
from cars.applications import application_constants
|
|
34
|
-
from cars.applications.grid_generation import
|
|
34
|
+
from cars.applications.grid_generation import (
|
|
35
|
+
grid_generation_algo,
|
|
36
|
+
)
|
|
35
37
|
from cars.applications.grid_generation import (
|
|
36
38
|
grid_generation_constants as grid_constants,
|
|
37
39
|
)
|
|
@@ -119,7 +121,7 @@ class EpipolarGridGeneration(GridGeneration, short_name="epipolar"):
|
|
|
119
121
|
return self.save_intermediate_data
|
|
120
122
|
|
|
121
123
|
@cars_profile(name="Epi Grid Generation")
|
|
122
|
-
def run(
|
|
124
|
+
def run( # pylint: disable=too-many-positional-arguments
|
|
123
125
|
self,
|
|
124
126
|
image_left,
|
|
125
127
|
image_right,
|
|
@@ -37,7 +37,9 @@ from scipy.spatial import Delaunay # pylint: disable=E0611
|
|
|
37
37
|
|
|
38
38
|
import cars.orchestrator.orchestrator as ocht
|
|
39
39
|
from cars.applications import application_constants
|
|
40
|
-
from cars.applications.grid_generation import
|
|
40
|
+
from cars.applications.grid_generation import (
|
|
41
|
+
grid_generation_algo,
|
|
42
|
+
)
|
|
41
43
|
from cars.applications.grid_generation import (
|
|
42
44
|
grid_generation_constants as grid_constants,
|
|
43
45
|
)
|
|
@@ -165,6 +167,7 @@ def correct_grid(grid, grid_correction, pair_folder, save_grid=None):
|
|
|
165
167
|
return corrected_grid_right
|
|
166
168
|
|
|
167
169
|
|
|
170
|
+
# pylint: disable=too-many-positional-arguments
|
|
168
171
|
@cars_profile(name="Grid correction estimation")
|
|
169
172
|
def estimate_right_grid_correction(
|
|
170
173
|
matches,
|
|
@@ -43,6 +43,7 @@ from cars.applications.triangulation.triangulation_algo import (
|
|
|
43
43
|
)
|
|
44
44
|
from cars.core import constants as cst
|
|
45
45
|
from cars.core import inputs, projection, tiling
|
|
46
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
def get_new_path(path):
|
|
@@ -106,7 +107,7 @@ def write_grid(grid, fname, origin, spacing):
|
|
|
106
107
|
dst.write_band(2, grid[:, :, 1])
|
|
107
108
|
|
|
108
109
|
|
|
109
|
-
def generate_epipolar_grids(
|
|
110
|
+
def generate_epipolar_grids( # pylint: disable=too-many-positional-arguments
|
|
110
111
|
sensor1, sensor2, geomodel1, geomodel2, geometry_plugin, epipolar_step
|
|
111
112
|
):
|
|
112
113
|
"""
|
|
@@ -140,6 +141,8 @@ def generate_epipolar_grids(
|
|
|
140
141
|
)
|
|
141
142
|
|
|
142
143
|
|
|
144
|
+
# pylint: disable=too-many-positional-arguments
|
|
145
|
+
@cars_profile(name="Compute epipolar grid min max", interval=0.5)
|
|
143
146
|
def compute_epipolar_grid_min_max(
|
|
144
147
|
geometry_plugin,
|
|
145
148
|
grid,
|
|
@@ -239,6 +242,7 @@ def compute_epipolar_grid_min_max(
|
|
|
239
242
|
grid1,
|
|
240
243
|
grid2,
|
|
241
244
|
matches_min,
|
|
245
|
+
interpolation_method="linear",
|
|
242
246
|
)
|
|
243
247
|
pc_max = triangulate_matches(
|
|
244
248
|
geometry_plugin,
|
|
@@ -249,6 +253,7 @@ def compute_epipolar_grid_min_max(
|
|
|
249
253
|
grid1,
|
|
250
254
|
grid2,
|
|
251
255
|
matches_max,
|
|
256
|
+
interpolation_method="linear",
|
|
252
257
|
)
|
|
253
258
|
|
|
254
259
|
# Convert to correct EPSG
|
|
@@ -278,7 +283,7 @@ def compute_epipolar_grid_min_max(
|
|
|
278
283
|
return grid_min, grid_max
|
|
279
284
|
|
|
280
285
|
|
|
281
|
-
def terrain_region_to_epipolar(
|
|
286
|
+
def terrain_region_to_epipolar( # pylint: disable=too-many-positional-arguments
|
|
282
287
|
region,
|
|
283
288
|
sensor1,
|
|
284
289
|
sensor2,
|