cars 1.0.0rc1__cp313-cp313-musllinux_1_2_i686.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 +74 -0
- cars/applications/__init__.py +37 -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 +104 -0
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -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 +655 -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 +1460 -0
- cars/applications/dense_matching/cpp/__init__.py +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-313-i386-linux-musl.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 +588 -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 +270 -0
- cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
- cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
- cars/applications/dsm_filling/exogenous_filling_app.py +333 -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_correction_app.py +496 -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 +527 -0
- cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -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 +634 -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 +762 -0
- cars/applications/resampling/resampling_algo.py +614 -0
- cars/applications/resampling/resampling_constants.py +36 -0
- cars/applications/resampling/resampling_wrappers.py +309 -0
- cars/applications/sparse_matching/__init__.py +30 -0
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
- cars/applications/sparse_matching/sift_app.py +735 -0
- cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
- cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
- cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -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 +757 -0
- cars/cars.py +177 -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 +1541 -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 +244 -0
- cars/orchestrator/cluster/abstract_dask_cluster.py +375 -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 +1075 -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 +873 -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/orchestrator.py +905 -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 +2 -0
- cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
- cars/pipelines/default/__init__.py +26 -0
- cars/pipelines/default/default_pipeline.py +786 -0
- cars/pipelines/parameters/__init__.py +0 -0
- cars/pipelines/parameters/advanced_parameters.py +417 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -0
- cars/pipelines/parameters/dsm_inputs.py +918 -0
- cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
- cars/pipelines/parameters/output_constants.py +52 -0
- cars/pipelines/parameters/output_parameters.py +454 -0
- cars/pipelines/parameters/sensor_inputs.py +842 -0
- cars/pipelines/parameters/sensor_inputs_constants.py +49 -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 +31 -0
- cars/pipelines/pipeline_template.py +139 -0
- cars/pipelines/unit/__init__.py +26 -0
- cars/pipelines/unit/unit_pipeline.py +2850 -0
- cars/starter.py +167 -0
- cars-1.0.0rc1.dist-info/METADATA +292 -0
- cars-1.0.0rc1.dist-info/RECORD +202 -0
- cars-1.0.0rc1.dist-info/WHEEL +5 -0
- cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
- cars.libs/libgcc_s-1257a076.so.1 +0 -0
- cars.libs/libstdc++-0530927c.so.6.0.32 +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
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
|
+
This module contains the exogenous dsm filling application class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import logging
|
|
26
|
+
import os
|
|
27
|
+
import shutil
|
|
28
|
+
import warnings
|
|
29
|
+
|
|
30
|
+
import numpy as np
|
|
31
|
+
import rasterio as rio
|
|
32
|
+
from json_checker import Checker, Or
|
|
33
|
+
from pyproj import CRS
|
|
34
|
+
from rasterio.enums import Resampling
|
|
35
|
+
from rasterio.errors import NodataShadowWarning
|
|
36
|
+
from rasterio.warp import reproject
|
|
37
|
+
from shapely import Polygon
|
|
38
|
+
|
|
39
|
+
from cars.core import inputs, projection
|
|
40
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
41
|
+
|
|
42
|
+
from .abstract_dsm_filling_app import DsmFilling
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
|
|
46
|
+
"""
|
|
47
|
+
Exogenous filling
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, conf=None):
|
|
51
|
+
"""
|
|
52
|
+
Init function of ExogenousFilling
|
|
53
|
+
|
|
54
|
+
:param conf: configuration for ExogenousFilling
|
|
55
|
+
:return: an application_to_use object
|
|
56
|
+
"""
|
|
57
|
+
super().__init__(conf=conf)
|
|
58
|
+
|
|
59
|
+
# check conf
|
|
60
|
+
self.used_method = self.used_config["method"]
|
|
61
|
+
self.classification = self.used_config["classification"]
|
|
62
|
+
self.fill_with_geoid = self.used_config["fill_with_geoid"]
|
|
63
|
+
self.interpolation_method = self.used_config["interpolation_method"]
|
|
64
|
+
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
65
|
+
|
|
66
|
+
def check_conf(self, conf):
|
|
67
|
+
|
|
68
|
+
# init conf
|
|
69
|
+
if conf is not None:
|
|
70
|
+
overloaded_conf = conf.copy()
|
|
71
|
+
else:
|
|
72
|
+
conf = {}
|
|
73
|
+
overloaded_conf = {}
|
|
74
|
+
|
|
75
|
+
# Overload conf
|
|
76
|
+
overloaded_conf["method"] = conf.get("method", "exogenous_filling")
|
|
77
|
+
overloaded_conf["classification"] = conf.get("classification", "nodata")
|
|
78
|
+
if isinstance(overloaded_conf["classification"], str):
|
|
79
|
+
overloaded_conf["classification"] = [
|
|
80
|
+
overloaded_conf["classification"]
|
|
81
|
+
]
|
|
82
|
+
overloaded_conf["fill_with_geoid"] = conf.get("fill_with_geoid", None)
|
|
83
|
+
overloaded_conf["interpolation_method"] = conf.get(
|
|
84
|
+
"interpolation_method", "bilinear"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if overloaded_conf["interpolation_method"] not in ["bilinear", "cubic"]:
|
|
88
|
+
# pylint: disable=inconsistent-quotes
|
|
89
|
+
raise RuntimeError(
|
|
90
|
+
f"Invalid interpolation method"
|
|
91
|
+
f"{overloaded_conf['interpolation_method']}, "
|
|
92
|
+
f"supported modes are bilinear and cubic."
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
96
|
+
"save_intermediate_data", False
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
rectification_schema = {
|
|
100
|
+
"method": str,
|
|
101
|
+
"classification": Or(None, [str]),
|
|
102
|
+
"fill_with_geoid": Or(None, [str]),
|
|
103
|
+
"interpolation_method": str,
|
|
104
|
+
"save_intermediate_data": bool,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Check conf
|
|
108
|
+
checker = Checker(rectification_schema)
|
|
109
|
+
checker.validate(overloaded_conf)
|
|
110
|
+
|
|
111
|
+
return overloaded_conf
|
|
112
|
+
|
|
113
|
+
@cars_profile(name="Exogeneous filling")
|
|
114
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
115
|
+
self,
|
|
116
|
+
dsm_file,
|
|
117
|
+
classif_file,
|
|
118
|
+
filling_file,
|
|
119
|
+
dump_dir,
|
|
120
|
+
roi_polys,
|
|
121
|
+
roi_epsg,
|
|
122
|
+
output_geoid,
|
|
123
|
+
geom_plugin,
|
|
124
|
+
):
|
|
125
|
+
"""
|
|
126
|
+
Run dsm filling using initial elevation and the current dsm
|
|
127
|
+
Replaces dsm.tif by the filled dsm. Adds a new band
|
|
128
|
+
to filling.tif if it exists.
|
|
129
|
+
The old dsm is saved in dump_dir.
|
|
130
|
+
|
|
131
|
+
roi_poly can any of these objects :
|
|
132
|
+
- a list of Shapely Polygons
|
|
133
|
+
- a Shapely Polygon
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
if self.classification is None:
|
|
137
|
+
self.classification = ["nodata"]
|
|
138
|
+
|
|
139
|
+
if self.fill_with_geoid is None:
|
|
140
|
+
self.fill_with_geoid = []
|
|
141
|
+
|
|
142
|
+
interpolation_methods_dict = {
|
|
143
|
+
"bilinear": Resampling.bilinear,
|
|
144
|
+
"cubic": Resampling.cubic,
|
|
145
|
+
}
|
|
146
|
+
interpolation_method = interpolation_methods_dict.get(
|
|
147
|
+
self.interpolation_method, Resampling.bilinear
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
if geom_plugin is None:
|
|
151
|
+
logging.error(
|
|
152
|
+
"No DEM was provided, exogenous_filling will not run."
|
|
153
|
+
)
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
if not os.path.exists(dump_dir):
|
|
157
|
+
os.makedirs(dump_dir)
|
|
158
|
+
|
|
159
|
+
old_dsm_path = os.path.join(dump_dir, "dsm_not_filled.tif")
|
|
160
|
+
new_dsm_path = os.path.join(dump_dir, "dsm_filled.tif")
|
|
161
|
+
|
|
162
|
+
# get dsm to be filled and its metadata
|
|
163
|
+
with rio.open(dsm_file) as in_dsm:
|
|
164
|
+
dsm = in_dsm.read(1)
|
|
165
|
+
dsm_tr = in_dsm.transform
|
|
166
|
+
dsm_crs = in_dsm.crs
|
|
167
|
+
dsm_meta = in_dsm.meta
|
|
168
|
+
|
|
169
|
+
roi_raster = np.ones(dsm.shape)
|
|
170
|
+
|
|
171
|
+
if isinstance(roi_polys, list):
|
|
172
|
+
roi_polys_outepsg = []
|
|
173
|
+
for poly in roi_polys:
|
|
174
|
+
if isinstance(poly, Polygon):
|
|
175
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
176
|
+
poly, CRS(roi_epsg), dsm_crs
|
|
177
|
+
)
|
|
178
|
+
roi_polys_outepsg.append(roi_poly_outepsg)
|
|
179
|
+
|
|
180
|
+
roi_raster = rio.features.rasterize(
|
|
181
|
+
roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
|
|
182
|
+
)
|
|
183
|
+
elif isinstance(roi_polys, Polygon):
|
|
184
|
+
roi_poly_outepsg = projection.polygon_projection_crs(
|
|
185
|
+
roi_polys, CRS(roi_epsg), dsm_crs
|
|
186
|
+
)
|
|
187
|
+
roi_raster = rio.features.rasterize(
|
|
188
|
+
[roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Get the initial elevation
|
|
192
|
+
with rio.open(geom_plugin.dem) as in_elev:
|
|
193
|
+
# Reproject the elevation data to match the DSM
|
|
194
|
+
elev_data = np.empty(dsm.shape, dtype=in_elev.dtypes[0])
|
|
195
|
+
|
|
196
|
+
reproject(
|
|
197
|
+
source=rio.band(in_elev, 1),
|
|
198
|
+
destination=elev_data,
|
|
199
|
+
src_transform=in_elev.transform,
|
|
200
|
+
src_crs=in_elev.crs,
|
|
201
|
+
dst_transform=dsm_tr,
|
|
202
|
+
dst_crs=dsm_crs,
|
|
203
|
+
resampling=interpolation_method,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
if self.save_intermediate_data:
|
|
207
|
+
reprojected_dem_path = os.path.join(dump_dir, "reprojected_dem.tif")
|
|
208
|
+
with rio.open(reprojected_dem_path, "w", **dsm_meta) as out_elev:
|
|
209
|
+
out_elev.write(elev_data, 1)
|
|
210
|
+
|
|
211
|
+
with rio.open(geom_plugin.geoid) as in_geoid:
|
|
212
|
+
# Reproject the geoid data to match the DSM
|
|
213
|
+
input_geoid_data = np.empty(dsm.shape, dtype=in_geoid.dtypes[0])
|
|
214
|
+
|
|
215
|
+
reproject(
|
|
216
|
+
source=rio.band(in_geoid, 1),
|
|
217
|
+
destination=input_geoid_data,
|
|
218
|
+
src_transform=in_geoid.transform,
|
|
219
|
+
src_crs=in_geoid.crs,
|
|
220
|
+
dst_transform=dsm_tr,
|
|
221
|
+
dst_crs=dsm_crs,
|
|
222
|
+
resampling=interpolation_method,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
if self.save_intermediate_data:
|
|
226
|
+
reprojected_geoid_path = os.path.join(
|
|
227
|
+
dump_dir, "reprojected_input_geoid.tif"
|
|
228
|
+
)
|
|
229
|
+
with rio.open(reprojected_geoid_path, "w", **dsm_meta) as out_geoid:
|
|
230
|
+
out_geoid.write(input_geoid_data, 1)
|
|
231
|
+
|
|
232
|
+
if isinstance(output_geoid, str):
|
|
233
|
+
with rio.open(output_geoid) as in_geoid:
|
|
234
|
+
# Reproject the geoid data to match the DSM
|
|
235
|
+
output_geoid_data = np.empty(
|
|
236
|
+
dsm.shape, dtype=in_geoid.dtypes[0]
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
reproject(
|
|
240
|
+
source=rio.band(in_geoid, 1),
|
|
241
|
+
destination=output_geoid_data,
|
|
242
|
+
src_transform=in_geoid.transform,
|
|
243
|
+
src_crs=in_geoid.crs,
|
|
244
|
+
dst_transform=dsm_tr,
|
|
245
|
+
dst_crs=dsm_crs,
|
|
246
|
+
resampling=interpolation_method,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
if self.save_intermediate_data:
|
|
250
|
+
reprojected_geoid_path = os.path.join(
|
|
251
|
+
dump_dir, "reprojected_output_geoid.tif"
|
|
252
|
+
)
|
|
253
|
+
with rio.open(
|
|
254
|
+
reprojected_geoid_path, "w", **dsm_meta
|
|
255
|
+
) as out_geoid:
|
|
256
|
+
out_geoid.write(input_geoid_data, 1)
|
|
257
|
+
|
|
258
|
+
# Save old dsm
|
|
259
|
+
if self.save_intermediate_data:
|
|
260
|
+
with rio.open(old_dsm_path, "w", **dsm_meta) as out_dsm:
|
|
261
|
+
out_dsm.write(dsm, 1)
|
|
262
|
+
|
|
263
|
+
# Fill DSM for every label
|
|
264
|
+
combined_mask = np.zeros_like(dsm).astype(np.uint8)
|
|
265
|
+
if classif_file is not None:
|
|
266
|
+
classif_descriptions = inputs.get_descriptions_bands(classif_file)
|
|
267
|
+
else:
|
|
268
|
+
classif_descriptions = []
|
|
269
|
+
for label in self.classification:
|
|
270
|
+
if label in classif_descriptions:
|
|
271
|
+
index_classif = classif_descriptions.index(label) + 1
|
|
272
|
+
with rio.open(classif_file) as in_classif:
|
|
273
|
+
classif = in_classif.read(index_classif)
|
|
274
|
+
classif_msk = in_classif.read_masks(1)
|
|
275
|
+
classif[classif_msk == 0] = 0
|
|
276
|
+
filling_mask = np.logical_and(classif, roi_raster > 0)
|
|
277
|
+
elif label == "nodata":
|
|
278
|
+
if classif_file is not None:
|
|
279
|
+
with rio.open(classif_file) as in_classif:
|
|
280
|
+
with warnings.catch_warnings():
|
|
281
|
+
warnings.simplefilter("ignore", NodataShadowWarning)
|
|
282
|
+
classif_msk = in_classif.read_masks(1)
|
|
283
|
+
classif = ~classif_msk
|
|
284
|
+
else:
|
|
285
|
+
with rio.open(dsm_file) as in_dsm:
|
|
286
|
+
dsm_msk = in_dsm.read_masks(1)
|
|
287
|
+
classif = ~dsm_msk
|
|
288
|
+
filling_mask = np.logical_and(classif, roi_raster > 0)
|
|
289
|
+
else:
|
|
290
|
+
logging.error(
|
|
291
|
+
"Label {} not found in classification "
|
|
292
|
+
"descriptions {}".format(label, classif_descriptions)
|
|
293
|
+
)
|
|
294
|
+
continue
|
|
295
|
+
|
|
296
|
+
if label in self.fill_with_geoid:
|
|
297
|
+
logging.info("Filling of {} with geoid".format(label))
|
|
298
|
+
dsm[filling_mask] = 0
|
|
299
|
+
else:
|
|
300
|
+
logging.info("Filling of {} with DEM and geoid".format(label))
|
|
301
|
+
dsm[filling_mask] = elev_data[filling_mask]
|
|
302
|
+
|
|
303
|
+
# apply offset to project on geoid if needed
|
|
304
|
+
if output_geoid is not True:
|
|
305
|
+
if isinstance(output_geoid, bool) and output_geoid is False:
|
|
306
|
+
# out geoid is ellipsoid: add geoid-ellipsoid distance
|
|
307
|
+
dsm[filling_mask] += input_geoid_data[filling_mask]
|
|
308
|
+
elif isinstance(output_geoid, str):
|
|
309
|
+
# out geoid is a new geoid whose path is in output_geoid:
|
|
310
|
+
# add carsgeoid-ellipsoid then add ellipsoid-outgeoid
|
|
311
|
+
dsm[filling_mask] += input_geoid_data[filling_mask]
|
|
312
|
+
dsm[filling_mask] -= output_geoid_data[filling_mask]
|
|
313
|
+
|
|
314
|
+
combined_mask = np.logical_or(combined_mask, filling_mask)
|
|
315
|
+
|
|
316
|
+
with rio.open(dsm_file, "w", **dsm_meta) as out_dsm:
|
|
317
|
+
out_dsm.write(dsm, 1)
|
|
318
|
+
if self.save_intermediate_data:
|
|
319
|
+
shutil.copy2(dsm_file, new_dsm_path)
|
|
320
|
+
|
|
321
|
+
if filling_file is not None:
|
|
322
|
+
with rio.open(filling_file, "r") as src:
|
|
323
|
+
fill_meta = src.meta
|
|
324
|
+
bands = [src.read(i + 1) for i in range(src.count)]
|
|
325
|
+
bands_desc = [src.descriptions[i] for i in range(src.count)]
|
|
326
|
+
fill_meta["count"] += 1
|
|
327
|
+
bands.append(combined_mask)
|
|
328
|
+
bands_desc.append("filling_exogenous")
|
|
329
|
+
|
|
330
|
+
with rio.open(filling_file, "w", **fill_meta) as out:
|
|
331
|
+
for i, band in enumerate(bands):
|
|
332
|
+
out.write(band, i + 1)
|
|
333
|
+
out.set_band_description(i + 1, bands_desc[i])
|
|
@@ -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_generation module init file
|
|
23
|
+
"""
|
|
24
|
+
# flake8: noqa: F401
|
|
25
|
+
|
|
26
|
+
from cars.applications.grid_generation.abstract_grid_generation_app import (
|
|
27
|
+
GridGeneration,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from . import epipolar_grid_generation_app
|
|
@@ -0,0 +1,142 @@
|
|
|
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
|
+
this module contains the abstract grid generation application class.
|
|
23
|
+
"""
|
|
24
|
+
import logging
|
|
25
|
+
from abc import ABCMeta, abstractmethod
|
|
26
|
+
from typing import Dict
|
|
27
|
+
|
|
28
|
+
from cars.applications.application import Application
|
|
29
|
+
from cars.applications.application_template import ApplicationTemplate
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@Application.register("grid_generation")
|
|
33
|
+
class GridGeneration(ApplicationTemplate, metaclass=ABCMeta):
|
|
34
|
+
"""
|
|
35
|
+
AbstractGridGeneration
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
available_applications: Dict = {}
|
|
39
|
+
default_application = "epipolar"
|
|
40
|
+
|
|
41
|
+
def __new__(cls, conf=None): # pylint: disable=W0613
|
|
42
|
+
"""
|
|
43
|
+
Return the required application
|
|
44
|
+
:raises:
|
|
45
|
+
- KeyError when the required application is not registered
|
|
46
|
+
|
|
47
|
+
:param conf: configuration for grid generation
|
|
48
|
+
:return: a application_to_use object
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
grid_method = cls.default_application
|
|
52
|
+
|
|
53
|
+
if bool(conf) is False or "method" not in conf:
|
|
54
|
+
logging.info(
|
|
55
|
+
"Grid generation method not specified, default "
|
|
56
|
+
" {} is used".format(grid_method)
|
|
57
|
+
)
|
|
58
|
+
else:
|
|
59
|
+
grid_method = conf.get("method", cls.default_application)
|
|
60
|
+
|
|
61
|
+
if grid_method not in cls.available_applications:
|
|
62
|
+
logging.error(
|
|
63
|
+
"No GridGeneration application named {} registered".format(
|
|
64
|
+
grid_method
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
raise KeyError(
|
|
68
|
+
"No GridGeneration application named {} registered".format(
|
|
69
|
+
grid_method
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
logging.info(
|
|
74
|
+
"The GridGeneration({}) application will be used".format(
|
|
75
|
+
grid_method
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return super(GridGeneration, cls).__new__(
|
|
80
|
+
cls.available_applications[grid_method]
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def __init_subclass__(cls, short_name, **kwargs): # pylint: disable=E0302
|
|
84
|
+
super().__init_subclass__(**kwargs)
|
|
85
|
+
cls.available_applications[short_name] = cls
|
|
86
|
+
|
|
87
|
+
def __init__(self, conf=None):
|
|
88
|
+
"""
|
|
89
|
+
Init function of GridGeneration
|
|
90
|
+
|
|
91
|
+
:param conf: configuration
|
|
92
|
+
:return: an application_to_use object
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
super().__init__(conf=conf)
|
|
96
|
+
|
|
97
|
+
@abstractmethod
|
|
98
|
+
def get_save_grids(self):
|
|
99
|
+
"""
|
|
100
|
+
Get whether the grid will be saved
|
|
101
|
+
|
|
102
|
+
:return: true is grid saving is activated
|
|
103
|
+
:rtype: bool
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def run( # pylint: disable=too-many-positional-arguments
|
|
108
|
+
self,
|
|
109
|
+
image_left,
|
|
110
|
+
image_right,
|
|
111
|
+
orchestrator=None,
|
|
112
|
+
pair_folder=None,
|
|
113
|
+
srtm_dir=None,
|
|
114
|
+
default_alt=None,
|
|
115
|
+
geoid_path=None,
|
|
116
|
+
pair_key="PAIR_0",
|
|
117
|
+
):
|
|
118
|
+
"""
|
|
119
|
+
Run EpipolarGridGeneration application
|
|
120
|
+
|
|
121
|
+
Create left and right grid CarsDataset filled with xarray.Dataset ,
|
|
122
|
+
corresponding to left and right epipolar grids.
|
|
123
|
+
|
|
124
|
+
:param image_left: left image
|
|
125
|
+
:type image_left: dict
|
|
126
|
+
:param image_right: right image
|
|
127
|
+
:type image_right: dict
|
|
128
|
+
:param pair_folder: folder used for current pair
|
|
129
|
+
:type pair_folder: str
|
|
130
|
+
:param orchestrator: orchestrator used
|
|
131
|
+
:param srtm_dir: srtm directory
|
|
132
|
+
:type srtm_dir: str
|
|
133
|
+
:param default_alt: default altitude
|
|
134
|
+
:type default_alt: float
|
|
135
|
+
:param geoid_path: geoid path
|
|
136
|
+
:type geoid_path: str
|
|
137
|
+
:param pair_key: pair configuration id
|
|
138
|
+
:type pair_key: str
|
|
139
|
+
|
|
140
|
+
:return: left grid, right grid
|
|
141
|
+
:rtype: Tuple(CarsDataset, CarsDataset)
|
|
142
|
+
"""
|