cars 1.0.0a2__cp311-cp311-musllinux_1_2_i686.whl → 1.0.0a4__cp311-cp311-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/applications/__init__.py +0 -3
- cars/applications/application.py +14 -6
- cars/applications/application_template.py +42 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
- cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
- cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
- cars/applications/dem_generation/rasterization_app.py +112 -43
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
- cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-311-i386-linux-musl.so +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +48 -14
- cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
- cars/applications/dense_matching/disparity_grid_algo.py +95 -79
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
- cars/applications/dsm_filling/border_interpolation_app.py +11 -12
- cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
- cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
- cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
- cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +88 -116
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +60 -53
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +5 -25
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +364 -22
- cars/core/geometry/shareloc_geometry.py +112 -82
- cars/core/inputs.py +72 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +126 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +12 -10
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +149 -22
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +15 -4
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +461 -1052
- cars/pipelines/parameters/advanced_parameters.py +91 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +122 -73
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +676 -1070
- cars/starter.py +4 -3
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +174 -187
- cars/applications/dense_match_filling/cpp/__init__.py +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cpython-311-i386-linux-musl.so +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
- cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
- cars/applications/dense_match_filling/cpp/meson.build +0 -9
- cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
- cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
- cars/applications/dense_match_filling/plane_app.py +0 -556
- cars/applications/hole_detection/__init__.py +0 -30
- cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
- cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
- cars/applications/hole_detection/hole_detection_algo.py +0 -144
- cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
- cars/applications/point_cloud_denoising/__init__.py +0 -29
- cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
- cars/applications/point_cloud_fusion/__init__.py +0 -30
- cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
cars/applications/__init__.py
CHANGED
|
@@ -30,9 +30,6 @@ from . import dense_matching # noqa: F401
|
|
|
30
30
|
from . import dsm_filling # noqa: F401
|
|
31
31
|
from . import grid_generation # noqa: F401
|
|
32
32
|
from . import ground_truth_reprojection # noqa: F401
|
|
33
|
-
from . import hole_detection # noqa: F401
|
|
34
|
-
from . import point_cloud_denoising # noqa: F401
|
|
35
|
-
from . import point_cloud_fusion # noqa: F401
|
|
36
33
|
from . import point_cloud_outlier_removal # noqa: F401
|
|
37
34
|
from . import rasterization # noqa: F401
|
|
38
35
|
from . import resampling # noqa: F401
|
cars/applications/application.py
CHANGED
|
@@ -26,6 +26,8 @@ This module contains class application factory.
|
|
|
26
26
|
# Standard imports
|
|
27
27
|
import logging
|
|
28
28
|
|
|
29
|
+
from cars.applications.application_template import ScalingApplicationTemplate
|
|
30
|
+
|
|
29
31
|
# CARS imports
|
|
30
32
|
from cars.conf.input_parameters import ConfigType
|
|
31
33
|
|
|
@@ -46,6 +48,7 @@ class Application:
|
|
|
46
48
|
cls,
|
|
47
49
|
app_name: str,
|
|
48
50
|
cfg: ConfigType = None,
|
|
51
|
+
scaling_coeff: float = 1,
|
|
49
52
|
):
|
|
50
53
|
"""
|
|
51
54
|
Return the instance of application associated with the application
|
|
@@ -55,12 +58,14 @@ class Application:
|
|
|
55
58
|
:type app_name: str
|
|
56
59
|
:param cfg: configuration {'matching_cost_method': value}
|
|
57
60
|
:type cfg: dictionary
|
|
61
|
+
:param scaling_coeff: scaling factor for resolution
|
|
62
|
+
:type scaling_coeff: float
|
|
58
63
|
"""
|
|
59
64
|
|
|
60
|
-
return cls.create_app(app_name, cfg)
|
|
65
|
+
return cls.create_app(app_name, cfg, scaling_coeff)
|
|
61
66
|
|
|
62
67
|
@classmethod
|
|
63
|
-
def create_app(cls, name: str, cfg: ConfigType):
|
|
68
|
+
def create_app(cls, name: str, cfg: ConfigType, scaling_coeff: float = 1):
|
|
64
69
|
"""Factory command to create the application
|
|
65
70
|
Return the instance of application associated with the application
|
|
66
71
|
name given as parameter
|
|
@@ -69,16 +74,19 @@ class Application:
|
|
|
69
74
|
:type app_name: str
|
|
70
75
|
:param cfg: configuration {'matching_cost_method': value}
|
|
71
76
|
:type cfg: dictionary
|
|
77
|
+
:param scaling_coeff: scaling factor for resolution
|
|
78
|
+
:type scaling_coeff: float
|
|
72
79
|
"""
|
|
73
|
-
app = None
|
|
74
|
-
|
|
75
80
|
try:
|
|
76
81
|
app_class = cls.available_applications[name]
|
|
77
82
|
except KeyError:
|
|
78
83
|
logging.error("No application named {0} supported".format(name))
|
|
79
84
|
return None
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
|
|
86
|
+
if issubclass(app_class, ScalingApplicationTemplate):
|
|
87
|
+
return app_class(scaling_coeff=scaling_coeff, conf=cfg)
|
|
88
|
+
|
|
89
|
+
return app_class(conf=cfg)
|
|
82
90
|
|
|
83
91
|
@classmethod
|
|
84
92
|
def print_applications(cls):
|
|
@@ -29,6 +29,7 @@ in sub application classes
|
|
|
29
29
|
|
|
30
30
|
# Standard imports
|
|
31
31
|
import logging
|
|
32
|
+
import os
|
|
32
33
|
import pprint
|
|
33
34
|
from abc import ABCMeta, abstractmethod
|
|
34
35
|
|
|
@@ -102,3 +103,44 @@ class ApplicationTemplate(metaclass=ABCMeta):
|
|
|
102
103
|
"""
|
|
103
104
|
|
|
104
105
|
return self.used_config
|
|
106
|
+
|
|
107
|
+
def generate_unknown_dump_dir(self, orchestrator):
|
|
108
|
+
"""
|
|
109
|
+
Generate dump dir from orchestrator
|
|
110
|
+
|
|
111
|
+
:param orchestrator: orchestrator
|
|
112
|
+
|
|
113
|
+
:return: dump dir
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
dump_dir = None
|
|
117
|
+
if orchestrator is not None:
|
|
118
|
+
orch_out_dir = orchestrator.out_dir
|
|
119
|
+
dump_dir = os.path.join(
|
|
120
|
+
orch_out_dir,
|
|
121
|
+
"unknown_dump",
|
|
122
|
+
self.__class__.__bases__[0].__name__,
|
|
123
|
+
)
|
|
124
|
+
return dump_dir
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class ScalingApplicationTemplate(ApplicationTemplate, metaclass=ABCMeta):
|
|
128
|
+
"""
|
|
129
|
+
Template for applications requiring resolution scaling.
|
|
130
|
+
|
|
131
|
+
Inherits from ApplicationTemplate and adds the scaling coefficient
|
|
132
|
+
as a required argument.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def __init__(self, scaling_coeff, conf=None):
|
|
136
|
+
"""
|
|
137
|
+
Init function of ScalingApplicationTemplate
|
|
138
|
+
|
|
139
|
+
:param scaling_coeff: scaling factor for resolution
|
|
140
|
+
:type scaling_coeff: float
|
|
141
|
+
|
|
142
|
+
:param conf: configuration for application
|
|
143
|
+
:type conf: dict
|
|
144
|
+
"""
|
|
145
|
+
self.scaling_coeff = scaling_coeff
|
|
146
|
+
super().__init__(conf=conf)
|
|
@@ -86,8 +86,18 @@ class AuxiliaryFilling(ApplicationTemplate, metaclass=ABCMeta):
|
|
|
86
86
|
cls.available_applications[short_name] = cls
|
|
87
87
|
|
|
88
88
|
@abstractmethod
|
|
89
|
-
def run(
|
|
90
|
-
self,
|
|
89
|
+
def run( # pylint: disable=too-many-positional-arguments
|
|
90
|
+
self,
|
|
91
|
+
dsm_file,
|
|
92
|
+
color_file,
|
|
93
|
+
classif_file,
|
|
94
|
+
dump_dir,
|
|
95
|
+
sensor_inputs,
|
|
96
|
+
pairing,
|
|
97
|
+
geom_plugin,
|
|
98
|
+
texture_bands,
|
|
99
|
+
output_geoid,
|
|
100
|
+
orchestrator=None,
|
|
91
101
|
):
|
|
92
102
|
"""
|
|
93
103
|
Run Auxiliary filling
|
|
@@ -28,7 +28,7 @@ import rasterio as rio
|
|
|
28
28
|
from scipy import interpolate
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def fill_auxiliary(
|
|
31
|
+
def fill_auxiliary( # pylint: disable=too-many-positional-arguments
|
|
32
32
|
sensor_inputs,
|
|
33
33
|
pairing,
|
|
34
34
|
longitudes,
|
|
@@ -156,7 +156,7 @@ def fill_auxiliary(
|
|
|
156
156
|
return filled_color, filled_classif
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-
def fill_from_one_sensor( # noqa C901
|
|
159
|
+
def fill_from_one_sensor( # pylint: disable=too-many-positional-arguments # noqa C901
|
|
160
160
|
sensor,
|
|
161
161
|
filled_color,
|
|
162
162
|
filled_classif,
|
|
@@ -30,6 +30,9 @@ import numpy as np
|
|
|
30
30
|
import rasterio as rio
|
|
31
31
|
import xarray as xr
|
|
32
32
|
from json_checker import Checker
|
|
33
|
+
from pyproj import CRS
|
|
34
|
+
from rasterio.enums import Resampling
|
|
35
|
+
from rasterio.warp import reproject
|
|
33
36
|
from shapely.geometry import Polygon
|
|
34
37
|
|
|
35
38
|
import cars.orchestrator.orchestrator as ocht
|
|
@@ -93,10 +96,11 @@ class AuxiliaryFillingFromSensors(
|
|
|
93
96
|
overloaded_conf["mode"] = conf.get("mode", "fill_nan")
|
|
94
97
|
|
|
95
98
|
if overloaded_conf["mode"] not in ["fill_nan", "full"]:
|
|
99
|
+
# pylint: disable=inconsistent-quotes
|
|
96
100
|
raise RuntimeError(
|
|
97
101
|
f"Invalid mode {overloaded_conf['mode']} for "
|
|
98
|
-
"AuxiliaryFilling, supported modes are fill_nan "
|
|
99
|
-
"and full"
|
|
102
|
+
f"AuxiliaryFilling, supported modes are fill_nan "
|
|
103
|
+
f"and full"
|
|
100
104
|
)
|
|
101
105
|
|
|
102
106
|
overloaded_conf["texture_interpolator"] = conf.get(
|
|
@@ -125,7 +129,8 @@ class AuxiliaryFillingFromSensors(
|
|
|
125
129
|
|
|
126
130
|
return overloaded_conf
|
|
127
131
|
|
|
128
|
-
|
|
132
|
+
# pylint: disable=too-many-positional-arguments
|
|
133
|
+
def run( # noqa: C901
|
|
129
134
|
self,
|
|
130
135
|
dsm_file,
|
|
131
136
|
color_file,
|
|
@@ -135,6 +140,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
135
140
|
pairing,
|
|
136
141
|
geom_plugin,
|
|
137
142
|
texture_bands,
|
|
143
|
+
output_geoid,
|
|
138
144
|
orchestrator=None,
|
|
139
145
|
):
|
|
140
146
|
"""
|
|
@@ -157,6 +163,10 @@ class AuxiliaryFillingFromSensors(
|
|
|
157
163
|
:type geom_plugin: AbstractGeometry
|
|
158
164
|
:param texture_bands: list of band names used for output texture
|
|
159
165
|
:type texture_bands: list
|
|
166
|
+
:param output_geoid: output geoid filename as vertical reference for the
|
|
167
|
+
input DSM. If a boolean is provided instead of a filename True means
|
|
168
|
+
defined relative to cars internal geoid, and false on ellipsoid
|
|
169
|
+
:type output_geoid: OR(bool, str)
|
|
160
170
|
:param orchestrator: orchestrator used
|
|
161
171
|
:type orchestrator: Orchestrator
|
|
162
172
|
"""
|
|
@@ -187,16 +197,19 @@ class AuxiliaryFillingFromSensors(
|
|
|
187
197
|
os.makedirs(dump_dir)
|
|
188
198
|
|
|
189
199
|
color_not_filled_file = os.path.join(dump_dir, "texture_not_filled.tif")
|
|
190
|
-
if os.path.exists(color_file):
|
|
200
|
+
if color_file is not None and os.path.exists(color_file):
|
|
191
201
|
shutil.move(color_file, color_not_filled_file)
|
|
192
202
|
|
|
193
203
|
classification_not_filled_file = None
|
|
204
|
+
# classif_file could be defined without data attached
|
|
205
|
+
if classif_file is not None and not os.path.exists(classif_file):
|
|
206
|
+
classif_file = None
|
|
207
|
+
|
|
194
208
|
if classif_file is not None:
|
|
195
209
|
classification_not_filled_file = os.path.join(
|
|
196
210
|
dump_dir, "classification_not_filled.tif"
|
|
197
211
|
)
|
|
198
|
-
|
|
199
|
-
shutil.move(classif_file, classification_not_filled_file)
|
|
212
|
+
shutil.move(classif_file, classification_not_filled_file)
|
|
200
213
|
|
|
201
214
|
# Clean dump_dir at the end of processing if required
|
|
202
215
|
if not self.used_config["save_intermediate_data"]:
|
|
@@ -229,19 +242,20 @@ class AuxiliaryFillingFromSensors(
|
|
|
229
242
|
color_dtype = np.float32
|
|
230
243
|
classif_dtype = np.uint8
|
|
231
244
|
|
|
232
|
-
if
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
if color_file is not None:
|
|
246
|
+
if os.path.exists(color_not_filled_file):
|
|
247
|
+
with rio.open(color_not_filled_file, "r") as descriptor:
|
|
248
|
+
texture_no_data_value = descriptor.nodata
|
|
249
|
+
color_dtype = descriptor.profile.get("dtype", np.float32)
|
|
250
|
+
|
|
251
|
+
self.orchestrator.add_to_save_lists(
|
|
252
|
+
os.path.join(dump_dir, color_file),
|
|
253
|
+
cst.RASTER_COLOR_IMG,
|
|
254
|
+
aux_filled_image,
|
|
255
|
+
nodata=texture_no_data_value,
|
|
256
|
+
dtype=color_dtype,
|
|
257
|
+
cars_ds_name="filled_texture",
|
|
258
|
+
)
|
|
245
259
|
|
|
246
260
|
if classif_file is not None:
|
|
247
261
|
if os.path.exists(classification_not_filled_file):
|
|
@@ -264,12 +278,12 @@ class AuxiliaryFillingFromSensors(
|
|
|
264
278
|
[saving_info] = self.orchestrator.get_saving_infos([aux_filled_image])
|
|
265
279
|
|
|
266
280
|
reference_transform = inputs.rasterio_get_transform(dsm_file)
|
|
267
|
-
|
|
281
|
+
reference_crs = inputs.rasterio_get_crs(dsm_file)
|
|
268
282
|
|
|
269
283
|
# Pre-compute sensor bounds of all sensors to filter sensors that do
|
|
270
284
|
# not intersect with tile in tasks
|
|
271
285
|
sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
|
|
272
|
-
sensor_inputs, geom_plugin,
|
|
286
|
+
sensor_inputs, geom_plugin, reference_crs
|
|
273
287
|
)
|
|
274
288
|
|
|
275
289
|
for row in range(aux_filled_image.shape[0]):
|
|
@@ -296,10 +310,11 @@ class AuxiliaryFillingFromSensors(
|
|
|
296
310
|
pairing,
|
|
297
311
|
window,
|
|
298
312
|
reference_transform,
|
|
299
|
-
|
|
313
|
+
reference_crs,
|
|
300
314
|
full_saving_info,
|
|
301
315
|
geom_plugin,
|
|
302
316
|
texture_bands,
|
|
317
|
+
output_geoid,
|
|
303
318
|
mode=self.used_config["mode"],
|
|
304
319
|
texture_interpolator=self.used_config[
|
|
305
320
|
"texture_interpolator"
|
|
@@ -315,6 +330,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
315
330
|
return aux_filled_image
|
|
316
331
|
|
|
317
332
|
|
|
333
|
+
# pylint: disable=too-many-positional-arguments
|
|
318
334
|
def filling_from_sensor_wrapper(
|
|
319
335
|
dsm_file,
|
|
320
336
|
color_file,
|
|
@@ -324,10 +340,11 @@ def filling_from_sensor_wrapper(
|
|
|
324
340
|
pairing,
|
|
325
341
|
window,
|
|
326
342
|
transform,
|
|
327
|
-
|
|
343
|
+
crs,
|
|
328
344
|
saving_info,
|
|
329
345
|
geom_plugin,
|
|
330
346
|
texture_bands,
|
|
347
|
+
output_geoid,
|
|
331
348
|
mode,
|
|
332
349
|
texture_interpolator,
|
|
333
350
|
use_mask,
|
|
@@ -351,14 +368,18 @@ def filling_from_sensor_wrapper(
|
|
|
351
368
|
:type window: dict
|
|
352
369
|
:param transform: input geo transform
|
|
353
370
|
:type transform: tuple
|
|
354
|
-
:param
|
|
355
|
-
:type
|
|
371
|
+
:param crs: input crs
|
|
372
|
+
:type crs: CRS
|
|
356
373
|
:param saving_info: saving info for cars orchestrator
|
|
357
374
|
:type saving_info: dict
|
|
358
375
|
:param geom_plugin: geometry plugin used for inverse locations
|
|
359
376
|
:type geom_plugin: AbstractGeometry
|
|
360
377
|
:param texture_bands: list of band names used for output texture
|
|
361
378
|
:type texture_bands: list
|
|
379
|
+
:param output_geoid: output geoid filename as vertical reference for the
|
|
380
|
+
input DSM. If a boolean is provided instead of a filename True means
|
|
381
|
+
defined relative to cars internal geoid, and false on ellipsoid
|
|
382
|
+
:type output_geoid: OR(bool, str)
|
|
362
383
|
:param mode: geometry plugin used for inverse locations
|
|
363
384
|
:type mode: str
|
|
364
385
|
:param texture_interpolator: scipy interpolator use to interpolate color
|
|
@@ -366,13 +387,17 @@ def filling_from_sensor_wrapper(
|
|
|
366
387
|
:type texture_interpolator: str
|
|
367
388
|
:param use_mask: use mask information from sensors in color computation
|
|
368
389
|
:type use_mask: bool
|
|
369
|
-
|
|
370
390
|
"""
|
|
371
391
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
392
|
+
col_min = window["col_min"]
|
|
393
|
+
col_max = window["col_max"]
|
|
394
|
+
row_min = window["row_min"]
|
|
395
|
+
row_max = window["row_max"]
|
|
396
|
+
|
|
397
|
+
col_min_ground = col_min * transform[0] + transform[2]
|
|
398
|
+
col_max_ground = col_max * transform[0] + transform[2]
|
|
399
|
+
row_min_ground = row_min * transform[4] + transform[5]
|
|
400
|
+
row_max_ground = row_max * transform[4] + transform[5]
|
|
376
401
|
|
|
377
402
|
ground_polygon = Polygon(
|
|
378
403
|
[
|
|
@@ -384,33 +409,31 @@ def filling_from_sensor_wrapper(
|
|
|
384
409
|
]
|
|
385
410
|
)
|
|
386
411
|
|
|
387
|
-
cols =
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
transform[0],
|
|
412
|
+
cols = (
|
|
413
|
+
np.linspace(col_min, col_max, col_max - col_min) * transform[0]
|
|
414
|
+
+ transform[2]
|
|
391
415
|
)
|
|
392
|
-
rows =
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
transform[4],
|
|
416
|
+
rows = (
|
|
417
|
+
np.linspace(row_min, row_max, row_max - row_min) * transform[4]
|
|
418
|
+
+ transform[5]
|
|
396
419
|
)
|
|
397
420
|
|
|
398
421
|
cols_values_2d, rows_values_2d = np.meshgrid(cols, rows)
|
|
399
422
|
|
|
400
423
|
stacked_values = np.vstack([cols_values_2d.ravel(), rows_values_2d.ravel()])
|
|
401
424
|
|
|
402
|
-
lon_lat = projection.
|
|
403
|
-
stacked_values.transpose(),
|
|
425
|
+
lon_lat = projection.point_cloud_conversion_crs(
|
|
426
|
+
stacked_values.transpose(), crs, CRS(4326)
|
|
404
427
|
)
|
|
405
428
|
|
|
406
429
|
rio_window = rio.windows.Window.from_slices(
|
|
407
430
|
(
|
|
408
|
-
|
|
409
|
-
|
|
431
|
+
row_min,
|
|
432
|
+
row_max,
|
|
410
433
|
),
|
|
411
434
|
(
|
|
412
|
-
|
|
413
|
-
|
|
435
|
+
col_min,
|
|
436
|
+
col_max,
|
|
414
437
|
),
|
|
415
438
|
)
|
|
416
439
|
|
|
@@ -424,6 +447,28 @@ def filling_from_sensor_wrapper(
|
|
|
424
447
|
target_mask = dsm_image.read_masks(1, window=rio_window)
|
|
425
448
|
dsm_profile = dsm_image.profile
|
|
426
449
|
|
|
450
|
+
if output_geoid:
|
|
451
|
+
if output_geoid is True:
|
|
452
|
+
geoid_file = geom_plugin.geoid
|
|
453
|
+
else:
|
|
454
|
+
geoid_file = output_geoid
|
|
455
|
+
with rio.open(geoid_file) as in_geoid:
|
|
456
|
+
# Reproject the geoid data to match the DSM
|
|
457
|
+
output_geoid_data = np.empty(
|
|
458
|
+
alt_values.shape, dtype=in_geoid.dtypes[0]
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
reproject(
|
|
462
|
+
source=rio.band(in_geoid, 1),
|
|
463
|
+
destination=output_geoid_data,
|
|
464
|
+
src_transform=in_geoid.transform,
|
|
465
|
+
src_crs=in_geoid.crs,
|
|
466
|
+
dst_transform=transform,
|
|
467
|
+
dst_crs=crs,
|
|
468
|
+
resampling=Resampling.bilinear,
|
|
469
|
+
)
|
|
470
|
+
alt_values += output_geoid_data
|
|
471
|
+
|
|
427
472
|
nodata_color = None
|
|
428
473
|
nodata_classif = None
|
|
429
474
|
|
|
@@ -458,6 +503,7 @@ def filling_from_sensor_wrapper(
|
|
|
458
503
|
number_of_classification_bands = 0
|
|
459
504
|
classification_values = None
|
|
460
505
|
classification_band_names = None
|
|
506
|
+
|
|
461
507
|
if classification_file is not None:
|
|
462
508
|
if os.path.exists(classification_file):
|
|
463
509
|
with rio.open(classification_file) as classification_image:
|
|
@@ -538,8 +584,8 @@ def filling_from_sensor_wrapper(
|
|
|
538
584
|
classification_values_filled[band_index, :],
|
|
539
585
|
)
|
|
540
586
|
|
|
541
|
-
row_arr = np.array(range(
|
|
542
|
-
col_arr = np.array(range(
|
|
587
|
+
row_arr = np.array(range(row_min, row_max))
|
|
588
|
+
col_arr = np.array(range(col_min, col_max))
|
|
543
589
|
|
|
544
590
|
values = {}
|
|
545
591
|
coords = {cst.ROW: row_arr, cst.COL: col_arr}
|
|
@@ -568,6 +614,9 @@ def filling_from_sensor_wrapper(
|
|
|
568
614
|
values,
|
|
569
615
|
coords=coords,
|
|
570
616
|
)
|
|
617
|
+
|
|
618
|
+
profile.update(crs=crs.to_wkt())
|
|
619
|
+
|
|
571
620
|
cars_dataset.fill_dataset(
|
|
572
621
|
dataset,
|
|
573
622
|
saving_info=saving_info,
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
this module contains the AuxiliaryFillingFromSensors application class.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
+
from pyproj import CRS
|
|
25
26
|
from shapely.geometry import Polygon
|
|
26
27
|
|
|
27
|
-
from cars.core.projection import
|
|
28
|
+
from cars.core.projection import polygon_projection_crs
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
def compute_sensor_bounds(sensor_inputs, geom_plugin,
|
|
31
|
+
def compute_sensor_bounds(sensor_inputs, geom_plugin, output_crs):
|
|
31
32
|
"""
|
|
32
33
|
Compute bounds of each input sensor that have an associated color or
|
|
33
34
|
classification image
|
|
@@ -38,8 +39,8 @@ def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
|
|
|
38
39
|
:type geom_plugin: AbstractGeometry
|
|
39
40
|
:param geom_plugin: geometry plugin used for inverse locations
|
|
40
41
|
:type geom_plugin: AbstractGeometry
|
|
41
|
-
:param
|
|
42
|
-
:type
|
|
42
|
+
:param output_crs: crs of the output polygons
|
|
43
|
+
:type output_crs: CRS
|
|
43
44
|
|
|
44
45
|
:return: a dictionary containing a Polygon in output geometry for each
|
|
45
46
|
valid input sensor
|
|
@@ -59,8 +60,8 @@ def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
|
|
|
59
60
|
|
|
60
61
|
poly_geo = Polygon([u_l, u_r, l_r, l_l, u_l])
|
|
61
62
|
|
|
62
|
-
sensor_bounds[sensor_name] =
|
|
63
|
-
poly_geo, 4326,
|
|
63
|
+
sensor_bounds[sensor_name] = polygon_projection_crs(
|
|
64
|
+
poly_geo, CRS(4326), output_crs
|
|
64
65
|
)
|
|
65
66
|
|
|
66
67
|
return sensor_bounds
|
|
@@ -26,11 +26,11 @@ from abc import ABCMeta, abstractmethod
|
|
|
26
26
|
from typing import Dict
|
|
27
27
|
|
|
28
28
|
from cars.applications.application import Application
|
|
29
|
-
from cars.applications.application_template import
|
|
29
|
+
from cars.applications.application_template import ScalingApplicationTemplate
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
@Application.register("dem_generation")
|
|
33
|
-
class DemGeneration(
|
|
33
|
+
class DemGeneration(ScalingApplicationTemplate, metaclass=ABCMeta):
|
|
34
34
|
"""
|
|
35
35
|
DemGeneration
|
|
36
36
|
"""
|
|
@@ -38,13 +38,15 @@ class DemGeneration(ApplicationTemplate, metaclass=ABCMeta):
|
|
|
38
38
|
available_applications: Dict = {}
|
|
39
39
|
default_application = "bulldozer_on_raster"
|
|
40
40
|
|
|
41
|
-
def __new__(cls, conf=None): # pylint: disable=W0613
|
|
41
|
+
def __new__(cls, scaling_coeff, conf=None): # pylint: disable=W0613
|
|
42
42
|
"""
|
|
43
43
|
Return the required application
|
|
44
44
|
:raises:
|
|
45
45
|
- KeyError when the required application is not registered
|
|
46
46
|
|
|
47
47
|
:param orchestrator: orchestrator used
|
|
48
|
+
:param scaling_coeff: scaling factor for resolution
|
|
49
|
+
:type scaling_coeff: float
|
|
48
50
|
:param conf: configuration for resampling
|
|
49
51
|
:return: an application_to_use object
|
|
50
52
|
"""
|
|
@@ -84,15 +86,17 @@ class DemGeneration(ApplicationTemplate, metaclass=ABCMeta):
|
|
|
84
86
|
super().__init_subclass__(**kwargs)
|
|
85
87
|
cls.available_applications[short_name] = cls
|
|
86
88
|
|
|
87
|
-
def __init__(self, conf=None):
|
|
89
|
+
def __init__(self, scaling_coeff, conf=None):
|
|
88
90
|
"""
|
|
89
91
|
Init function of MntGeneration
|
|
90
92
|
|
|
93
|
+
:param scaling_coeff: scaling factor for resolution
|
|
94
|
+
:type scaling_coeff: float
|
|
91
95
|
:param conf: configuration
|
|
92
96
|
:return: an application_to_use object
|
|
93
97
|
"""
|
|
94
98
|
|
|
95
|
-
super().__init__(conf=conf)
|
|
99
|
+
super().__init__(scaling_coeff, conf=conf)
|
|
96
100
|
|
|
97
101
|
@abstractmethod
|
|
98
102
|
def run(self, triangulated_matches_list, output_dir):
|