cars 1.0.0rc3__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
- cars/__init__.py +74 -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 +46 -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.cpython-313-x86_64-linux-gnu.so +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 +1130 -0
- cars/core/geometry/shareloc_geometry.py +604 -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 +1095 -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 +190 -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 +435 -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.0rc3.dist-info/METADATA +289 -0
- cars-1.0.0rc3.dist-info/RECORD +220 -0
- cars-1.0.0rc3.dist-info/WHEEL +6 -0
- cars-1.0.0rc3.dist-info/entry_points.txt +8 -0
|
@@ -0,0 +1,639 @@
|
|
|
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
|
+
# pylint: disable=too-many-lines
|
|
21
|
+
"""
|
|
22
|
+
CARS dsm inputs
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import collections
|
|
26
|
+
import logging
|
|
27
|
+
import os
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
import rasterio
|
|
31
|
+
import xarray as xr
|
|
32
|
+
from affine import Affine
|
|
33
|
+
from json_checker import Checker
|
|
34
|
+
from rasterio.windows import from_bounds
|
|
35
|
+
|
|
36
|
+
# CARS imports
|
|
37
|
+
import cars.orchestrator.orchestrator as ocht
|
|
38
|
+
from cars.applications.rasterization.rasterization_wrappers import (
|
|
39
|
+
update_data,
|
|
40
|
+
update_weights,
|
|
41
|
+
)
|
|
42
|
+
from cars.core import constants as cst
|
|
43
|
+
from cars.core import inputs, preprocessing, tiling
|
|
44
|
+
from cars.core.utils import safe_makedirs
|
|
45
|
+
from cars.data_structures import cars_dataset
|
|
46
|
+
|
|
47
|
+
from .abstract_dsm_merging_app import DsmMerging
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class WeightedFusion(DsmMerging, short_name="weighted_fusion"):
|
|
51
|
+
"""
|
|
52
|
+
DSM merging app
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, conf=None):
|
|
56
|
+
"""
|
|
57
|
+
Init function of BulldozerFilling
|
|
58
|
+
|
|
59
|
+
:param conf: configuration for BulldozerFilling
|
|
60
|
+
:return: an application_to_use object
|
|
61
|
+
"""
|
|
62
|
+
super().__init__(conf=conf)
|
|
63
|
+
|
|
64
|
+
# check conf
|
|
65
|
+
self.used_method = self.used_config["method"]
|
|
66
|
+
self.tile_size = self.used_config["tile_size"]
|
|
67
|
+
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
68
|
+
|
|
69
|
+
def check_conf(self, conf):
|
|
70
|
+
|
|
71
|
+
# init conf
|
|
72
|
+
if conf is not None:
|
|
73
|
+
overloaded_conf = conf.copy()
|
|
74
|
+
else:
|
|
75
|
+
conf = {}
|
|
76
|
+
overloaded_conf = {}
|
|
77
|
+
|
|
78
|
+
# Overload conf
|
|
79
|
+
overloaded_conf["method"] = conf.get("method", "weighted_fusion")
|
|
80
|
+
overloaded_conf["tile_size"] = conf.get("tile_size", 4000)
|
|
81
|
+
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
82
|
+
"save_intermediate_data", False
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
rectification_schema = {
|
|
86
|
+
"method": str,
|
|
87
|
+
"tile_size": int,
|
|
88
|
+
"save_intermediate_data": bool,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Check conf
|
|
92
|
+
checker = Checker(rectification_schema)
|
|
93
|
+
checker.validate(overloaded_conf)
|
|
94
|
+
|
|
95
|
+
return overloaded_conf
|
|
96
|
+
|
|
97
|
+
# pylint: disable=too-many-positional-arguments
|
|
98
|
+
def run( # noqa: C901
|
|
99
|
+
self,
|
|
100
|
+
dict_path,
|
|
101
|
+
orchestrator,
|
|
102
|
+
roi_poly,
|
|
103
|
+
dump_dir=None,
|
|
104
|
+
dsm_file_name=None,
|
|
105
|
+
color_file_name=None,
|
|
106
|
+
classif_file_name=None,
|
|
107
|
+
filling_file_name=None,
|
|
108
|
+
performance_map_file_name=None,
|
|
109
|
+
ambiguity_file_name=None,
|
|
110
|
+
contributing_pair_file_name=None,
|
|
111
|
+
):
|
|
112
|
+
"""
|
|
113
|
+
Merge all the dsms
|
|
114
|
+
|
|
115
|
+
:param dict_path: path of all variables from all dsms
|
|
116
|
+
:type dict_path: dict
|
|
117
|
+
:param orchestrator: orchestrator used
|
|
118
|
+
:param dump_dir: output path
|
|
119
|
+
:type dump_dir: str
|
|
120
|
+
:param dsm_file_name: name of the dsm output file
|
|
121
|
+
:type dsm_file_name: str
|
|
122
|
+
:param color_file_name: name of the color output file
|
|
123
|
+
:type color_file_name: str
|
|
124
|
+
:param classif_file_name: name of the classif output file
|
|
125
|
+
:type classif_file_name: str
|
|
126
|
+
:param filling_file_name: name of the filling output file
|
|
127
|
+
:type filling_file_name: str
|
|
128
|
+
:param performance_map_file_name: name of the performance_map file
|
|
129
|
+
:type performance_map_file_name: str
|
|
130
|
+
:param ambiguity_file_name: name of the ambiguity output file
|
|
131
|
+
:type ambiguity_file_name: str
|
|
132
|
+
:param contributing_pair_file_name: name of contributing_pair file
|
|
133
|
+
:type contributing_pair_file_name: str
|
|
134
|
+
|
|
135
|
+
:return: raster DSM. CarsDataset contains:
|
|
136
|
+
|
|
137
|
+
- Z x W Delayed tiles. \
|
|
138
|
+
Each tile will be a future xarray Dataset containing:
|
|
139
|
+
|
|
140
|
+
- data : with keys : "hgt", "img", "raster_msk",optional : \
|
|
141
|
+
"n_pts", "pts_in_cell", "hgt_mean", "hgt_stdev",\
|
|
142
|
+
"hgt_inf", "hgt_sup"
|
|
143
|
+
- attrs with keys: "epsg"
|
|
144
|
+
- attributes containing: None
|
|
145
|
+
|
|
146
|
+
:rtype : CarsDataset filled with xr.Dataset
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
# Create CarsDataset
|
|
150
|
+
terrain_raster = cars_dataset.CarsDataset(
|
|
151
|
+
"arrays", name="rasterization"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# find the global bounds of the dataset
|
|
155
|
+
dsm_nodata = None
|
|
156
|
+
epsg = None
|
|
157
|
+
resolution = None
|
|
158
|
+
for index, path in enumerate(dict_path["dsm"]):
|
|
159
|
+
with rasterio.open(path) as src:
|
|
160
|
+
if index == 0:
|
|
161
|
+
bounds = src.bounds
|
|
162
|
+
global_bounds = bounds
|
|
163
|
+
profile = src.profile
|
|
164
|
+
transform = list(profile["transform"])
|
|
165
|
+
res_x = transform[0]
|
|
166
|
+
res_y = transform[4]
|
|
167
|
+
resolution = (res_y, res_x)
|
|
168
|
+
|
|
169
|
+
epsg = src.crs
|
|
170
|
+
|
|
171
|
+
dsm_nodata = src.nodata
|
|
172
|
+
else:
|
|
173
|
+
bounds = src.bounds
|
|
174
|
+
global_bounds = (
|
|
175
|
+
min(bounds[0], global_bounds[0]), # xmin
|
|
176
|
+
min(bounds[1], global_bounds[1]), # ymin
|
|
177
|
+
max(bounds[2], global_bounds[2]), # xmax
|
|
178
|
+
max(bounds[3], global_bounds[3]), # ymax
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if roi_poly is not None:
|
|
182
|
+
global_bounds = preprocessing.crop_terrain_bounds_with_roi(
|
|
183
|
+
roi_poly,
|
|
184
|
+
global_bounds[0],
|
|
185
|
+
global_bounds[1],
|
|
186
|
+
global_bounds[2],
|
|
187
|
+
global_bounds[3],
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Tiling of the dataset
|
|
191
|
+
[xmin, ymin, xmax, ymax] = global_bounds
|
|
192
|
+
|
|
193
|
+
terrain_raster.tiling_grid = tiling.generate_tiling_grid(
|
|
194
|
+
xmin,
|
|
195
|
+
ymin,
|
|
196
|
+
xmax,
|
|
197
|
+
ymax,
|
|
198
|
+
self.tile_size,
|
|
199
|
+
self.tile_size,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
xsize, ysize = tiling.roi_to_start_and_size(
|
|
203
|
+
global_bounds, resolution[1]
|
|
204
|
+
)[2:]
|
|
205
|
+
|
|
206
|
+
# build the tranform of the dataset
|
|
207
|
+
# Generate profile
|
|
208
|
+
geotransform = (
|
|
209
|
+
global_bounds[0],
|
|
210
|
+
resolution[1],
|
|
211
|
+
0.0,
|
|
212
|
+
global_bounds[3],
|
|
213
|
+
0.0,
|
|
214
|
+
-resolution[1],
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
transform = Affine.from_gdal(*geotransform)
|
|
218
|
+
raster_profile = collections.OrderedDict(
|
|
219
|
+
{
|
|
220
|
+
"height": ysize,
|
|
221
|
+
"width": xsize,
|
|
222
|
+
"driver": "GTiff",
|
|
223
|
+
"dtype": "float32",
|
|
224
|
+
"transform": transform,
|
|
225
|
+
"crs": "EPSG:{}".format(epsg),
|
|
226
|
+
"tiled": True,
|
|
227
|
+
"no_data": dsm_nodata,
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
# Get sources pc
|
|
232
|
+
full_sources_band_descriptions = None
|
|
233
|
+
if cst.DSM_SOURCE_PC in list(dict_path.keys()):
|
|
234
|
+
full_sources_band_descriptions = []
|
|
235
|
+
for source_pc in dict_path[cst.DSM_SOURCE_PC]:
|
|
236
|
+
full_sources_band_descriptions += list(
|
|
237
|
+
inputs.get_descriptions_bands(source_pc)
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# remove copies
|
|
241
|
+
full_sources_band_descriptions = list(
|
|
242
|
+
dict.fromkeys(full_sources_band_descriptions)
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Setup dump directory
|
|
246
|
+
if dump_dir is not None:
|
|
247
|
+
out_dump_dir = dump_dir
|
|
248
|
+
safe_makedirs(out_dump_dir)
|
|
249
|
+
else:
|
|
250
|
+
out_dump_dir = orchestrator.out_dir
|
|
251
|
+
|
|
252
|
+
if dsm_file_name is not None:
|
|
253
|
+
safe_makedirs(os.path.dirname(dsm_file_name))
|
|
254
|
+
|
|
255
|
+
# Save all file that are in inputs
|
|
256
|
+
for key in dict_path.keys():
|
|
257
|
+
if key in (cst.DSM_ALT, cst.DSM_COLOR, cst.DSM_WEIGHTS_SUM):
|
|
258
|
+
option = False
|
|
259
|
+
else:
|
|
260
|
+
option = True
|
|
261
|
+
|
|
262
|
+
if key == cst.DSM_ALT and dsm_file_name is not None:
|
|
263
|
+
out_file_name = dsm_file_name
|
|
264
|
+
elif key == cst.DSM_COLOR and color_file_name is not None:
|
|
265
|
+
out_file_name = color_file_name
|
|
266
|
+
elif key == cst.DSM_CLASSIF and classif_file_name is not None:
|
|
267
|
+
out_file_name = classif_file_name
|
|
268
|
+
elif key == cst.DSM_FILLING and filling_file_name is not None:
|
|
269
|
+
out_file_name = filling_file_name
|
|
270
|
+
elif (
|
|
271
|
+
key == cst.DSM_PERFORMANCE_MAP
|
|
272
|
+
and performance_map_file_name is not None
|
|
273
|
+
):
|
|
274
|
+
out_file_name = performance_map_file_name
|
|
275
|
+
elif key == cst.DSM_AMBIGUITY and ambiguity_file_name is not None:
|
|
276
|
+
out_file_name = ambiguity_file_name
|
|
277
|
+
elif (
|
|
278
|
+
key == cst.DSM_SOURCE_PC
|
|
279
|
+
and contributing_pair_file_name is not None
|
|
280
|
+
):
|
|
281
|
+
out_file_name = contributing_pair_file_name
|
|
282
|
+
else:
|
|
283
|
+
out_file_name = os.path.join(out_dump_dir, key + ".tif")
|
|
284
|
+
|
|
285
|
+
orchestrator.add_to_save_lists(
|
|
286
|
+
out_file_name,
|
|
287
|
+
key,
|
|
288
|
+
terrain_raster,
|
|
289
|
+
dtype=inputs.rasterio_get_dtype(dict_path[key][0]),
|
|
290
|
+
nodata=inputs.rasterio_get_nodata(dict_path[key][0]),
|
|
291
|
+
cars_ds_name=key,
|
|
292
|
+
optional_data=option,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
[saving_info] = orchestrator.get_saving_infos([terrain_raster])
|
|
296
|
+
logging.info(
|
|
297
|
+
"Merge DSM info in {} x {} tiles".format(
|
|
298
|
+
terrain_raster.shape[0], terrain_raster.shape[1]
|
|
299
|
+
)
|
|
300
|
+
)
|
|
301
|
+
for col in range(terrain_raster.shape[1]):
|
|
302
|
+
for row in range(terrain_raster.shape[0]):
|
|
303
|
+
# update saving infos for potential replacement
|
|
304
|
+
full_saving_info = ocht.update_saving_infos(
|
|
305
|
+
saving_info, row=row, col=col
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
# Delayed call to dsm merging operations using all
|
|
309
|
+
terrain_raster[row, col] = orchestrator.cluster.create_task(
|
|
310
|
+
dsm_merging_wrapper, nout=1
|
|
311
|
+
)(
|
|
312
|
+
dict_path,
|
|
313
|
+
terrain_raster.tiling_grid[row, col],
|
|
314
|
+
resolution,
|
|
315
|
+
raster_profile,
|
|
316
|
+
full_saving_info,
|
|
317
|
+
full_sources_band_descriptions,
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
return terrain_raster
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def dsm_merging_wrapper( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
324
|
+
dict_path,
|
|
325
|
+
tile_bounds,
|
|
326
|
+
resolution,
|
|
327
|
+
profile,
|
|
328
|
+
saving_info=None,
|
|
329
|
+
full_sources_band_descriptions=None,
|
|
330
|
+
):
|
|
331
|
+
"""
|
|
332
|
+
Merge all the variables
|
|
333
|
+
|
|
334
|
+
:param dict_path: path of all variables from all dsms
|
|
335
|
+
:type dict_path: dict
|
|
336
|
+
:param tile_bounds: list of tiles coordinates
|
|
337
|
+
:type tile_bounds: list
|
|
338
|
+
:param resolution: resolution of the dsms
|
|
339
|
+
:type resolution: list
|
|
340
|
+
:param profile: profile of the global dsm
|
|
341
|
+
:type profile: OrderedDict
|
|
342
|
+
:saving_info: the saving infos
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
# create the tile dataset
|
|
346
|
+
x_value = np.arange(tile_bounds[0], tile_bounds[1], resolution[1])
|
|
347
|
+
y_value = np.arange(tile_bounds[2], tile_bounds[3], resolution[1])
|
|
348
|
+
height = len(y_value)
|
|
349
|
+
width = len(x_value)
|
|
350
|
+
|
|
351
|
+
dataset = xr.Dataset(
|
|
352
|
+
data_vars={},
|
|
353
|
+
coords={
|
|
354
|
+
"y": y_value,
|
|
355
|
+
"x": x_value,
|
|
356
|
+
},
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# calculate the bounds intersection between each path
|
|
360
|
+
list_intersection = []
|
|
361
|
+
|
|
362
|
+
for path in dict_path["dsm"]:
|
|
363
|
+
with rasterio.open(path) as src:
|
|
364
|
+
intersect_bounds = (
|
|
365
|
+
max(tile_bounds[0], src.bounds.left), # xmin
|
|
366
|
+
max(tile_bounds[2], src.bounds.bottom), # ymin
|
|
367
|
+
min(tile_bounds[1], src.bounds.right), # xmax
|
|
368
|
+
min(tile_bounds[3], src.bounds.top), # ymax
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if (
|
|
372
|
+
intersect_bounds[0] < intersect_bounds[2]
|
|
373
|
+
and intersect_bounds[1] < intersect_bounds[3]
|
|
374
|
+
):
|
|
375
|
+
list_intersection.append(intersect_bounds)
|
|
376
|
+
else:
|
|
377
|
+
list_intersection.append("no intersection")
|
|
378
|
+
|
|
379
|
+
# Update the data
|
|
380
|
+
for key in dict_path.keys():
|
|
381
|
+
# Choose the method regarding the variable
|
|
382
|
+
if key in [cst.DSM_NB_PTS, cst.DSM_NB_PTS_IN_CELL]:
|
|
383
|
+
method = "sum"
|
|
384
|
+
elif key in [
|
|
385
|
+
cst.DSM_SOURCE_PC,
|
|
386
|
+
]:
|
|
387
|
+
method = "bool"
|
|
388
|
+
elif key in [
|
|
389
|
+
cst.DSM_FILLING,
|
|
390
|
+
cst.DSM_CLASSIF,
|
|
391
|
+
]:
|
|
392
|
+
method = "max"
|
|
393
|
+
else:
|
|
394
|
+
method = "basic"
|
|
395
|
+
|
|
396
|
+
# take band description information
|
|
397
|
+
band_descriptions = list(
|
|
398
|
+
inputs.get_descriptions_bands(dict_path[key][0])
|
|
399
|
+
)
|
|
400
|
+
nb_bands = inputs.rasterio_get_nb_bands(dict_path[key][0])
|
|
401
|
+
if len(band_descriptions) == 0:
|
|
402
|
+
band_descriptions = []
|
|
403
|
+
elif (
|
|
404
|
+
key
|
|
405
|
+
in [
|
|
406
|
+
cst.DSM_COLOR,
|
|
407
|
+
cst.DSM_SOURCE_PC,
|
|
408
|
+
]
|
|
409
|
+
and None in band_descriptions
|
|
410
|
+
):
|
|
411
|
+
band_descriptions = [
|
|
412
|
+
str(current_band) for current_band in range(nb_bands)
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
# Define the dimension of the data in the dataset
|
|
416
|
+
if key == cst.DSM_COLOR:
|
|
417
|
+
dataset.coords[cst.BAND_IM] = (cst.BAND_IM, band_descriptions)
|
|
418
|
+
dim = [cst.BAND_IM, cst.Y, cst.X]
|
|
419
|
+
elif key == cst.DSM_SOURCE_PC:
|
|
420
|
+
dataset.coords[cst.BAND_SOURCE_PC] = (
|
|
421
|
+
cst.BAND_SOURCE_PC,
|
|
422
|
+
full_sources_band_descriptions,
|
|
423
|
+
)
|
|
424
|
+
dim = [cst.BAND_SOURCE_PC, cst.Y, cst.X]
|
|
425
|
+
else:
|
|
426
|
+
dim = [cst.Y, cst.X]
|
|
427
|
+
|
|
428
|
+
# Update data
|
|
429
|
+
if key == cst.DSM_ALT:
|
|
430
|
+
# Update dsm_value and weights once
|
|
431
|
+
value, weights = assemblage(
|
|
432
|
+
dict_path[key],
|
|
433
|
+
dict_path[cst.DSM_WEIGHTS_SUM],
|
|
434
|
+
method,
|
|
435
|
+
list_intersection,
|
|
436
|
+
tile_bounds,
|
|
437
|
+
height,
|
|
438
|
+
width,
|
|
439
|
+
band_descriptions,
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
dataset[key] = (dim, value)
|
|
443
|
+
dataset[cst.DSM_WEIGHTS_SUM] = (dim, weights)
|
|
444
|
+
elif key == cst.DSM_SOURCE_PC:
|
|
445
|
+
value, _ = assemblage(
|
|
446
|
+
dict_path[key],
|
|
447
|
+
dict_path[cst.DSM_WEIGHTS_SUM],
|
|
448
|
+
method,
|
|
449
|
+
list_intersection,
|
|
450
|
+
tile_bounds,
|
|
451
|
+
height,
|
|
452
|
+
width,
|
|
453
|
+
full_sources_band_descriptions,
|
|
454
|
+
merge_sources=True,
|
|
455
|
+
)
|
|
456
|
+
dataset[key] = (dim, value)
|
|
457
|
+
elif key != cst.DSM_WEIGHTS_SUM:
|
|
458
|
+
# Update other variables
|
|
459
|
+
value, _ = assemblage(
|
|
460
|
+
dict_path[key],
|
|
461
|
+
dict_path[cst.DSM_WEIGHTS_SUM],
|
|
462
|
+
method,
|
|
463
|
+
list_intersection,
|
|
464
|
+
tile_bounds,
|
|
465
|
+
height,
|
|
466
|
+
width,
|
|
467
|
+
band_descriptions,
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
dataset[key] = (dim, value)
|
|
471
|
+
|
|
472
|
+
# add performance map classes
|
|
473
|
+
if key == cst.DSM_PERFORMANCE_MAP:
|
|
474
|
+
perf_map_classes = inputs.rasterio_get_tags(dict_path[key][0])[
|
|
475
|
+
"CLASSES"
|
|
476
|
+
]
|
|
477
|
+
dataset.attrs[cst.RIO_TAG_PERFORMANCE_MAP_CLASSES] = (
|
|
478
|
+
perf_map_classes
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
# Define the tile transform
|
|
482
|
+
bounds = [tile_bounds[0], tile_bounds[2], tile_bounds[1], tile_bounds[3]]
|
|
483
|
+
xstart, ystart, xsize, ysize = tiling.roi_to_start_and_size(
|
|
484
|
+
bounds, resolution[1]
|
|
485
|
+
)
|
|
486
|
+
transform = rasterio.Affine(*profile["transform"][0:6])
|
|
487
|
+
|
|
488
|
+
row_pix_pos, col_pix_pos = rasterio.transform.AffineTransformer(
|
|
489
|
+
transform
|
|
490
|
+
).rowcol(xstart, ystart)
|
|
491
|
+
window = [
|
|
492
|
+
row_pix_pos,
|
|
493
|
+
row_pix_pos + ysize,
|
|
494
|
+
col_pix_pos,
|
|
495
|
+
col_pix_pos + xsize,
|
|
496
|
+
]
|
|
497
|
+
|
|
498
|
+
window = cars_dataset.window_array_to_dict(window)
|
|
499
|
+
|
|
500
|
+
# Fill dataset
|
|
501
|
+
cars_dataset.fill_dataset(
|
|
502
|
+
dataset,
|
|
503
|
+
saving_info=saving_info,
|
|
504
|
+
window=window,
|
|
505
|
+
profile=profile,
|
|
506
|
+
overlaps=None,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
return dataset
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def assemblage( # pylint: disable=too-many-positional-arguments
|
|
513
|
+
out,
|
|
514
|
+
current_weights,
|
|
515
|
+
method,
|
|
516
|
+
intersect_bounds,
|
|
517
|
+
tile_bounds,
|
|
518
|
+
height,
|
|
519
|
+
width,
|
|
520
|
+
band_descriptions=None,
|
|
521
|
+
merge_sources=False,
|
|
522
|
+
):
|
|
523
|
+
"""
|
|
524
|
+
Update data
|
|
525
|
+
|
|
526
|
+
:param out: the data to update
|
|
527
|
+
:type out: list of path
|
|
528
|
+
:param current_weights: the current weights of the data
|
|
529
|
+
:type current_weights: list of path
|
|
530
|
+
:param method: the method used to update the data
|
|
531
|
+
:type method: str
|
|
532
|
+
:param intersect_bounds: the bounds intersection
|
|
533
|
+
:type intersect_bounds: list of bounds
|
|
534
|
+
:param height: the height of the tile
|
|
535
|
+
:type height: int
|
|
536
|
+
:param width: the width of the tile
|
|
537
|
+
:type width: int
|
|
538
|
+
:param band_descriptions: the band description of the data
|
|
539
|
+
:type band_descriptions: str of list
|
|
540
|
+
:param merge_sources: merge source pc, using full band_description
|
|
541
|
+
:type merge_sources: bool
|
|
542
|
+
|
|
543
|
+
"""
|
|
544
|
+
# Initialize the tile
|
|
545
|
+
if merge_sources:
|
|
546
|
+
nb_bands = len(band_descriptions)
|
|
547
|
+
else:
|
|
548
|
+
nb_bands = inputs.rasterio_get_nb_bands(out[0])
|
|
549
|
+
dtype = inputs.rasterio_get_dtype(out[0])
|
|
550
|
+
nodata = inputs.rasterio_get_nodata(out[0])
|
|
551
|
+
|
|
552
|
+
if band_descriptions[0] is not None:
|
|
553
|
+
tile = np.full((nb_bands, height, width), nodata, dtype=dtype)
|
|
554
|
+
else:
|
|
555
|
+
tile = np.full((height, width), nodata, dtype=dtype)
|
|
556
|
+
|
|
557
|
+
# Initialize the weights
|
|
558
|
+
weights = np.full((height, width), 0, dtype=dtype)
|
|
559
|
+
|
|
560
|
+
for idx, path in enumerate(out):
|
|
561
|
+
with (
|
|
562
|
+
rasterio.open(path) as src,
|
|
563
|
+
rasterio.open(current_weights[idx]) as drt,
|
|
564
|
+
):
|
|
565
|
+
if intersect_bounds[idx] != "no intersection":
|
|
566
|
+
# Build the window
|
|
567
|
+
window = from_bounds(
|
|
568
|
+
*intersect_bounds[idx], transform=src.transform
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
# Extract the data
|
|
572
|
+
current_nb_bands = src.count
|
|
573
|
+
if current_nb_bands > 1:
|
|
574
|
+
data = src.read(window=window)
|
|
575
|
+
_, rows, cols = data.shape
|
|
576
|
+
else:
|
|
577
|
+
data = src.read(1, window=window)
|
|
578
|
+
rows, cols = data.shape
|
|
579
|
+
|
|
580
|
+
indexes = list(range(current_nb_bands))
|
|
581
|
+
if merge_sources:
|
|
582
|
+
# Extract current band description
|
|
583
|
+
current_band_descriptions = list(src.descriptions)
|
|
584
|
+
# Get position
|
|
585
|
+
indexes = []
|
|
586
|
+
for current_band in current_band_descriptions:
|
|
587
|
+
indexes.append(band_descriptions.index(current_band))
|
|
588
|
+
|
|
589
|
+
current_weights_window = drt.read(1, window=window)
|
|
590
|
+
|
|
591
|
+
# Calculate the x and y offset because the current_data
|
|
592
|
+
# doesn't equal to the entire tile
|
|
593
|
+
x_offset = int(
|
|
594
|
+
(intersect_bounds[idx][0] - tile_bounds[0])
|
|
595
|
+
/ np.abs(src.res[0])
|
|
596
|
+
)
|
|
597
|
+
y_offset = int(
|
|
598
|
+
(tile_bounds[3] - intersect_bounds[idx][3])
|
|
599
|
+
/ np.abs(src.res[1])
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
if cols > 0 and rows > 0:
|
|
603
|
+
tab_x = np.arange(x_offset, x_offset + cols)
|
|
604
|
+
|
|
605
|
+
tab_y = np.arange(y_offset, y_offset + rows)
|
|
606
|
+
|
|
607
|
+
# Update data
|
|
608
|
+
if band_descriptions[0] is not None:
|
|
609
|
+
|
|
610
|
+
tile[np.ix_(indexes, tab_y, tab_x)] = np.reshape(
|
|
611
|
+
update_data(
|
|
612
|
+
tile[np.ix_(indexes, tab_y, tab_x)],
|
|
613
|
+
data,
|
|
614
|
+
current_weights_window,
|
|
615
|
+
weights[np.ix_(tab_y, tab_x)],
|
|
616
|
+
nodata,
|
|
617
|
+
method=method,
|
|
618
|
+
),
|
|
619
|
+
tile[np.ix_(indexes, tab_y, tab_x)].shape,
|
|
620
|
+
)
|
|
621
|
+
else:
|
|
622
|
+
tile[np.ix_(tab_y, tab_x)] = np.reshape(
|
|
623
|
+
update_data(
|
|
624
|
+
tile[np.ix_(tab_y, tab_x)],
|
|
625
|
+
data,
|
|
626
|
+
current_weights_window,
|
|
627
|
+
weights[np.ix_(tab_y, tab_x)],
|
|
628
|
+
nodata,
|
|
629
|
+
method=method,
|
|
630
|
+
),
|
|
631
|
+
tile[np.ix_(tab_y, tab_x)].shape,
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
# Update weights
|
|
635
|
+
weights[np.ix_(tab_y, tab_x)] = update_weights(
|
|
636
|
+
weights[np.ix_(tab_y, tab_x)], current_weights_window
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
return tile, weights
|
|
@@ -0,0 +1,30 @@
|
|
|
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 grid_correction module init file
|
|
23
|
+
"""
|
|
24
|
+
# flake8: noqa: F401
|
|
25
|
+
|
|
26
|
+
from cars.applications.grid_correction.abstract_grid_correction_app import (
|
|
27
|
+
GridCorrection,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from . import grid_correction_app
|