cars 1.0.0rc2__cp312-cp312-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 +86 -0
- cars/applications/__init__.py +40 -0
- cars/applications/application.py +117 -0
- cars/applications/application_constants.py +29 -0
- cars/applications/application_template.py +146 -0
- cars/applications/auxiliary_filling/__init__.py +29 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +105 -0
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +632 -0
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
- cars/applications/dem_generation/__init__.py +30 -0
- cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
- cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
- cars/applications/dem_generation/bulldozer_dem_app.py +641 -0
- cars/applications/dem_generation/bulldozer_memory.py +55 -0
- cars/applications/dem_generation/dem_generation_algo.py +107 -0
- cars/applications/dem_generation/dem_generation_constants.py +32 -0
- cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
- cars/applications/dense_match_filling/__init__.py +30 -0
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
- cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
- cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
- cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
- cars/applications/dense_match_filling/zero_padding_app.py +302 -0
- cars/applications/dense_matching/__init__.py +30 -0
- cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
- cars/applications/dense_matching/census_mccnn_sgm_app.py +1461 -0
- cars/applications/dense_matching/cpp/__init__.py +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.pyd +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
- cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
- cars/applications/dense_matching/cpp/meson.build +9 -0
- cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
- cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
- cars/applications/dense_matching/dense_matching_algo.py +401 -0
- cars/applications/dense_matching/dense_matching_constants.py +89 -0
- cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
- cars/applications/dense_matching/disparity_grid_algo.py +597 -0
- cars/applications/dense_matching/loaders/__init__.py +23 -0
- cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
- cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
- cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
- cars/applications/dsm_filling/__init__.py +32 -0
- cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
- cars/applications/dsm_filling/border_interpolation_app.py +278 -0
- cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
- cars/applications/dsm_filling/bulldozer_filling_app.py +288 -0
- cars/applications/dsm_filling/exogenous_filling_app.py +341 -0
- cars/applications/dsm_merging/__init__.py +28 -0
- cars/applications/dsm_merging/abstract_dsm_merging_app.py +101 -0
- cars/applications/dsm_merging/weighted_fusion_app.py +639 -0
- cars/applications/grid_correction/__init__.py +30 -0
- cars/applications/grid_correction/abstract_grid_correction_app.py +103 -0
- cars/applications/grid_correction/grid_correction_app.py +557 -0
- cars/applications/grid_generation/__init__.py +30 -0
- cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
- cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
- cars/applications/grid_generation/grid_generation_algo.py +388 -0
- cars/applications/grid_generation/grid_generation_constants.py +46 -0
- cars/applications/grid_generation/transform_grid.py +88 -0
- cars/applications/ground_truth_reprojection/__init__.py +30 -0
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
- cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
- cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
- cars/applications/point_cloud_outlier_removal/small_components_app.py +522 -0
- cars/applications/point_cloud_outlier_removal/statistical_app.py +528 -0
- cars/applications/rasterization/__init__.py +30 -0
- cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
- cars/applications/rasterization/rasterization_algo.py +534 -0
- cars/applications/rasterization/rasterization_constants.py +38 -0
- cars/applications/rasterization/rasterization_wrappers.py +639 -0
- cars/applications/rasterization/simple_gaussian_app.py +1152 -0
- cars/applications/resampling/__init__.py +28 -0
- cars/applications/resampling/abstract_resampling_app.py +187 -0
- cars/applications/resampling/bicubic_resampling_app.py +760 -0
- cars/applications/resampling/resampling_algo.py +590 -0
- cars/applications/resampling/resampling_constants.py +36 -0
- cars/applications/resampling/resampling_wrappers.py +309 -0
- cars/applications/sensors_subsampling/__init__.py +32 -0
- cars/applications/sensors_subsampling/abstract_subsampling_app.py +109 -0
- cars/applications/sensors_subsampling/rasterio_subsampling_app.py +420 -0
- cars/applications/sensors_subsampling/subsampling_algo.py +108 -0
- cars/applications/sparse_matching/__init__.py +30 -0
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +599 -0
- cars/applications/sparse_matching/sift_app.py +724 -0
- cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
- cars/applications/sparse_matching/sparse_matching_constants.py +66 -0
- cars/applications/sparse_matching/sparse_matching_wrappers.py +282 -0
- cars/applications/triangulation/__init__.py +32 -0
- cars/applications/triangulation/abstract_triangulation_app.py +227 -0
- cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +371 -0
- cars/applications/triangulation/triangulation_constants.py +38 -0
- cars/applications/triangulation/triangulation_wrappers.py +259 -0
- cars/bundleadjustment.py +750 -0
- cars/cars.py +179 -0
- cars/conf/__init__.py +23 -0
- cars/conf/geoid/egm96.grd +0 -0
- cars/conf/geoid/egm96.grd.hdr +15 -0
- cars/conf/input_parameters.py +156 -0
- cars/conf/mask_cst.py +35 -0
- cars/core/__init__.py +23 -0
- cars/core/cars_logging.py +402 -0
- cars/core/constants.py +191 -0
- cars/core/constants_disparity.py +50 -0
- cars/core/datasets.py +140 -0
- cars/core/geometry/__init__.py +27 -0
- cars/core/geometry/abstract_geometry.py +1119 -0
- cars/core/geometry/shareloc_geometry.py +598 -0
- cars/core/inputs.py +568 -0
- cars/core/outputs.py +176 -0
- cars/core/preprocessing.py +722 -0
- cars/core/projection.py +843 -0
- cars/core/roi_tools.py +215 -0
- cars/core/tiling.py +774 -0
- cars/core/utils.py +164 -0
- cars/data_structures/__init__.py +23 -0
- cars/data_structures/cars_dataset.py +1544 -0
- cars/data_structures/cars_dict.py +74 -0
- cars/data_structures/corresponding_tiles_tools.py +186 -0
- cars/data_structures/dataframe_converter.py +185 -0
- cars/data_structures/format_transformation.py +297 -0
- cars/devibrate.py +689 -0
- cars/extractroi.py +264 -0
- cars/orchestrator/__init__.py +23 -0
- cars/orchestrator/achievement_tracker.py +125 -0
- cars/orchestrator/cluster/__init__.py +37 -0
- cars/orchestrator/cluster/abstract_cluster.py +250 -0
- cars/orchestrator/cluster/abstract_dask_cluster.py +381 -0
- cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
- cars/orchestrator/cluster/dask_config/README.md +94 -0
- cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
- cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
- cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
- cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
- cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
- cars/orchestrator/cluster/local_dask_cluster.py +116 -0
- cars/orchestrator/cluster/log_wrapper.py +728 -0
- cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
- cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
- cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
- cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
- cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +986 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
- cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
- cars/orchestrator/cluster/sequential_cluster.py +139 -0
- cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
- cars/orchestrator/memory_tools.py +47 -0
- cars/orchestrator/orchestrator.py +755 -0
- cars/orchestrator/orchestrator_constants.py +29 -0
- cars/orchestrator/registry/__init__.py +23 -0
- cars/orchestrator/registry/abstract_registry.py +143 -0
- cars/orchestrator/registry/compute_registry.py +106 -0
- cars/orchestrator/registry/id_generator.py +116 -0
- cars/orchestrator/registry/replacer_registry.py +213 -0
- cars/orchestrator/registry/saver_registry.py +363 -0
- cars/orchestrator/registry/unseen_registry.py +118 -0
- cars/orchestrator/tiles_profiler.py +279 -0
- cars/pipelines/__init__.py +26 -0
- cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
- cars/pipelines/conf_resolution/conf_first_resolution.yaml +4 -0
- cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
- cars/pipelines/default/__init__.py +26 -0
- cars/pipelines/default/default_pipeline.py +1088 -0
- cars/pipelines/filling/__init__.py +26 -0
- cars/pipelines/filling/filling.py +981 -0
- cars/pipelines/formatting/__init__.py +26 -0
- cars/pipelines/formatting/formatting.py +186 -0
- cars/pipelines/merging/__init__.py +26 -0
- cars/pipelines/merging/merging.py +439 -0
- cars/pipelines/parameters/__init__.py +0 -0
- cars/pipelines/parameters/advanced_parameters.py +256 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +68 -0
- cars/pipelines/parameters/application_parameters.py +72 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -0
- cars/pipelines/parameters/dsm_inputs.py +349 -0
- cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
- cars/pipelines/parameters/output_constants.py +52 -0
- cars/pipelines/parameters/output_parameters.py +438 -0
- cars/pipelines/parameters/sensor_inputs.py +859 -0
- cars/pipelines/parameters/sensor_inputs_constants.py +51 -0
- cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
- cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
- cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
- cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
- cars/pipelines/pipeline.py +119 -0
- cars/pipelines/pipeline_constants.py +38 -0
- cars/pipelines/pipeline_template.py +135 -0
- cars/pipelines/subsampling/__init__.py +26 -0
- cars/pipelines/subsampling/subsampling.py +358 -0
- cars/pipelines/surface_modeling/__init__.py +26 -0
- cars/pipelines/surface_modeling/surface_modeling.py +2098 -0
- cars/pipelines/tie_points/__init__.py +26 -0
- cars/pipelines/tie_points/tie_points.py +536 -0
- cars/starter.py +167 -0
- cars-1.0.0rc2.dist-info/DELVEWHEEL +2 -0
- cars-1.0.0rc2.dist-info/METADATA +289 -0
- cars-1.0.0rc2.dist-info/RECORD +225 -0
- cars-1.0.0rc2.dist-info/WHEEL +4 -0
- cars-1.0.0rc2.dist-info/entry_points.txt +8 -0
- cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
- cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
- cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
|
|
5
|
+
#
|
|
6
|
+
# This file is part of CARS
|
|
7
|
+
# (see https://github.com/CNES/cars).
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
"""
|
|
22
|
+
CARS pandora loader file
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import copy
|
|
26
|
+
import json
|
|
27
|
+
import logging
|
|
28
|
+
import os
|
|
29
|
+
from collections import OrderedDict
|
|
30
|
+
from typing import Dict
|
|
31
|
+
|
|
32
|
+
import numpy as np
|
|
33
|
+
import pandora
|
|
34
|
+
import rasterio
|
|
35
|
+
import xarray as xr
|
|
36
|
+
from json_checker import Checker, Or
|
|
37
|
+
from pandora.check_configuration import (
|
|
38
|
+
check_pipeline_section,
|
|
39
|
+
concat_conf,
|
|
40
|
+
get_config_pipeline,
|
|
41
|
+
update_conf,
|
|
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
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class PandoraLoader:
|
|
52
|
+
"""
|
|
53
|
+
PandoraLoader
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__( # pylint: disable=too-many-positional-arguments # noqa: C901
|
|
58
|
+
self,
|
|
59
|
+
conf=None,
|
|
60
|
+
method_name=None,
|
|
61
|
+
generate_performance_map_from_risk=False,
|
|
62
|
+
generate_performance_map_from_intervals=False,
|
|
63
|
+
generate_ambiguity=False,
|
|
64
|
+
perf_eta_max_ambiguity=0.99,
|
|
65
|
+
perf_eta_max_risk=0.25,
|
|
66
|
+
perf_eta_step=0.04,
|
|
67
|
+
use_cross_validation=True,
|
|
68
|
+
denoise_disparity_map=False,
|
|
69
|
+
used_band="b0",
|
|
70
|
+
):
|
|
71
|
+
"""
|
|
72
|
+
Init function of PandoraLoader
|
|
73
|
+
|
|
74
|
+
If conf is profided, pandora will use it
|
|
75
|
+
If not, Pandora will use intern configuration :
|
|
76
|
+
census or mccnn, depending on method_name
|
|
77
|
+
|
|
78
|
+
:param conf: configuration of pandora to use
|
|
79
|
+
:type conf: dict
|
|
80
|
+
:param method_name: name of method to use
|
|
81
|
+
:param performance_map_conf: true if generate performance maps
|
|
82
|
+
:param use_cross_validation: true to add crossvalidation
|
|
83
|
+
:param denoise_disparity_map: true to add the disparity denoiser filter
|
|
84
|
+
:param used_band: name of band used for correlation
|
|
85
|
+
:type used_band: str
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
if method_name is None:
|
|
89
|
+
method_name = "census_sgm_default"
|
|
90
|
+
|
|
91
|
+
self.pandora_config = None
|
|
92
|
+
|
|
93
|
+
uses_cars_pandora_conf = False
|
|
94
|
+
|
|
95
|
+
if isinstance(conf, str):
|
|
96
|
+
# load file
|
|
97
|
+
with open(conf, "r", encoding="utf8") as fstream:
|
|
98
|
+
conf = json.load(fstream)
|
|
99
|
+
|
|
100
|
+
elif conf is None:
|
|
101
|
+
uses_cars_pandora_conf = True
|
|
102
|
+
package_path = os.path.dirname(__file__)
|
|
103
|
+
|
|
104
|
+
if method_name == "mccnn_sgm":
|
|
105
|
+
# Use mccn_conf
|
|
106
|
+
|
|
107
|
+
conf_file_path = os.path.join(package_path, "config_mccnn.json")
|
|
108
|
+
# Read conf
|
|
109
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
110
|
+
conf = json.load(fstream)
|
|
111
|
+
elif method_name == "census_sgm_urban":
|
|
112
|
+
# Use census sgm conf
|
|
113
|
+
conf_file_path = os.path.join(
|
|
114
|
+
package_path, "config_census_sgm_urban.json"
|
|
115
|
+
)
|
|
116
|
+
# read conf
|
|
117
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
118
|
+
conf = json.load(fstream)
|
|
119
|
+
elif method_name == "census_sgm_shadow":
|
|
120
|
+
# Use census sgm conf
|
|
121
|
+
conf_file_path = os.path.join(
|
|
122
|
+
package_path, "config_census_sgm_shadow.json"
|
|
123
|
+
)
|
|
124
|
+
# read conf
|
|
125
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
126
|
+
conf = json.load(fstream)
|
|
127
|
+
elif method_name == "census_sgm_mountain_and_vegetation":
|
|
128
|
+
# Use census sgm conf
|
|
129
|
+
conf_file_path = os.path.join(
|
|
130
|
+
package_path,
|
|
131
|
+
"config_census_sgm_mountain_and_vegetation.json",
|
|
132
|
+
)
|
|
133
|
+
# read conf
|
|
134
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
135
|
+
conf = json.load(fstream)
|
|
136
|
+
elif method_name == "census_sgm_homogeneous":
|
|
137
|
+
# Use census sgm conf
|
|
138
|
+
conf_file_path = os.path.join(
|
|
139
|
+
package_path, "config_census_sgm_homogeneous.json"
|
|
140
|
+
)
|
|
141
|
+
# read conf
|
|
142
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
143
|
+
conf = json.load(fstream)
|
|
144
|
+
elif method_name in ("census_sgm_default", "auto"):
|
|
145
|
+
# Use census sgm conf
|
|
146
|
+
conf_file_path = os.path.join(
|
|
147
|
+
package_path, "config_census_sgm_default.json"
|
|
148
|
+
)
|
|
149
|
+
# read conf
|
|
150
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
151
|
+
conf = json.load(fstream)
|
|
152
|
+
elif method_name == "census_sgm_sparse":
|
|
153
|
+
# Use census sgm conf
|
|
154
|
+
conf_file_path = os.path.join(
|
|
155
|
+
package_path, "config_census_sgm_sparse.json"
|
|
156
|
+
)
|
|
157
|
+
# read conf
|
|
158
|
+
with open(conf_file_path, "r", encoding="utf8") as fstream:
|
|
159
|
+
conf = json.load(fstream)
|
|
160
|
+
else:
|
|
161
|
+
logging.error(
|
|
162
|
+
"No method named {} in pandora loader".format(method_name)
|
|
163
|
+
)
|
|
164
|
+
raise NameError(
|
|
165
|
+
"No method named {} in pandora loader".format(method_name)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
perf_ambiguity_conf = {
|
|
169
|
+
"cost_volume_confidence.cars_1": {
|
|
170
|
+
"confidence_method": "ambiguity",
|
|
171
|
+
"eta_max": perf_eta_max_ambiguity,
|
|
172
|
+
"eta_step": perf_eta_step,
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
perf_risk_conf = {
|
|
177
|
+
"cost_volume_confidence.cars_2": {
|
|
178
|
+
"confidence_method": "risk",
|
|
179
|
+
"eta_max": perf_eta_max_risk,
|
|
180
|
+
"eta_step": perf_eta_step,
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
intervals_conf = {
|
|
184
|
+
"cost_volume_confidence.cars_3": {
|
|
185
|
+
"confidence_method": "interval_bounds",
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
# Cross validation
|
|
189
|
+
cross_validation_acc_conf = {
|
|
190
|
+
"validation": {
|
|
191
|
+
"validation_method": "cross_checking_accurate",
|
|
192
|
+
"cross_checking_threshold": 1.0,
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
cross_validation_fast_conf = {
|
|
197
|
+
"validation": {
|
|
198
|
+
"validation_method": "cross_checking_fast",
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
disparity_denoiser_conf = {
|
|
203
|
+
"filter": {"filter_method": "disparity_denoiser"}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
confidences = {}
|
|
207
|
+
if generate_performance_map_from_risk:
|
|
208
|
+
confidences.update(perf_ambiguity_conf)
|
|
209
|
+
confidences.update(perf_risk_conf)
|
|
210
|
+
if generate_performance_map_from_intervals:
|
|
211
|
+
confidences.update(perf_ambiguity_conf)
|
|
212
|
+
confidences.update(intervals_conf)
|
|
213
|
+
|
|
214
|
+
if generate_ambiguity:
|
|
215
|
+
confidences.update(perf_ambiguity_conf)
|
|
216
|
+
|
|
217
|
+
if confidences:
|
|
218
|
+
conf["pipeline"] = overload_pandora_conf_with_confidence(
|
|
219
|
+
conf["pipeline"], confidences
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# update with cross validation
|
|
223
|
+
if "validation" not in conf["pipeline"]:
|
|
224
|
+
if use_cross_validation in (True, "fast"):
|
|
225
|
+
conf["pipeline"].update(cross_validation_fast_conf)
|
|
226
|
+
elif use_cross_validation == "accurate":
|
|
227
|
+
conf["pipeline"].update(cross_validation_acc_conf)
|
|
228
|
+
|
|
229
|
+
if (
|
|
230
|
+
denoise_disparity_map
|
|
231
|
+
and conf["pipeline"]["filter"]["filter_method"]
|
|
232
|
+
!= "disparity_denoiser"
|
|
233
|
+
):
|
|
234
|
+
conf["pipeline"].update(disparity_denoiser_conf)
|
|
235
|
+
|
|
236
|
+
if "band" not in conf["pipeline"]["matching_cost"]:
|
|
237
|
+
conf["pipeline"]["matching_cost"]["band"] = used_band
|
|
238
|
+
|
|
239
|
+
if generate_performance_map_from_intervals:
|
|
240
|
+
# To ensure the consistency between the disparity map
|
|
241
|
+
# and the intervals, the median filter for intervals
|
|
242
|
+
# must be similar to the median filter. The filter is
|
|
243
|
+
# added at the end of the conf as it is applied during
|
|
244
|
+
# the disp_map state.
|
|
245
|
+
try:
|
|
246
|
+
filter_size = conf["pipeline"]["filter"]["filter_size"]
|
|
247
|
+
except KeyError:
|
|
248
|
+
filter_size = 3
|
|
249
|
+
|
|
250
|
+
conf_filter_interval = {
|
|
251
|
+
"filter.cars_3": {
|
|
252
|
+
"filter_method": "median_for_intervals",
|
|
253
|
+
"filter_size": filter_size,
|
|
254
|
+
"interval_indicator": "cars_3",
|
|
255
|
+
"regularization": True,
|
|
256
|
+
"ambiguity_indicator": "cars_1",
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
pipeline_dict = OrderedDict()
|
|
260
|
+
pipeline_dict.update(conf["pipeline"])
|
|
261
|
+
# Filter is placed after validation in config
|
|
262
|
+
# and should be placed before.
|
|
263
|
+
# However it does not have any incidence on operation
|
|
264
|
+
if uses_cars_pandora_conf:
|
|
265
|
+
pipeline_dict.update(conf_filter_interval)
|
|
266
|
+
|
|
267
|
+
conf["pipeline"] = pipeline_dict
|
|
268
|
+
|
|
269
|
+
if "filter" in conf["pipeline"]:
|
|
270
|
+
filter_conf = conf["pipeline"]["filter"]
|
|
271
|
+
if filter_conf["filter_method"] == "disparity_denoiser":
|
|
272
|
+
if "band" not in filter_conf:
|
|
273
|
+
conf["pipeline"]["filter"]["band"] = used_band
|
|
274
|
+
|
|
275
|
+
# Check conf
|
|
276
|
+
self.pandora_config = conf
|
|
277
|
+
|
|
278
|
+
def get_conf(self):
|
|
279
|
+
"""
|
|
280
|
+
Get pandora configuration used
|
|
281
|
+
|
|
282
|
+
:return: pandora configuration
|
|
283
|
+
:rtype: dict
|
|
284
|
+
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
return self.pandora_config
|
|
288
|
+
|
|
289
|
+
def get_classif_bands(self):
|
|
290
|
+
"""
|
|
291
|
+
Get the classification bands used in the pandora configuration
|
|
292
|
+
|
|
293
|
+
:return: list of classification bands
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
classif_bands = []
|
|
297
|
+
|
|
298
|
+
def search_classes_recursive(obj):
|
|
299
|
+
"""
|
|
300
|
+
Recursive search of keys containing 'classes' in the configuration
|
|
301
|
+
"""
|
|
302
|
+
if isinstance(obj, dict):
|
|
303
|
+
for key, value in obj.items():
|
|
304
|
+
if "classes" in key.lower():
|
|
305
|
+
if isinstance(value, list):
|
|
306
|
+
classif_bands.extend(value)
|
|
307
|
+
elif value is not None:
|
|
308
|
+
classif_bands.append(value)
|
|
309
|
+
# Continue recursive search
|
|
310
|
+
search_classes_recursive(value)
|
|
311
|
+
|
|
312
|
+
search_classes_recursive(self.pandora_config)
|
|
313
|
+
|
|
314
|
+
# Remove duplicates and return the list
|
|
315
|
+
return list(set(classif_bands))
|
|
316
|
+
|
|
317
|
+
@cars_profile(name="Find auto conf")
|
|
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
|
|
391
|
+
self,
|
|
392
|
+
user_cfg,
|
|
393
|
+
nodata_left,
|
|
394
|
+
nodata_right,
|
|
395
|
+
bands_left,
|
|
396
|
+
bands_right,
|
|
397
|
+
bands_classif_left=None,
|
|
398
|
+
bands_classif_right=None,
|
|
399
|
+
):
|
|
400
|
+
"""
|
|
401
|
+
Check configuration
|
|
402
|
+
|
|
403
|
+
:param user_cfg: configuration
|
|
404
|
+
:type user_cfg: dict
|
|
405
|
+
|
|
406
|
+
:return: pandora configuration
|
|
407
|
+
:rtype: dict
|
|
408
|
+
|
|
409
|
+
"""
|
|
410
|
+
# Import plugins before checking configuration
|
|
411
|
+
pandora.import_plugin()
|
|
412
|
+
# Check configuration and update the configuration with default values
|
|
413
|
+
# Instantiate pandora state machine
|
|
414
|
+
pandora_machine = PandoraMachine()
|
|
415
|
+
# check pipeline
|
|
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
|
+
)
|
|
422
|
+
|
|
423
|
+
metadata_left = metadata_left.assign_coords(band_im=bands_left)
|
|
424
|
+
metadata_right = metadata_right.assign_coords(band_im=bands_right)
|
|
425
|
+
|
|
426
|
+
user_cfg_pipeline = get_config_pipeline(user_cfg)
|
|
427
|
+
saved_schema = copy.deepcopy(
|
|
428
|
+
pandora.matching_cost.matching_cost.AbstractMatchingCost.schema
|
|
429
|
+
)
|
|
430
|
+
cfg_pipeline = check_pipeline_section(
|
|
431
|
+
user_cfg_pipeline, metadata_left, metadata_right, pandora_machine
|
|
432
|
+
)
|
|
433
|
+
# quick fix to remove when the problem is solved in pandora
|
|
434
|
+
pandora.matching_cost.matching_cost.AbstractMatchingCost.schema = (
|
|
435
|
+
saved_schema
|
|
436
|
+
)
|
|
437
|
+
# check a part of input section
|
|
438
|
+
user_cfg_input = get_config_input_custom_cars(
|
|
439
|
+
user_cfg, nodata_left, nodata_right
|
|
440
|
+
)
|
|
441
|
+
cfg_input = check_input_section_custom_cars(user_cfg_input)
|
|
442
|
+
# concatenate updated config
|
|
443
|
+
cfg = concat_conf([cfg_input, cfg_pipeline])
|
|
444
|
+
|
|
445
|
+
return cfg
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
input_configuration_schema_custom_cars = {
|
|
449
|
+
"nodata_left": Or(
|
|
450
|
+
int, lambda x: np.isnan(x) # pylint: disable=unnecessary-lambda
|
|
451
|
+
),
|
|
452
|
+
"nodata_right": Or(
|
|
453
|
+
int, lambda x: np.isnan(x) # pylint: disable=unnecessary-lambda
|
|
454
|
+
),
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
default_short_configuration_input_custom_cars = {
|
|
458
|
+
"input": {
|
|
459
|
+
"nodata_left": -9999,
|
|
460
|
+
"nodata_right": -9999,
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
|
|
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]:
|
|
505
|
+
"""
|
|
506
|
+
Get the input configuration
|
|
507
|
+
|
|
508
|
+
:param user_cfg: user configuration
|
|
509
|
+
:type user_cfg: dict
|
|
510
|
+
:return cfg: partial configuration
|
|
511
|
+
:rtype cfg: dict
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
cfg = {}
|
|
515
|
+
|
|
516
|
+
if "input" in user_cfg:
|
|
517
|
+
cfg["input"] = {}
|
|
518
|
+
|
|
519
|
+
if "nodata_left" in user_cfg["input"]:
|
|
520
|
+
cfg["input"]["nodata_left"] = user_cfg["input"]["nodata_left"]
|
|
521
|
+
else:
|
|
522
|
+
cfg["input"]["nodata_left"] = nodata_left
|
|
523
|
+
|
|
524
|
+
if "nodata_right" in user_cfg["input"]:
|
|
525
|
+
cfg["input"]["nodata_right"] = user_cfg["input"]["nodata_right"]
|
|
526
|
+
else:
|
|
527
|
+
cfg["input"]["nodata_right"] = nodata_right
|
|
528
|
+
|
|
529
|
+
return cfg
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def check_input_section_custom_cars(
|
|
533
|
+
user_cfg: Dict[str, dict],
|
|
534
|
+
) -> Dict[str, dict]:
|
|
535
|
+
"""
|
|
536
|
+
Complete and check if the dictionary is correct
|
|
537
|
+
|
|
538
|
+
:param user_cfg: user configuration
|
|
539
|
+
:type user_cfg: dict
|
|
540
|
+
:return: cfg: global configuration
|
|
541
|
+
:rtype: cfg: dict
|
|
542
|
+
"""
|
|
543
|
+
# Add missing steps and inputs defaults values in user_cfg
|
|
544
|
+
cfg = update_conf(default_short_configuration_input_custom_cars, user_cfg)
|
|
545
|
+
|
|
546
|
+
# check schema
|
|
547
|
+
configuration_schema = {"input": input_configuration_schema_custom_cars}
|
|
548
|
+
|
|
549
|
+
checker = Checker(configuration_schema)
|
|
550
|
+
checker.validate(cfg)
|
|
551
|
+
|
|
552
|
+
return cfg
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def overload_pandora_conf_with_confidence(conf, confidence_conf):
|
|
556
|
+
"""
|
|
557
|
+
Overload pandora pipeline configuration with given confidence to add
|
|
558
|
+
just before disparity computation.
|
|
559
|
+
|
|
560
|
+
:param conf: current pandora configuration
|
|
561
|
+
:type conf: OrderedDict
|
|
562
|
+
:param confidence_conf: confidence applications config
|
|
563
|
+
:type confidence_conf: OrderedDict
|
|
564
|
+
|
|
565
|
+
:return: updated pandora pipeline conf
|
|
566
|
+
:rtype: OrderedDict
|
|
567
|
+
"""
|
|
568
|
+
|
|
569
|
+
out_dict = OrderedDict()
|
|
570
|
+
out_dict.update(conf)
|
|
571
|
+
|
|
572
|
+
conf_keys = list(conf.keys())
|
|
573
|
+
confidence_conf_keys = list(confidence_conf.keys())
|
|
574
|
+
|
|
575
|
+
for key in confidence_conf_keys:
|
|
576
|
+
if key in conf_keys:
|
|
577
|
+
logging.info("{} pandora key already in configuration".format(key))
|
|
578
|
+
|
|
579
|
+
# update confidence
|
|
580
|
+
out_dict.update(confidence_conf)
|
|
581
|
+
|
|
582
|
+
# move confidence keys right before disparity computation
|
|
583
|
+
|
|
584
|
+
# get position of key "disparity"
|
|
585
|
+
if "disparity" not in conf_keys:
|
|
586
|
+
raise RuntimeError("disparity key not in pandora configuration")
|
|
587
|
+
disp_index = conf_keys.index("disparity")
|
|
588
|
+
|
|
589
|
+
# move to end every key from disparity
|
|
590
|
+
for ind in range(disp_index, len(conf_keys)):
|
|
591
|
+
out_dict.move_to_end(conf_keys[ind])
|
|
592
|
+
|
|
593
|
+
return out_dict
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
|
|
5
|
+
#
|
|
6
|
+
# This file is part of CARS
|
|
7
|
+
# (see https://github.com/CNES/cars).
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
"""
|
|
22
|
+
CARS dsm filling module init file
|
|
23
|
+
"""
|
|
24
|
+
# flake8: noqa: F401
|
|
25
|
+
|
|
26
|
+
from cars.applications.dsm_filling.abstract_dsm_filling_app import DsmFilling
|
|
27
|
+
|
|
28
|
+
from . import (
|
|
29
|
+
border_interpolation_app,
|
|
30
|
+
bulldozer_filling_app,
|
|
31
|
+
exogenous_filling_app,
|
|
32
|
+
)
|