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,632 @@
|
|
|
1
|
+
# !/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2024 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 AuxiliaryFillingFromSensors application class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
import logging
|
|
26
|
+
import os
|
|
27
|
+
import shutil
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
import rasterio as rio
|
|
31
|
+
import xarray as xr
|
|
32
|
+
from json_checker import Checker
|
|
33
|
+
from pyproj import CRS
|
|
34
|
+
from rasterio.enums import Resampling
|
|
35
|
+
from rasterio.warp import reproject
|
|
36
|
+
from shapely.geometry import Polygon
|
|
37
|
+
|
|
38
|
+
import cars.orchestrator.orchestrator as ocht
|
|
39
|
+
from cars.applications.auxiliary_filling import (
|
|
40
|
+
auxiliary_filling_algo,
|
|
41
|
+
auxiliary_filling_wrappers,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# CARS imports
|
|
45
|
+
from cars.applications.auxiliary_filling.abstract_auxiliary_filling_app import (
|
|
46
|
+
AuxiliaryFilling,
|
|
47
|
+
)
|
|
48
|
+
from cars.core import constants as cst
|
|
49
|
+
from cars.core import inputs, projection, tiling
|
|
50
|
+
from cars.data_structures import cars_dataset
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class AuxiliaryFillingFromSensors(
|
|
54
|
+
AuxiliaryFilling, short_name="auxiliary_filling_from_sensors"
|
|
55
|
+
):
|
|
56
|
+
"""
|
|
57
|
+
AuxiliaryFillingFromSensors Application
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(self, conf=None):
|
|
61
|
+
"""
|
|
62
|
+
Init function of AuxiliaryFillingFromSensors
|
|
63
|
+
|
|
64
|
+
:param conf: configuration for AuxiliaryFillingFromSensors
|
|
65
|
+
:return: an application_to_use object
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
self.orchestrator = None
|
|
69
|
+
|
|
70
|
+
super().__init__(conf=conf)
|
|
71
|
+
|
|
72
|
+
def check_conf(self, conf):
|
|
73
|
+
"""
|
|
74
|
+
Check configuration
|
|
75
|
+
|
|
76
|
+
:param conf: configuration to check
|
|
77
|
+
:type conf: dict
|
|
78
|
+
|
|
79
|
+
:return: overloaded configuration
|
|
80
|
+
:rtype: dict
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
# init conf
|
|
85
|
+
if conf is not None:
|
|
86
|
+
overloaded_conf = conf.copy()
|
|
87
|
+
else:
|
|
88
|
+
conf = {}
|
|
89
|
+
overloaded_conf = {}
|
|
90
|
+
|
|
91
|
+
# Overload conf
|
|
92
|
+
overloaded_conf["method"] = conf.get(
|
|
93
|
+
"method", "auxiliary_filling_from_sensors"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
overloaded_conf["mode"] = conf.get("mode", "fill_nan")
|
|
97
|
+
|
|
98
|
+
if overloaded_conf["mode"] not in ["fill_nan", "full"]:
|
|
99
|
+
# pylint: disable=inconsistent-quotes
|
|
100
|
+
raise RuntimeError(
|
|
101
|
+
f"Invalid mode {overloaded_conf['mode']} for "
|
|
102
|
+
f"AuxiliaryFilling, supported modes are fill_nan "
|
|
103
|
+
f"and full"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
overloaded_conf["texture_interpolator"] = conf.get(
|
|
107
|
+
"texture_interpolator", "linear"
|
|
108
|
+
)
|
|
109
|
+
overloaded_conf["activated"] = conf.get("activated", False)
|
|
110
|
+
overloaded_conf["use_mask"] = conf.get("use_mask", True)
|
|
111
|
+
|
|
112
|
+
# Saving files
|
|
113
|
+
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
114
|
+
"save_intermediate_data", False
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
auxiliary_filling_schema = {
|
|
118
|
+
"method": str,
|
|
119
|
+
"activated": bool,
|
|
120
|
+
"mode": str,
|
|
121
|
+
"use_mask": bool,
|
|
122
|
+
"texture_interpolator": str,
|
|
123
|
+
"save_intermediate_data": bool,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Check conf
|
|
127
|
+
checker = Checker(auxiliary_filling_schema)
|
|
128
|
+
checker.validate(overloaded_conf)
|
|
129
|
+
|
|
130
|
+
return overloaded_conf
|
|
131
|
+
|
|
132
|
+
# pylint: disable=too-many-positional-arguments
|
|
133
|
+
def run( # noqa: C901
|
|
134
|
+
self,
|
|
135
|
+
dsm_file,
|
|
136
|
+
color_file,
|
|
137
|
+
classif_file,
|
|
138
|
+
dump_dir,
|
|
139
|
+
sensor_inputs,
|
|
140
|
+
pairing,
|
|
141
|
+
geom_plugin,
|
|
142
|
+
texture_bands,
|
|
143
|
+
output_geoid,
|
|
144
|
+
orchestrator=None,
|
|
145
|
+
dsm_dir=None,
|
|
146
|
+
):
|
|
147
|
+
"""
|
|
148
|
+
run AuxiliaryFillingFromSensors
|
|
149
|
+
|
|
150
|
+
:param dsm_file: path to the filled dsm file
|
|
151
|
+
:type dsm_file: str
|
|
152
|
+
:param color_file: path to the color file
|
|
153
|
+
:type color_file: str
|
|
154
|
+
:param classification_file: path to the classification file
|
|
155
|
+
:type classification_file: str
|
|
156
|
+
:param dump_dir: output dump directory
|
|
157
|
+
:type dump_dir: str
|
|
158
|
+
:param sensor_inputs: dictionary containing paths to input images and
|
|
159
|
+
models
|
|
160
|
+
:type sensor_inputs: dict
|
|
161
|
+
:param pairing: pairing between input images
|
|
162
|
+
:type pairing: list
|
|
163
|
+
:param geom_plugin: geometry plugin used for inverse locations
|
|
164
|
+
:type geom_plugin: AbstractGeometry
|
|
165
|
+
:param texture_bands: list of band names used for output texture
|
|
166
|
+
:type texture_bands: list
|
|
167
|
+
:param output_geoid: output geoid filename as vertical reference for the
|
|
168
|
+
input DSM. If a boolean is provided instead of a filename True means
|
|
169
|
+
defined relative to cars internal geoid, and false on ellipsoid
|
|
170
|
+
:type output_geoid: OR(bool, str)
|
|
171
|
+
:param orchestrator: orchestrator used
|
|
172
|
+
:type orchestrator: Orchestrator
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
if dsm_dir is not None:
|
|
176
|
+
image_path_out = os.path.join(dsm_dir, "image.tif")
|
|
177
|
+
else:
|
|
178
|
+
image_path_out = color_file
|
|
179
|
+
|
|
180
|
+
if not self.used_config["activated"]:
|
|
181
|
+
return None
|
|
182
|
+
if sensor_inputs is None:
|
|
183
|
+
logging.error(
|
|
184
|
+
"No sensor inputs were provided, "
|
|
185
|
+
"auxiliary_filling will not run."
|
|
186
|
+
)
|
|
187
|
+
return None
|
|
188
|
+
# Default orchestrator
|
|
189
|
+
if orchestrator is None:
|
|
190
|
+
# Create default sequential orchestrator for current application
|
|
191
|
+
# be aware, no out_json will be shared between orchestrators
|
|
192
|
+
# No files saved
|
|
193
|
+
self.orchestrator = ocht.Orchestrator(
|
|
194
|
+
orchestrator_conf={"mode": "sequential"}
|
|
195
|
+
)
|
|
196
|
+
else:
|
|
197
|
+
self.orchestrator = orchestrator
|
|
198
|
+
|
|
199
|
+
dump_dir = os.path.join(dump_dir, "auxiliary_filling")
|
|
200
|
+
|
|
201
|
+
if not os.path.exists(dump_dir):
|
|
202
|
+
os.makedirs(dump_dir)
|
|
203
|
+
|
|
204
|
+
color_not_filled_file = color_file
|
|
205
|
+
|
|
206
|
+
classification_not_filled_file = None
|
|
207
|
+
# classif_file could be defined without data attached
|
|
208
|
+
if classif_file is not None and not os.path.exists(classif_file):
|
|
209
|
+
classif_file = None
|
|
210
|
+
|
|
211
|
+
if classif_file is not None:
|
|
212
|
+
classification_not_filled_file = os.path.join(
|
|
213
|
+
dump_dir, "classification_not_filled.tif"
|
|
214
|
+
)
|
|
215
|
+
shutil.move(classif_file, classification_not_filled_file)
|
|
216
|
+
|
|
217
|
+
# Clean dump_dir at the end of processing if required
|
|
218
|
+
if not self.used_config["save_intermediate_data"]:
|
|
219
|
+
self.orchestrator.add_to_clean(dump_dir)
|
|
220
|
+
|
|
221
|
+
# Create output CarsDataset
|
|
222
|
+
aux_filled_image = cars_dataset.CarsDataset(
|
|
223
|
+
"arrays", name="aux_filled_image"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Create tiling grid
|
|
227
|
+
ground_image_width, ground_image_height = inputs.rasterio_get_size(
|
|
228
|
+
dsm_file
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
region_grid = tiling.generate_tiling_grid(
|
|
232
|
+
0,
|
|
233
|
+
0,
|
|
234
|
+
ground_image_height,
|
|
235
|
+
ground_image_width,
|
|
236
|
+
1000,
|
|
237
|
+
1000,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
aux_filled_image.tiling_grid = region_grid
|
|
241
|
+
|
|
242
|
+
# Initialize no data value
|
|
243
|
+
classification_no_data_value = 0
|
|
244
|
+
texture_no_data_value = 0
|
|
245
|
+
color_dtype = np.float32
|
|
246
|
+
classif_dtype = np.uint8
|
|
247
|
+
|
|
248
|
+
if color_file is not None:
|
|
249
|
+
if os.path.exists(color_not_filled_file):
|
|
250
|
+
with rio.open(color_not_filled_file, "r") as descriptor:
|
|
251
|
+
texture_no_data_value = descriptor.nodata
|
|
252
|
+
color_dtype = descriptor.profile.get("dtype", np.float32)
|
|
253
|
+
|
|
254
|
+
self.orchestrator.add_to_save_lists(
|
|
255
|
+
os.path.join(dump_dir, image_path_out),
|
|
256
|
+
cst.RASTER_COLOR_IMG,
|
|
257
|
+
aux_filled_image,
|
|
258
|
+
nodata=texture_no_data_value,
|
|
259
|
+
dtype=color_dtype,
|
|
260
|
+
cars_ds_name="filled_texture",
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
if classif_file is not None:
|
|
264
|
+
if os.path.exists(classification_not_filled_file):
|
|
265
|
+
with rio.open(
|
|
266
|
+
classification_not_filled_file, "r"
|
|
267
|
+
) as descriptor:
|
|
268
|
+
classification_no_data_value = descriptor.nodata
|
|
269
|
+
classif_dtype = descriptor.profile.get("dtype", np.uint8)
|
|
270
|
+
|
|
271
|
+
self.orchestrator.add_to_save_lists(
|
|
272
|
+
os.path.join(dump_dir, classif_file),
|
|
273
|
+
cst.RASTER_CLASSIF,
|
|
274
|
+
aux_filled_image,
|
|
275
|
+
dtype=classif_dtype,
|
|
276
|
+
nodata=classification_no_data_value,
|
|
277
|
+
cars_ds_name="filled_classification",
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# Get saving infos in order to save tiles when they are computed
|
|
281
|
+
[saving_info] = self.orchestrator.get_saving_infos([aux_filled_image])
|
|
282
|
+
|
|
283
|
+
reference_transform = inputs.rasterio_get_transform(dsm_file)
|
|
284
|
+
reference_crs = inputs.rasterio_get_crs(dsm_file)
|
|
285
|
+
|
|
286
|
+
# Pre-compute sensor bounds of all sensors to filter sensors that do
|
|
287
|
+
# not intersect with tile in tasks
|
|
288
|
+
sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
|
|
289
|
+
sensor_inputs, geom_plugin, reference_crs
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
for row in range(aux_filled_image.shape[0]):
|
|
293
|
+
for col in range(aux_filled_image.shape[1]):
|
|
294
|
+
|
|
295
|
+
# Get window
|
|
296
|
+
window = cars_dataset.window_array_to_dict(
|
|
297
|
+
aux_filled_image.tiling_grid[row, col]
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
full_saving_info = ocht.update_saving_infos(
|
|
301
|
+
saving_info, row=row, col=col
|
|
302
|
+
)
|
|
303
|
+
aux_filled_image[
|
|
304
|
+
row, col
|
|
305
|
+
] = self.orchestrator.cluster.create_task(
|
|
306
|
+
filling_from_sensor_wrapper, nout=1
|
|
307
|
+
)(
|
|
308
|
+
dsm_file,
|
|
309
|
+
color_not_filled_file,
|
|
310
|
+
classification_not_filled_file,
|
|
311
|
+
sensor_inputs,
|
|
312
|
+
sensor_bounds,
|
|
313
|
+
pairing,
|
|
314
|
+
window,
|
|
315
|
+
reference_transform,
|
|
316
|
+
reference_crs,
|
|
317
|
+
full_saving_info,
|
|
318
|
+
geom_plugin,
|
|
319
|
+
texture_bands,
|
|
320
|
+
output_geoid,
|
|
321
|
+
mode=self.used_config["mode"],
|
|
322
|
+
texture_interpolator=self.used_config[
|
|
323
|
+
"texture_interpolator"
|
|
324
|
+
],
|
|
325
|
+
use_mask=self.used_config["use_mask"],
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# Run tasks if an internal orchestrator is used, in order to save output
|
|
329
|
+
# files
|
|
330
|
+
if orchestrator is None:
|
|
331
|
+
self.orchestrator.breakpoint()
|
|
332
|
+
|
|
333
|
+
return aux_filled_image
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
# pylint: disable=too-many-positional-arguments
|
|
337
|
+
def filling_from_sensor_wrapper(
|
|
338
|
+
dsm_file,
|
|
339
|
+
color_file,
|
|
340
|
+
classification_file,
|
|
341
|
+
sensor_inputs,
|
|
342
|
+
sensor_bounds,
|
|
343
|
+
pairing,
|
|
344
|
+
window,
|
|
345
|
+
transform,
|
|
346
|
+
crs,
|
|
347
|
+
saving_info,
|
|
348
|
+
geom_plugin,
|
|
349
|
+
texture_bands,
|
|
350
|
+
output_geoid,
|
|
351
|
+
mode,
|
|
352
|
+
texture_interpolator,
|
|
353
|
+
use_mask,
|
|
354
|
+
):
|
|
355
|
+
"""
|
|
356
|
+
Fill color and classification from sensor information for a terrain tile
|
|
357
|
+
|
|
358
|
+
:param dsm_file: path to the filled dsm file
|
|
359
|
+
:type dsm_file: str
|
|
360
|
+
:param color_file: path to the color file
|
|
361
|
+
:type color_file: str
|
|
362
|
+
:param classification_file: path to the classification file
|
|
363
|
+
:type classification_file: str
|
|
364
|
+
:param sensor_inputs: dictionary containing paths to input images and models
|
|
365
|
+
:type sensor_inputs: dict
|
|
366
|
+
:param sensor_bounds: dictionary containing bounds of input sensors
|
|
367
|
+
:type sensor_bounds: dict
|
|
368
|
+
:param pairing: pairing between input images
|
|
369
|
+
:type pairing: list
|
|
370
|
+
:param window: window of the current tile
|
|
371
|
+
:type window: dict
|
|
372
|
+
:param transform: input geo transform
|
|
373
|
+
:type transform: tuple
|
|
374
|
+
:param crs: input crs
|
|
375
|
+
:type crs: CRS
|
|
376
|
+
:param saving_info: saving info for cars orchestrator
|
|
377
|
+
:type saving_info: dict
|
|
378
|
+
:param geom_plugin: geometry plugin used for inverse locations
|
|
379
|
+
:type geom_plugin: AbstractGeometry
|
|
380
|
+
:param texture_bands: list of band names used for output texture
|
|
381
|
+
:type texture_bands: list
|
|
382
|
+
:param output_geoid: output geoid filename as vertical reference for the
|
|
383
|
+
input DSM. If a boolean is provided instead of a filename True means
|
|
384
|
+
defined relative to cars internal geoid, and false on ellipsoid
|
|
385
|
+
:type output_geoid: OR(bool, str)
|
|
386
|
+
:param mode: geometry plugin used for inverse locations
|
|
387
|
+
:type mode: str
|
|
388
|
+
:param texture_interpolator: scipy interpolator use to interpolate color
|
|
389
|
+
values
|
|
390
|
+
:type texture_interpolator: str
|
|
391
|
+
:param use_mask: use mask information from sensors in color computation
|
|
392
|
+
:type use_mask: bool
|
|
393
|
+
"""
|
|
394
|
+
col_min = window["col_min"]
|
|
395
|
+
col_max = window["col_max"]
|
|
396
|
+
row_min = window["row_min"]
|
|
397
|
+
row_max = window["row_max"]
|
|
398
|
+
|
|
399
|
+
col_min_ground = col_min * transform[0] + transform[2]
|
|
400
|
+
col_max_ground = col_max * transform[0] + transform[2]
|
|
401
|
+
row_min_ground = row_min * transform[4] + transform[5]
|
|
402
|
+
row_max_ground = row_max * transform[4] + transform[5]
|
|
403
|
+
|
|
404
|
+
ground_polygon = Polygon(
|
|
405
|
+
[
|
|
406
|
+
(col_min_ground, row_min_ground),
|
|
407
|
+
(col_min_ground, row_max_ground),
|
|
408
|
+
(col_max_ground, row_max_ground),
|
|
409
|
+
(col_max_ground, row_min_ground),
|
|
410
|
+
(col_min_ground, row_min_ground),
|
|
411
|
+
]
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
cols = (
|
|
415
|
+
np.linspace(col_min, col_max, col_max - col_min) * transform[0]
|
|
416
|
+
+ transform[2]
|
|
417
|
+
)
|
|
418
|
+
rows = (
|
|
419
|
+
np.linspace(row_min, row_max, row_max - row_min) * transform[4]
|
|
420
|
+
+ transform[5]
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
cols_values_2d, rows_values_2d = np.meshgrid(cols, rows)
|
|
424
|
+
|
|
425
|
+
stacked_values = np.vstack([cols_values_2d.ravel(), rows_values_2d.ravel()])
|
|
426
|
+
|
|
427
|
+
lon_lat = projection.point_cloud_conversion_crs(
|
|
428
|
+
stacked_values.transpose(), crs, CRS(4326)
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
rio_window = rio.windows.Window.from_slices(
|
|
432
|
+
(
|
|
433
|
+
row_min,
|
|
434
|
+
row_max,
|
|
435
|
+
),
|
|
436
|
+
(
|
|
437
|
+
col_min,
|
|
438
|
+
col_max,
|
|
439
|
+
),
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# From input DSM read altitudes for localisation and no-data mask.
|
|
443
|
+
# if fill_nan mode is chosed, all values valid in dsm and invalid in color
|
|
444
|
+
# will be filled
|
|
445
|
+
# if not, all values valid in dsm will be filled
|
|
446
|
+
# Note that the same pixels are filled for color and classification
|
|
447
|
+
with rio.open(dsm_file) as dsm_image:
|
|
448
|
+
alt_values = dsm_image.read(1, window=rio_window)
|
|
449
|
+
target_mask = dsm_image.read_masks(1, window=rio_window)
|
|
450
|
+
dsm_profile = dsm_image.profile
|
|
451
|
+
|
|
452
|
+
if output_geoid:
|
|
453
|
+
if output_geoid is True:
|
|
454
|
+
geoid_file = geom_plugin.geoid
|
|
455
|
+
else:
|
|
456
|
+
geoid_file = output_geoid
|
|
457
|
+
with rio.open(geoid_file) as in_geoid:
|
|
458
|
+
# Reproject the geoid data to match the DSM
|
|
459
|
+
output_geoid_data = np.empty(
|
|
460
|
+
alt_values.shape, dtype=in_geoid.dtypes[0]
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
reproject(
|
|
464
|
+
source=rio.band(in_geoid, 1),
|
|
465
|
+
destination=output_geoid_data,
|
|
466
|
+
src_transform=in_geoid.transform,
|
|
467
|
+
src_crs=in_geoid.crs,
|
|
468
|
+
dst_transform=transform,
|
|
469
|
+
dst_crs=crs,
|
|
470
|
+
resampling=Resampling.bilinear,
|
|
471
|
+
)
|
|
472
|
+
alt_values += output_geoid_data
|
|
473
|
+
|
|
474
|
+
nodata_color = None
|
|
475
|
+
nodata_classif = None
|
|
476
|
+
|
|
477
|
+
if os.path.exists(color_file):
|
|
478
|
+
with rio.open(color_file) as color_image:
|
|
479
|
+
profile = color_image.profile
|
|
480
|
+
nodata_color = color_image.nodata
|
|
481
|
+
|
|
482
|
+
number_of_color_bands = color_image.count
|
|
483
|
+
color_band_names = list(color_image.descriptions)
|
|
484
|
+
|
|
485
|
+
color_values = color_image.read(window=rio_window)
|
|
486
|
+
|
|
487
|
+
if mode == "fill_nan":
|
|
488
|
+
target_mask = target_mask & ~color_image.read_masks(
|
|
489
|
+
1, window=rio_window
|
|
490
|
+
)
|
|
491
|
+
else:
|
|
492
|
+
profile = dsm_profile
|
|
493
|
+
number_of_color_bands = inputs.rasterio_get_nb_bands(
|
|
494
|
+
sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
|
|
495
|
+
)
|
|
496
|
+
color_values = np.full(
|
|
497
|
+
(number_of_color_bands, *target_mask.shape), np.nan
|
|
498
|
+
)
|
|
499
|
+
color_band_names = inputs.get_descriptions_bands(
|
|
500
|
+
sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
|
|
501
|
+
)
|
|
502
|
+
# update profile
|
|
503
|
+
profile.update(count=number_of_color_bands)
|
|
504
|
+
|
|
505
|
+
number_of_classification_bands = 0
|
|
506
|
+
classification_values = None
|
|
507
|
+
classification_band_names = None
|
|
508
|
+
|
|
509
|
+
if classification_file is not None:
|
|
510
|
+
if os.path.exists(classification_file):
|
|
511
|
+
with rio.open(classification_file) as classification_image:
|
|
512
|
+
nodata_classif = None
|
|
513
|
+
|
|
514
|
+
number_of_classification_bands = classification_image.count
|
|
515
|
+
|
|
516
|
+
classification_values = classification_image.read(
|
|
517
|
+
window=rio_window
|
|
518
|
+
)
|
|
519
|
+
classification_band_names = list(
|
|
520
|
+
classification_image.descriptions
|
|
521
|
+
)
|
|
522
|
+
else:
|
|
523
|
+
profile = dsm_profile
|
|
524
|
+
classif_sample = sensor_inputs[list(sensor_inputs.keys())[0]].get(
|
|
525
|
+
"classification", None
|
|
526
|
+
)
|
|
527
|
+
if classif_sample is None:
|
|
528
|
+
raise RuntimeError(
|
|
529
|
+
"No classification file found for auxiliary filling"
|
|
530
|
+
)
|
|
531
|
+
number_of_classification_bands = len(classif_sample["values"])
|
|
532
|
+
classification_values = np.full(
|
|
533
|
+
(number_of_classification_bands, *target_mask.shape), np.nan
|
|
534
|
+
)
|
|
535
|
+
classification_band_names = inputs.get_descriptions_bands(
|
|
536
|
+
classif_sample
|
|
537
|
+
)
|
|
538
|
+
# update profile
|
|
539
|
+
profile.update(count=number_of_classification_bands)
|
|
540
|
+
|
|
541
|
+
# 1D index list from target mask
|
|
542
|
+
index_1d = target_mask.flatten().nonzero()[0]
|
|
543
|
+
|
|
544
|
+
# Remove sensor that don't intesects with current tile
|
|
545
|
+
filtered_sensor_inputs = auxiliary_filling_wrappers.filter_sensor_inputs(
|
|
546
|
+
sensor_inputs, sensor_bounds, ground_polygon
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
if len(index_1d) > 0:
|
|
550
|
+
# Fill required pixels
|
|
551
|
+
color_values_filled, classification_values_filled = (
|
|
552
|
+
auxiliary_filling_algo.fill_auxiliary(
|
|
553
|
+
filtered_sensor_inputs,
|
|
554
|
+
pairing,
|
|
555
|
+
lon_lat[index_1d, 0],
|
|
556
|
+
lon_lat[index_1d, 1],
|
|
557
|
+
alt_values.ravel()[index_1d],
|
|
558
|
+
geom_plugin,
|
|
559
|
+
number_of_color_bands,
|
|
560
|
+
number_of_classification_bands,
|
|
561
|
+
texture_bands,
|
|
562
|
+
texture_interpolator=texture_interpolator,
|
|
563
|
+
use_mask=use_mask,
|
|
564
|
+
)
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
# Change nan to nodata
|
|
568
|
+
if nodata_color is not None:
|
|
569
|
+
color_values_filled[np.isnan(color_values_filled)] = nodata_color
|
|
570
|
+
if nodata_classif is not None:
|
|
571
|
+
classification_values_filled[
|
|
572
|
+
np.isnan(classification_values_filled)
|
|
573
|
+
] = nodata_classif
|
|
574
|
+
|
|
575
|
+
# forward filled values in the output buffer
|
|
576
|
+
for band_index in range(number_of_color_bands):
|
|
577
|
+
np.put(
|
|
578
|
+
color_values[band_index, :, :],
|
|
579
|
+
index_1d,
|
|
580
|
+
color_values_filled[band_index, :],
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
for band_index in range(number_of_classification_bands):
|
|
584
|
+
np.put(
|
|
585
|
+
classification_values[band_index, :, :],
|
|
586
|
+
index_1d,
|
|
587
|
+
classification_values_filled[band_index, :],
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
row_arr = np.array(range(row_min, row_max))
|
|
591
|
+
col_arr = np.array(range(col_min, col_max))
|
|
592
|
+
|
|
593
|
+
values = {}
|
|
594
|
+
coords = {cst.ROW: row_arr, cst.COL: col_arr}
|
|
595
|
+
|
|
596
|
+
if len(color_band_names) == 0 or None in color_band_names:
|
|
597
|
+
color_band_names = [
|
|
598
|
+
str(current_band) for current_band in range(number_of_color_bands)
|
|
599
|
+
]
|
|
600
|
+
|
|
601
|
+
values[cst.RASTER_COLOR_IMG] = (
|
|
602
|
+
[cst.BAND_IM, cst.ROW, cst.COL],
|
|
603
|
+
color_values,
|
|
604
|
+
)
|
|
605
|
+
coords[cst.BAND_IM] = list(color_band_names)
|
|
606
|
+
|
|
607
|
+
if classification_values is not None:
|
|
608
|
+
values[cst.RASTER_CLASSIF] = (
|
|
609
|
+
[cst.BAND_CLASSIF, cst.ROW, cst.COL],
|
|
610
|
+
classification_values,
|
|
611
|
+
)
|
|
612
|
+
coords[cst.BAND_CLASSIF] = list(classification_band_names)
|
|
613
|
+
|
|
614
|
+
attributes = {}
|
|
615
|
+
|
|
616
|
+
dataset = xr.Dataset(
|
|
617
|
+
values,
|
|
618
|
+
coords=coords,
|
|
619
|
+
)
|
|
620
|
+
|
|
621
|
+
profile.update(crs=crs.to_wkt())
|
|
622
|
+
|
|
623
|
+
cars_dataset.fill_dataset(
|
|
624
|
+
dataset,
|
|
625
|
+
saving_info=saving_info,
|
|
626
|
+
window=window,
|
|
627
|
+
profile=profile,
|
|
628
|
+
attributes=attributes,
|
|
629
|
+
overlaps=None,
|
|
630
|
+
)
|
|
631
|
+
|
|
632
|
+
return dataset
|