cars 1.0.0a1__cp310-cp310-musllinux_1_2_i686.whl → 1.0.0a3__cp310-cp310-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/application.py +14 -6
- cars/applications/application_template.py +22 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +15 -10
- 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_wrappers.py +48 -25
- cars/applications/dem_generation/dichotomic_generation_app.py +27 -9
- cars/applications/dem_generation/rasterization_app.py +85 -32
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +4 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cpython-310-i386-linux-gnu.so +0 -0
- cars/applications/dense_match_filling/fill_disp_algo.py +41 -12
- cars/applications/dense_match_filling/plane_app.py +11 -0
- cars/applications/dense_match_filling/zero_padding_app.py +11 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +254 -548
- cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-310-i386-linux-gnu.so +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +59 -11
- cars/applications/dense_matching/dense_matching_wrappers.py +51 -31
- cars/applications/dense_matching/disparity_grid_algo.py +566 -0
- 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 +78 -1
- cars/applications/dsm_filling/border_interpolation_app.py +10 -5
- cars/applications/dsm_filling/bulldozer_filling_app.py +14 -7
- cars/applications/dsm_filling/exogenous_filling_app.py +10 -5
- cars/applications/grid_generation/grid_correction_app.py +0 -53
- cars/applications/grid_generation/transform_grid.py +5 -5
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +17 -11
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +3 -4
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +9 -5
- cars/applications/point_cloud_outlier_removal/small_components_app.py +5 -3
- cars/applications/point_cloud_outlier_removal/statistical_app.py +4 -2
- cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -0
- cars/applications/rasterization/rasterization_algo.py +20 -27
- cars/applications/rasterization/rasterization_wrappers.py +6 -5
- cars/applications/rasterization/simple_gaussian_app.py +30 -17
- cars/applications/resampling/resampling_algo.py +44 -49
- cars/applications/sparse_matching/sift_app.py +2 -22
- cars/applications/sparse_matching/sparse_matching_wrappers.py +0 -49
- cars/applications/triangulation/line_of_sight_intersection_app.py +1 -1
- cars/applications/triangulation/triangulation_wrappers.py +2 -1
- cars/bundleadjustment.py +51 -11
- cars/cars.py +15 -5
- cars/core/constants.py +1 -1
- cars/core/geometry/abstract_geometry.py +166 -12
- cars/core/geometry/shareloc_geometry.py +61 -14
- cars/core/inputs.py +15 -0
- cars/core/projection.py +117 -0
- cars/data_structures/cars_dataset.py +7 -5
- cars/orchestrator/cluster/log_wrapper.py +1 -1
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +1 -1
- cars/orchestrator/registry/saver_registry.py +0 -78
- cars/pipelines/default/default_pipeline.py +69 -52
- cars/pipelines/parameters/advanced_parameters.py +17 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +4 -0
- cars/pipelines/parameters/depth_map_inputs.py +22 -67
- cars/pipelines/parameters/dsm_inputs.py +16 -29
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +117 -24
- cars/pipelines/parameters/sensor_loaders/basic_sensor_loader.py +3 -3
- cars/pipelines/parameters/sensor_loaders/pivot_sensor_loader.py +2 -2
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +2 -2
- cars/pipelines/pipeline.py +8 -8
- cars/pipelines/unit/unit_pipeline.py +276 -274
- cars/starter.py +20 -1
- {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/METADATA +3 -2
- {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/RECORD +161 -158
- {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/WHEEL +0 -0
- {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/entry_points.txt +0 -0
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):
|
|
@@ -102,3 +102,25 @@ class ApplicationTemplate(metaclass=ABCMeta):
|
|
|
102
102
|
"""
|
|
103
103
|
|
|
104
104
|
return self.used_config
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ScalingApplicationTemplate(ApplicationTemplate, metaclass=ABCMeta):
|
|
108
|
+
"""
|
|
109
|
+
Template for applications requiring resolution scaling.
|
|
110
|
+
|
|
111
|
+
Inherits from ApplicationTemplate and adds the scaling coefficient
|
|
112
|
+
as a required argument.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(self, scaling_coeff, conf=None):
|
|
116
|
+
"""
|
|
117
|
+
Init function of ScalingApplicationTemplate
|
|
118
|
+
|
|
119
|
+
:param scaling_coeff: scaling factor for resolution
|
|
120
|
+
:type scaling_coeff: float
|
|
121
|
+
|
|
122
|
+
:param conf: configuration for application
|
|
123
|
+
:type conf: dict
|
|
124
|
+
"""
|
|
125
|
+
self.scaling_coeff = scaling_coeff
|
|
126
|
+
super().__init__(conf=conf)
|
|
@@ -30,6 +30,7 @@ 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
|
|
33
34
|
from shapely.geometry import Polygon
|
|
34
35
|
|
|
35
36
|
import cars.orchestrator.orchestrator as ocht
|
|
@@ -191,12 +192,15 @@ class AuxiliaryFillingFromSensors(
|
|
|
191
192
|
shutil.move(color_file, color_not_filled_file)
|
|
192
193
|
|
|
193
194
|
classification_not_filled_file = None
|
|
195
|
+
# classif_file could be defined without data attached
|
|
196
|
+
if classif_file is not None and not os.path.exists(classif_file):
|
|
197
|
+
classif_file = None
|
|
198
|
+
|
|
194
199
|
if classif_file is not None:
|
|
195
200
|
classification_not_filled_file = os.path.join(
|
|
196
201
|
dump_dir, "classification_not_filled.tif"
|
|
197
202
|
)
|
|
198
|
-
|
|
199
|
-
shutil.move(classif_file, classification_not_filled_file)
|
|
203
|
+
shutil.move(classif_file, classification_not_filled_file)
|
|
200
204
|
|
|
201
205
|
# Clean dump_dir at the end of processing if required
|
|
202
206
|
if not self.used_config["save_intermediate_data"]:
|
|
@@ -264,12 +268,12 @@ class AuxiliaryFillingFromSensors(
|
|
|
264
268
|
[saving_info] = self.orchestrator.get_saving_infos([aux_filled_image])
|
|
265
269
|
|
|
266
270
|
reference_transform = inputs.rasterio_get_transform(dsm_file)
|
|
267
|
-
|
|
271
|
+
reference_crs = inputs.rasterio_get_crs(dsm_file)
|
|
268
272
|
|
|
269
273
|
# Pre-compute sensor bounds of all sensors to filter sensors that do
|
|
270
274
|
# not intersect with tile in tasks
|
|
271
275
|
sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
|
|
272
|
-
sensor_inputs, geom_plugin,
|
|
276
|
+
sensor_inputs, geom_plugin, reference_crs
|
|
273
277
|
)
|
|
274
278
|
|
|
275
279
|
for row in range(aux_filled_image.shape[0]):
|
|
@@ -296,7 +300,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
296
300
|
pairing,
|
|
297
301
|
window,
|
|
298
302
|
reference_transform,
|
|
299
|
-
|
|
303
|
+
reference_crs,
|
|
300
304
|
full_saving_info,
|
|
301
305
|
geom_plugin,
|
|
302
306
|
texture_bands,
|
|
@@ -324,7 +328,7 @@ def filling_from_sensor_wrapper(
|
|
|
324
328
|
pairing,
|
|
325
329
|
window,
|
|
326
330
|
transform,
|
|
327
|
-
|
|
331
|
+
crs,
|
|
328
332
|
saving_info,
|
|
329
333
|
geom_plugin,
|
|
330
334
|
texture_bands,
|
|
@@ -351,8 +355,8 @@ def filling_from_sensor_wrapper(
|
|
|
351
355
|
:type window: dict
|
|
352
356
|
:param transform: input geo transform
|
|
353
357
|
:type transform: tuple
|
|
354
|
-
:param
|
|
355
|
-
:type
|
|
358
|
+
:param crs: input crs
|
|
359
|
+
:type crs: CRS
|
|
356
360
|
:param saving_info: saving info for cars orchestrator
|
|
357
361
|
:type saving_info: dict
|
|
358
362
|
:param geom_plugin: geometry plugin used for inverse locations
|
|
@@ -399,8 +403,8 @@ def filling_from_sensor_wrapper(
|
|
|
399
403
|
|
|
400
404
|
stacked_values = np.vstack([cols_values_2d.ravel(), rows_values_2d.ravel()])
|
|
401
405
|
|
|
402
|
-
lon_lat = projection.
|
|
403
|
-
stacked_values.transpose(),
|
|
406
|
+
lon_lat = projection.point_cloud_conversion_crs(
|
|
407
|
+
stacked_values.transpose(), crs, CRS(4326)
|
|
404
408
|
)
|
|
405
409
|
|
|
406
410
|
rio_window = rio.windows.Window.from_slices(
|
|
@@ -458,6 +462,7 @@ def filling_from_sensor_wrapper(
|
|
|
458
462
|
number_of_classification_bands = 0
|
|
459
463
|
classification_values = None
|
|
460
464
|
classification_band_names = None
|
|
465
|
+
|
|
461
466
|
if classification_file is not None:
|
|
462
467
|
if os.path.exists(classification_file):
|
|
463
468
|
with rio.open(classification_file) as classification_image:
|
|
@@ -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):
|
|
@@ -35,6 +35,7 @@ from affine import Affine
|
|
|
35
35
|
from rasterio.coords import BoundingBox
|
|
36
36
|
from rasterio.enums import Resampling
|
|
37
37
|
from rasterio.warp import calculate_default_transform, reproject
|
|
38
|
+
from scipy.ndimage import median_filter
|
|
38
39
|
|
|
39
40
|
from cars.core import preprocessing
|
|
40
41
|
|
|
@@ -243,7 +244,12 @@ def reverse_dem(input_dem):
|
|
|
243
244
|
out_dem.nodata = -nodata
|
|
244
245
|
|
|
245
246
|
|
|
246
|
-
def downsample_dem(
|
|
247
|
+
def downsample_dem(
|
|
248
|
+
input_dem,
|
|
249
|
+
scale,
|
|
250
|
+
median_filter_size=7,
|
|
251
|
+
default_alt=0,
|
|
252
|
+
):
|
|
247
253
|
"""
|
|
248
254
|
Downsample median DEM with median resampling
|
|
249
255
|
|
|
@@ -265,10 +271,10 @@ def downsample_dem(input_dem, scale):
|
|
|
265
271
|
metadata["transform"] = dst_transform
|
|
266
272
|
metadata["height"] = dst_height
|
|
267
273
|
metadata["width"] = dst_width
|
|
268
|
-
|
|
274
|
+
dem_data = np.zeros((dst_height, dst_width))
|
|
269
275
|
reproject(
|
|
270
276
|
data,
|
|
271
|
-
|
|
277
|
+
dem_data,
|
|
272
278
|
src_transform=src_transform,
|
|
273
279
|
src_crs=crs,
|
|
274
280
|
dst_transform=dst_transform,
|
|
@@ -277,23 +283,39 @@ def downsample_dem(input_dem, scale):
|
|
|
277
283
|
resampling=Resampling.med,
|
|
278
284
|
)
|
|
279
285
|
|
|
286
|
+
# Post-processing
|
|
287
|
+
|
|
288
|
+
# Median filter
|
|
289
|
+
dem_data = median_filter(dem_data, size=median_filter_size)
|
|
290
|
+
|
|
291
|
+
# Fill nodata
|
|
292
|
+
dem_data = rio.fill.fillnodata(
|
|
293
|
+
dem_data,
|
|
294
|
+
mask=~(dem_data == nodata),
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
dem_data[dem_data == nodata] = default_alt
|
|
298
|
+
|
|
280
299
|
with rio.open(input_dem, "w", **metadata) as dst:
|
|
281
|
-
dst.write(
|
|
300
|
+
dst.write(dem_data, 1)
|
|
282
301
|
|
|
283
302
|
|
|
284
|
-
def modify_terrain_bounds(
|
|
303
|
+
def modify_terrain_bounds(
|
|
304
|
+
bounds_poly, in_epsg, out_epsg, constant_margin, linear_margin=0
|
|
305
|
+
):
|
|
285
306
|
"""
|
|
286
307
|
Modify the terrain bounds
|
|
287
308
|
|
|
288
|
-
:param
|
|
289
|
-
:type
|
|
290
|
-
:param
|
|
291
|
-
:type
|
|
292
|
-
:param
|
|
309
|
+
:param bounds_poly: Input region of interest for DEM
|
|
310
|
+
:type bounds_poly: list
|
|
311
|
+
:param in_epsg: EPSG code of dem_roi_to_use
|
|
312
|
+
:type in_epsg: int
|
|
313
|
+
:param out_epsg: EPSG code of dem_roi_to_use
|
|
314
|
+
:type out_epsg: int
|
|
315
|
+
:param margin: Margin of the output ROI in meters
|
|
293
316
|
:type margin: int
|
|
294
317
|
"""
|
|
295
318
|
# Get bounds
|
|
296
|
-
bounds_poly = dem_roi_to_use.bounds
|
|
297
319
|
xmin = min(bounds_poly[0], bounds_poly[2])
|
|
298
320
|
xmax = max(bounds_poly[0], bounds_poly[2])
|
|
299
321
|
ymin = min(bounds_poly[1], bounds_poly[3])
|
|
@@ -301,24 +323,25 @@ def modify_terrain_bounds(dem_roi_to_use, epsg, margin):
|
|
|
301
323
|
|
|
302
324
|
bounds_cloud = [xmin, ymin, xmax, ymax]
|
|
303
325
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
326
|
+
if in_epsg == 4326:
|
|
327
|
+
# Convert resolution and margin to degrees
|
|
328
|
+
utm_epsg = preprocessing.get_utm_zone_as_epsg_code(xmin, ymin)
|
|
329
|
+
conversion_factor = preprocessing.get_conversion_factor(
|
|
330
|
+
bounds_cloud, 4326, utm_epsg
|
|
331
|
+
)
|
|
332
|
+
constant_margin *= conversion_factor
|
|
310
333
|
|
|
311
334
|
# Get borders, adding margin
|
|
312
|
-
xmin = xmin -
|
|
313
|
-
ymin = ymin -
|
|
314
|
-
xmax = xmax +
|
|
315
|
-
ymax = ymax +
|
|
335
|
+
xmin = xmin - constant_margin - linear_margin * (xmax - xmin)
|
|
336
|
+
ymin = ymin - constant_margin - linear_margin * (ymax - ymin)
|
|
337
|
+
xmax = xmax + constant_margin + linear_margin * (xmax - xmin)
|
|
338
|
+
ymax = ymax + constant_margin + linear_margin * (ymax - ymin)
|
|
316
339
|
|
|
317
340
|
terrain_bounds = [xmin, ymin, xmax, ymax]
|
|
318
341
|
|
|
319
|
-
if
|
|
320
|
-
crs_in = pyproj.CRS.from_epsg(
|
|
321
|
-
crs_out = pyproj.CRS.from_epsg(
|
|
342
|
+
if out_epsg != in_epsg:
|
|
343
|
+
crs_in = pyproj.CRS.from_epsg(in_epsg)
|
|
344
|
+
crs_out = pyproj.CRS.from_epsg(out_epsg)
|
|
322
345
|
|
|
323
346
|
transformer = pyproj.Transformer.from_crs(
|
|
324
347
|
crs_in, crs_out, always_xy=True
|
|
@@ -340,7 +363,7 @@ def modify_terrain_bounds(dem_roi_to_use, epsg, margin):
|
|
|
340
363
|
|
|
341
364
|
def reproject_dem(dsm_file_name, epsg_out, out_file_name):
|
|
342
365
|
"""
|
|
343
|
-
Reproject the
|
|
366
|
+
Reproject the DEM
|
|
344
367
|
|
|
345
368
|
:param dsm_file_name: the path to dsm
|
|
346
369
|
:type dsm_file_name: str
|
|
@@ -64,14 +64,16 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
64
64
|
|
|
65
65
|
# pylint: disable=too-many-instance-attributes
|
|
66
66
|
|
|
67
|
-
def __init__(self, conf=None):
|
|
67
|
+
def __init__(self, scaling_coeff, conf=None):
|
|
68
68
|
"""
|
|
69
69
|
Init function of DichotomicGeneration
|
|
70
70
|
|
|
71
|
+
:param scaling_coeff: scaling factor for resolution
|
|
72
|
+
:type scaling_coeff: float
|
|
71
73
|
:param conf: configuration for DichotomicGeneration
|
|
72
74
|
:return: an application_to_use object
|
|
73
75
|
"""
|
|
74
|
-
super().__init__(conf=conf)
|
|
76
|
+
super().__init__(scaling_coeff, conf=conf)
|
|
75
77
|
|
|
76
78
|
# check conf
|
|
77
79
|
self.used_method = self.used_config["method"]
|
|
@@ -175,11 +177,13 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
175
177
|
self,
|
|
176
178
|
triangulated_matches_list,
|
|
177
179
|
output_dir,
|
|
178
|
-
|
|
180
|
+
input_geoid,
|
|
181
|
+
output_geoid,
|
|
179
182
|
dem_roi_to_use=None,
|
|
180
183
|
initial_elevation=None,
|
|
184
|
+
default_alt=0,
|
|
181
185
|
cars_orchestrator=None,
|
|
182
|
-
):
|
|
186
|
+
): # pylint: disable=W0613
|
|
183
187
|
"""
|
|
184
188
|
Run dichotomic dem generation using matches
|
|
185
189
|
|
|
@@ -188,7 +192,8 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
188
192
|
:type triangulated_matches_list: list(pandas.Dataframe)
|
|
189
193
|
:param output_dir: directory to save dem
|
|
190
194
|
:type output_dir: str
|
|
191
|
-
:param
|
|
195
|
+
:param input_geoid: input geoid path
|
|
196
|
+
:param output_geoid: output geoid path
|
|
192
197
|
:param cars_orchrestrator: the main cars orchestrator
|
|
193
198
|
:param dem_roi_to_use: dem roi polygon to use as roi
|
|
194
199
|
:param initial_elevation: the path to the initial elevation file
|
|
@@ -208,6 +213,11 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
208
213
|
# Generate point cloud
|
|
209
214
|
epsg = 4326
|
|
210
215
|
|
|
216
|
+
# Optimize the case when input and output geoid are the same
|
|
217
|
+
if output_geoid is True:
|
|
218
|
+
input_geoid = False
|
|
219
|
+
output_geoid = False
|
|
220
|
+
|
|
211
221
|
for pair_pc in triangulated_matches_list:
|
|
212
222
|
# convert to degrees for geoid offset
|
|
213
223
|
if pair_pc.attrs["epsg"] != epsg:
|
|
@@ -312,9 +322,14 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
312
322
|
# Transform to lon lat
|
|
313
323
|
projection.point_cloud_conversion_dataset(alti_zeros_dataset, 4326)
|
|
314
324
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
325
|
+
if input_geoid:
|
|
326
|
+
input_geoid = triangulation_wrappers.geoid_offset(
|
|
327
|
+
alti_zeros_dataset, input_geoid
|
|
328
|
+
)
|
|
329
|
+
if output_geoid:
|
|
330
|
+
output_geoid = triangulation_wrappers.geoid_offset(
|
|
331
|
+
alti_zeros_dataset, output_geoid
|
|
332
|
+
)
|
|
318
333
|
|
|
319
334
|
# fillnodata
|
|
320
335
|
valid = np.isfinite(list_z_grid[0])
|
|
@@ -323,7 +338,10 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
|
|
|
323
338
|
list_z_grid[idx] = rasterio.fill.fillnodata(
|
|
324
339
|
list_z_grid[idx], mask=valid, max_search_distance=msd
|
|
325
340
|
)
|
|
326
|
-
|
|
341
|
+
if input_geoid:
|
|
342
|
+
list_z_grid[idx] += input_geoid[cst.Z].values
|
|
343
|
+
if output_geoid:
|
|
344
|
+
list_z_grid[idx] -= output_geoid[cst.Z].values
|
|
327
345
|
|
|
328
346
|
dem_median = list_z_grid[0]
|
|
329
347
|
dem_min = list_z_grid[1]
|