cars 0.12.0rc2__cp311-cp311-win_amd64.whl → 1.0.0a2__cp311-cp311-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 +4 -4
- cars/applications/auxiliary_filling/__init__.py +2 -2
- cars/applications/auxiliary_filling/{auxiliary_filling_tools.py → auxiliary_filling_algo.py} +129 -170
- cars/applications/auxiliary_filling/{auxiliary_filling_from_sensors.py → auxiliary_filling_from_sensors_app.py} +34 -21
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +89 -0
- cars/applications/dem_generation/__init__.py +4 -2
- cars/applications/dem_generation/dem_generation_algo.py +232 -0
- cars/applications/dem_generation/dem_generation_wrappers.py +380 -0
- cars/applications/dem_generation/{dichotomic_generation.py → dichotomic_generation_app.py} +30 -175
- cars/applications/dem_generation/rasterization_app.py +538 -0
- cars/applications/dense_match_filling/__init__.py +2 -2
- cars/applications/dense_match_filling/{dense_match_filling.py → abstract_dense_match_filling_app.py} +5 -1
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.pyd +0 -0
- cars/applications/dense_match_filling/fill_disp_algo.py +457 -0
- cars/applications/dense_match_filling/fill_disp_wrappers.py +426 -0
- cars/applications/dense_match_filling/{plane.py → plane_app.py} +27 -13
- cars/applications/dense_match_filling/{zero_padding.py → zero_padding_app.py} +19 -6
- cars/applications/dense_matching/__init__.py +4 -2
- cars/applications/dense_matching/{dense_matching.py → abstract_dense_matching_app.py} +7 -3
- cars/applications/dense_matching/{census_mccnn_sgm.py → census_mccnn_sgm_app.py} +404 -546
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.pyd +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.py +11 -2
- cars/applications/dense_matching/cpp/includes/dense_matching.hpp +4 -2
- cars/applications/dense_matching/cpp/src/dense_matching.cpp +25 -8
- cars/applications/dense_matching/dense_matching_algo.py +304 -0
- cars/applications/dense_matching/{dense_matching_tools.py → dense_matching_wrappers.py} +161 -243
- cars/applications/dense_matching/disparity_grid_algo.py +572 -0
- cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +2 -1
- cars/applications/dense_matching/loaders/pandora_loader.py +13 -11
- cars/applications/dsm_filling/__init__.py +6 -2
- cars/applications/dsm_filling/{border_interpolation.py → border_interpolation_app.py} +1 -1
- cars/applications/dsm_filling/{bulldozer_filling.py → bulldozer_filling_app.py} +1 -1
- cars/applications/dsm_filling/{exogenous_filling.py → exogenous_filling_app.py} +1 -1
- cars/applications/grid_generation/__init__.py +4 -2
- cars/applications/grid_generation/{epipolar_grid_generation.py → epipolar_grid_generation_app.py} +29 -46
- cars/applications/grid_generation/{grid_correction.py → grid_correction_app.py} +52 -104
- cars/applications/grid_generation/{grids.py → grid_generation_algo.py} +8 -13
- cars/applications/grid_generation/{grid_constants.py → grid_generation_constants.py} +2 -1
- cars/applications/grid_generation/transform_grid.py +88 -0
- cars/applications/ground_truth_reprojection/__init__.py +2 -2
- cars/applications/ground_truth_reprojection/{ground_truth_reprojection.py → abstract_ground_truth_reprojection_app.py} +1 -1
- cars/applications/ground_truth_reprojection/{direct_localization.py → direct_localization_app.py} +15 -12
- cars/applications/ground_truth_reprojection/{ground_truth_reprojection_tools.py → ground_truth_reprojection_algo.py} +2 -2
- cars/applications/hole_detection/__init__.py +4 -2
- cars/applications/hole_detection/{cloud_to_bbox.py → cloud_to_bbox_app.py} +9 -7
- cars/applications/hole_detection/{hole_detection_tools.py → hole_detection_algo.py} +4 -27
- cars/applications/hole_detection/hole_detection_wrappers.py +53 -0
- cars/applications/point_cloud_denoising/__init__.py +2 -2
- cars/applications/point_cloud_fusion/__init__.py +2 -2
- cars/applications/point_cloud_fusion/{point_cloud_fusion.py → abstract_pc_fusion_app.py} +1 -1
- cars/applications/point_cloud_fusion/{mapping_to_terrain_tiles.py → mapping_to_terrain_tiles_app.py} +12 -12
- cars/applications/point_cloud_fusion/{pc_tif_tools.py → pc_fusion_algo.py} +519 -434
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +869 -0
- cars/applications/point_cloud_outlier_removal/__init__.py +2 -2
- cars/applications/point_cloud_outlier_removal/{pc_out_removal.py → abstract_outlier_removal_app.py} +1 -1
- cars/applications/point_cloud_outlier_removal/{outlier_removal_tools.py → outlier_removal_algo.py} +1 -6
- cars/applications/point_cloud_outlier_removal/{small_components.py → small_components_app.py} +37 -18
- cars/applications/point_cloud_outlier_removal/{statistical.py → statistical_app.py} +11 -10
- cars/applications/rasterization/__init__.py +2 -2
- cars/applications/rasterization/rasterization_algo.py +522 -0
- cars/applications/rasterization/rasterization_constants.py +1 -1
- cars/applications/rasterization/{rasterization_tools.py → rasterization_wrappers.py} +10 -496
- cars/applications/rasterization/{simple_gaussian.py → simple_gaussian_app.py} +50 -45
- cars/applications/resampling/__init__.py +2 -2
- cars/applications/resampling/{resampling.py → abstract_resampling_app.py} +12 -3
- cars/applications/resampling/{bicubic_resampling.py → bicubic_resampling_app.py} +102 -382
- cars/applications/resampling/resampling_algo.py +563 -0
- cars/applications/resampling/resampling_wrappers.py +296 -0
- cars/applications/sparse_matching/__init__.py +4 -2
- cars/applications/sparse_matching/{sparse_matching.py → abstract_sparse_matching_app.py} +13 -11
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/applications/sparse_matching/{sift.py → sift_app.py} +79 -8
- cars/applications/sparse_matching/sparse_matching_algo.py +326 -0
- cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
- cars/applications/triangulation/__init__.py +4 -2
- cars/applications/triangulation/{triangulation.py → abstract_triangulation_app.py} +3 -3
- cars/applications/triangulation/{line_of_sight_intersection.py → line_of_sight_intersection_app.py} +50 -54
- cars/applications/triangulation/{triangulation_tools.py → triangulation_algo.py} +9 -232
- cars/applications/triangulation/triangulation_wrappers.py +258 -0
- cars/bundleadjustment.py +54 -13
- cars/cars.py +25 -9
- cars/core/constants.py +12 -6
- cars/core/datasets.py +13 -18
- cars/core/geometry/abstract_geometry.py +138 -84
- cars/core/geometry/shareloc_geometry.py +74 -31
- cars/core/inputs.py +10 -3
- cars/core/preprocessing.py +30 -42
- cars/core/projection.py +1 -0
- cars/data_structures/cars_dataset.py +2 -2
- cars/devibrate.py +1 -1
- cars/extractroi.py +44 -13
- cars/orchestrator/cluster/log_wrapper.py +7 -2
- cars/orchestrator/cluster/sequential_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +18 -9
- cars/orchestrator/registry/saver_registry.py +0 -78
- cars/pipelines/conf_resolution/conf_final_resolution.json +7 -0
- cars/pipelines/conf_resolution/conf_first_resolution.json +1 -0
- cars/pipelines/conf_resolution/conf_intermediate_resolution.json +1 -0
- cars/pipelines/default/default_pipeline.py +470 -2185
- cars/pipelines/parameters/advanced_parameters.py +71 -3
- cars/pipelines/parameters/advanced_parameters_constants.py +6 -0
- cars/pipelines/parameters/depth_map_inputs.py +23 -68
- cars/pipelines/parameters/dsm_inputs.py +18 -30
- cars/pipelines/parameters/output_constants.py +5 -1
- cars/pipelines/parameters/output_parameters.py +23 -5
- cars/pipelines/parameters/sensor_inputs.py +89 -66
- cars/pipelines/parameters/sensor_inputs_constants.py +1 -1
- cars/pipelines/parameters/sensor_loaders/__init__.py +27 -0
- cars/pipelines/parameters/sensor_loaders/basic_sensor_loader.py +108 -0
- cars/pipelines/parameters/sensor_loaders/pivot_sensor_loader.py +130 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +95 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +73 -0
- cars/pipelines/pipeline.py +8 -8
- cars/pipelines/pipeline_template.py +3 -27
- cars/pipelines/unit/__init__.py +26 -0
- cars/pipelines/unit/unit_pipeline.py +3039 -0
- cars/starter.py +20 -1
- cars-1.0.0a2.dist-info/DELVEWHEEL +2 -0
- {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/METADATA +4 -3
- cars-1.0.0a2.dist-info/RECORD +222 -0
- cars.libs/{libgcc_s_seh-1-5dff426d781f17f961e57918b62ba809.dll → libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll} +0 -0
- cars.libs/{libstdc++-6-45391cced8aa80fea5519d684c730dc3.dll → libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll} +0 -0
- cars/applications/dem_generation/dem_generation_tools.py +0 -127
- cars/applications/dem_generation/rasterization.py +0 -769
- cars/applications/dense_match_filling/fill_disp_tools.py +0 -813
- cars/applications/point_cloud_fusion/point_cloud_tools.py +0 -934
- cars/applications/resampling/resampling_tools.py +0 -484
- cars/applications/sparse_matching/pandora_sparse_matching.py +0 -814
- cars/applications/sparse_matching/sparse_matching_tools.py +0 -910
- cars-0.12.0rc2.dist-info/DELVEWHEEL +0 -2
- cars-0.12.0rc2.dist-info/RECORD +0 -201
- /cars/applications/auxiliary_filling/{auxiliary_filling.py → abstract_auxiliary_filling_app.py} +0 -0
- /cars/applications/dem_generation/{dem_generation.py → abstract_dem_generation_app.py} +0 -0
- /cars/applications/dsm_filling/{dsm_filling.py → abstract_dsm_filling_app.py} +0 -0
- /cars/applications/grid_generation/{grid_generation.py → abstract_grid_generation_app.py} +0 -0
- /cars/applications/hole_detection/{hole_detection.py → abstract_hole_detection_app.py} +0 -0
- /cars/applications/point_cloud_denoising/{point_cloud_denoising.py → abstract_pc_denoising_app.py} +0 -0
- /cars/applications/point_cloud_outlier_removal/{point_removal_constants.py → outlier_removal_constants.py} +0 -0
- /cars/applications/rasterization/{point_cloud_rasterization.py → abstract_pc_rasterization_app.py} +0 -0
- {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/WHEEL +0 -0
- {cars-0.12.0rc2.dist-info → cars-1.0.0a2.dist-info}/entry_points.txt +0 -0
- /cars.libs/{libwinpthread-1-9fce0fc5eca62fc2578af36d8585939c.dll → libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll} +0 -0
cars/__init__.py
CHANGED
|
@@ -24,14 +24,14 @@ Cars module init file
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
# start delvewheel patch
|
|
27
|
-
def
|
|
27
|
+
def _delvewheel_patch_1_11_1():
|
|
28
28
|
import os
|
|
29
29
|
if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'cars.libs'))):
|
|
30
30
|
os.add_dll_directory(libs_dir)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
del
|
|
33
|
+
_delvewheel_patch_1_11_1()
|
|
34
|
+
del _delvewheel_patch_1_11_1
|
|
35
35
|
# end delvewheel patch
|
|
36
36
|
|
|
37
37
|
import os
|
|
@@ -83,4 +83,4 @@ def import_plugins() -> None:
|
|
|
83
83
|
entry_point.load()
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
import_plugins()
|
|
86
|
+
import_plugins()
|
|
@@ -23,7 +23,7 @@ CARS auxiliary filling module init file
|
|
|
23
23
|
"""
|
|
24
24
|
# flake8: noqa: F401
|
|
25
25
|
|
|
26
|
-
import cars.applications.auxiliary_filling.
|
|
27
|
-
from cars.applications.auxiliary_filling.
|
|
26
|
+
import cars.applications.auxiliary_filling.abstract_auxiliary_filling_app
|
|
27
|
+
from cars.applications.auxiliary_filling.auxiliary_filling_from_sensors_app import ( # pylint: disable=C0301
|
|
28
28
|
AuxiliaryFilling,
|
|
29
29
|
)
|
cars/applications/auxiliary_filling/{auxiliary_filling_tools.py → auxiliary_filling_algo.py}
RENAMED
|
@@ -26,9 +26,6 @@ this module contains the AuxiliaryFillingFromSensors application class.
|
|
|
26
26
|
import numpy as np
|
|
27
27
|
import rasterio as rio
|
|
28
28
|
from scipy import interpolate
|
|
29
|
-
from shapely.geometry import Polygon
|
|
30
|
-
|
|
31
|
-
from cars.core.projection import polygon_projection
|
|
32
29
|
|
|
33
30
|
|
|
34
31
|
def fill_auxiliary(
|
|
@@ -40,7 +37,8 @@ def fill_auxiliary(
|
|
|
40
37
|
geom_plugin,
|
|
41
38
|
number_of_color_bands,
|
|
42
39
|
number_of_classification_bands,
|
|
43
|
-
|
|
40
|
+
texture_bands,
|
|
41
|
+
texture_interpolator,
|
|
44
42
|
use_mask=False,
|
|
45
43
|
):
|
|
46
44
|
"""
|
|
@@ -63,9 +61,11 @@ def fill_auxiliary(
|
|
|
63
61
|
:type number_of_color_bands: int
|
|
64
62
|
:param number_of_classification_bands: number of bands in the color image
|
|
65
63
|
:type number_of_classification_bands: int
|
|
66
|
-
:param
|
|
64
|
+
:param texture_bands: list of band names used for output texture
|
|
65
|
+
:type texture_bands: list
|
|
66
|
+
:param texture_interpolator: scipy interpolator use to interpolate color
|
|
67
67
|
values
|
|
68
|
-
:type
|
|
68
|
+
:type texture_interpolator: str
|
|
69
69
|
:param use_mask: use mask information from sensors in color computation
|
|
70
70
|
:type use_mask: bool
|
|
71
71
|
|
|
@@ -107,7 +107,8 @@ def fill_auxiliary(
|
|
|
107
107
|
geom_plugin,
|
|
108
108
|
number_of_color_bands,
|
|
109
109
|
number_of_classification_bands,
|
|
110
|
-
|
|
110
|
+
texture_bands,
|
|
111
|
+
texture_interpolator,
|
|
111
112
|
not_interpolated_mask=None,
|
|
112
113
|
use_mask=use_mask,
|
|
113
114
|
return_all_points=True,
|
|
@@ -132,7 +133,8 @@ def fill_auxiliary(
|
|
|
132
133
|
geom_plugin,
|
|
133
134
|
number_of_color_bands,
|
|
134
135
|
number_of_classification_bands,
|
|
135
|
-
|
|
136
|
+
texture_bands,
|
|
137
|
+
texture_interpolator,
|
|
136
138
|
not_interpolated_mask,
|
|
137
139
|
use_mask=use_mask,
|
|
138
140
|
return_all_points=False,
|
|
@@ -165,7 +167,8 @@ def fill_from_one_sensor( # noqa C901
|
|
|
165
167
|
geom_plugin,
|
|
166
168
|
number_of_color_bands,
|
|
167
169
|
number_of_classification_bands,
|
|
168
|
-
|
|
170
|
+
texture_bands,
|
|
171
|
+
texture_interpolator,
|
|
169
172
|
not_interpolated_mask=None,
|
|
170
173
|
use_mask=False,
|
|
171
174
|
return_all_points=False,
|
|
@@ -194,9 +197,11 @@ def fill_from_one_sensor( # noqa C901
|
|
|
194
197
|
:type number_of_color_bands: int
|
|
195
198
|
:param number_of_classification_bands: number of bands in the color image
|
|
196
199
|
:type number_of_classification_bands: int
|
|
197
|
-
:param
|
|
200
|
+
:param texture_bands: list of band names used for output texture
|
|
201
|
+
:type texture_bands: list
|
|
202
|
+
:param texture_interpolator: scipy interpolator use to interpolate color
|
|
198
203
|
values
|
|
199
|
-
:type
|
|
204
|
+
:type texture_interpolator: str
|
|
200
205
|
:param not_interpolated_mask: use mask information in color computation
|
|
201
206
|
:type not_interpolated_mask: numpy.array
|
|
202
207
|
:param use_mask: use mask information in color computation
|
|
@@ -207,9 +212,7 @@ def fill_from_one_sensor( # noqa C901
|
|
|
207
212
|
"""
|
|
208
213
|
|
|
209
214
|
# Check if the sensor has color or classification
|
|
210
|
-
reference_sensor_image = sensor
|
|
211
|
-
"color", sensor.get("classification", None)
|
|
212
|
-
)
|
|
215
|
+
reference_sensor_image = sensor["image"]["main_file"]
|
|
213
216
|
|
|
214
217
|
output_not_interpolated_mask = np.ones(len(altitudes), dtype=bool)
|
|
215
218
|
all_values = np.zeros((number_of_color_bands, len(altitudes)))
|
|
@@ -251,12 +254,12 @@ def fill_from_one_sensor( # noqa C901
|
|
|
251
254
|
):
|
|
252
255
|
return output_not_interpolated_mask, all_values
|
|
253
256
|
|
|
254
|
-
if
|
|
255
|
-
|
|
256
|
-
elif
|
|
257
|
-
|
|
257
|
+
if texture_interpolator in ("linear", "nearest"):
|
|
258
|
+
texture_interpolator_margin = 1
|
|
259
|
+
elif texture_interpolator == "cubic":
|
|
260
|
+
texture_interpolator_margin = 3
|
|
258
261
|
else:
|
|
259
|
-
raise RuntimeError(f"Invalid interpolator {
|
|
262
|
+
raise RuntimeError(f"Invalid interpolator {texture_interpolator}")
|
|
260
263
|
|
|
261
264
|
# Classification interpolator is always nearest
|
|
262
265
|
classif_interpolator = "nearest"
|
|
@@ -308,100 +311,112 @@ def fill_from_one_sensor( # noqa C901
|
|
|
308
311
|
validity_mask, not_interpolated_mask
|
|
309
312
|
)
|
|
310
313
|
|
|
311
|
-
if sensor.get("
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
314
|
+
if sensor.get("image"):
|
|
315
|
+
# Only fill color if all texture bands are present
|
|
316
|
+
if all(
|
|
317
|
+
band_name in sensor["image"]["bands"] for band_name in texture_bands
|
|
318
|
+
):
|
|
319
|
+
with rio.open(sensor["image"]["main_file"]) as sensor_color_image:
|
|
317
320
|
first_row = np.floor(
|
|
318
|
-
max(
|
|
321
|
+
max(
|
|
322
|
+
np.min(ind_rows_sensor) - texture_interpolator_margin, 0
|
|
323
|
+
)
|
|
319
324
|
)
|
|
320
325
|
last_row = np.ceil(
|
|
321
326
|
min(
|
|
322
|
-
np.max(ind_rows_sensor) +
|
|
327
|
+
np.max(ind_rows_sensor) + texture_interpolator_margin,
|
|
323
328
|
sensor_color_image.height,
|
|
324
329
|
)
|
|
325
330
|
)
|
|
326
331
|
first_col = np.floor(
|
|
327
|
-
max(
|
|
332
|
+
max(
|
|
333
|
+
np.min(ind_cols_sensor) - texture_interpolator_margin, 0
|
|
334
|
+
)
|
|
328
335
|
)
|
|
329
336
|
last_col = np.ceil(
|
|
330
337
|
min(
|
|
331
|
-
np.max(ind_cols_sensor) +
|
|
338
|
+
np.max(ind_cols_sensor) + texture_interpolator_margin,
|
|
332
339
|
sensor_color_image.width,
|
|
333
340
|
)
|
|
334
341
|
)
|
|
335
342
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
343
|
+
rio_window = rio.windows.Window.from_slices(
|
|
344
|
+
(first_row, last_row),
|
|
345
|
+
(first_col, last_col),
|
|
346
|
+
)
|
|
340
347
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
348
|
+
sensor_points = (
|
|
349
|
+
np.arange(first_row, last_row),
|
|
350
|
+
np.arange(first_col, last_col),
|
|
351
|
+
)
|
|
345
352
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
353
|
+
if validity_mask is not None:
|
|
354
|
+
interpolated_mask = validity_mask
|
|
355
|
+
else:
|
|
356
|
+
interpolated_mask = np.ones(len(altitudes), dtype=bool)
|
|
350
357
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
358
|
+
for output_band, band_name in enumerate(texture_bands):
|
|
359
|
+
# rio band convention
|
|
360
|
+
sensor_file = rio.open(
|
|
361
|
+
sensor["image"]["bands"][band_name]["path"]
|
|
362
|
+
)
|
|
363
|
+
input_band = sensor["image"]["bands"][band_name]["band"]
|
|
364
|
+
sensor_data = sensor_file.read(
|
|
365
|
+
input_band + 1, window=rio_window
|
|
366
|
+
)
|
|
356
367
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
)
|
|
366
|
-
band_values = all_values[band, validity_mask]
|
|
367
|
-
# No need to interpolate on every points
|
|
368
|
-
else:
|
|
369
|
-
band_values = interpolate.interpn(
|
|
370
|
-
sensor_points,
|
|
371
|
-
sensor_data,
|
|
372
|
-
(
|
|
373
|
-
ind_rows_sensor[validity_mask],
|
|
374
|
-
ind_cols_sensor[validity_mask],
|
|
375
|
-
),
|
|
376
|
-
bounds_error=False,
|
|
377
|
-
method=color_interpolator,
|
|
378
|
-
)
|
|
379
|
-
nan_values = np.isnan(band_values)
|
|
380
|
-
interpolated_mask[validity_mask] = np.logical_or(
|
|
381
|
-
interpolated_mask[validity_mask], ~nan_values
|
|
368
|
+
if validity_mask is not None:
|
|
369
|
+
if return_all_points is True:
|
|
370
|
+
all_values[output_band, :] = interpolate.interpn(
|
|
371
|
+
sensor_points,
|
|
372
|
+
sensor_data,
|
|
373
|
+
(ind_rows_sensor, ind_cols_sensor),
|
|
374
|
+
bounds_error=False,
|
|
375
|
+
method=texture_interpolator,
|
|
382
376
|
)
|
|
383
|
-
|
|
384
|
-
|
|
377
|
+
band_values = all_values[output_band, validity_mask]
|
|
378
|
+
# No need to interpolate on every points
|
|
385
379
|
else:
|
|
386
380
|
band_values = interpolate.interpn(
|
|
387
381
|
sensor_points,
|
|
388
382
|
sensor_data,
|
|
389
|
-
(
|
|
383
|
+
(
|
|
384
|
+
ind_rows_sensor[validity_mask],
|
|
385
|
+
ind_cols_sensor[validity_mask],
|
|
386
|
+
),
|
|
390
387
|
bounds_error=False,
|
|
391
|
-
method=
|
|
388
|
+
method=texture_interpolator,
|
|
392
389
|
)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
390
|
+
nan_values = np.isnan(band_values)
|
|
391
|
+
interpolated_mask[validity_mask] = np.logical_or(
|
|
392
|
+
interpolated_mask[validity_mask], ~nan_values
|
|
393
|
+
)
|
|
394
|
+
filled_color[output_band, interpolated_mask] += band_values
|
|
398
395
|
|
|
399
|
-
|
|
396
|
+
else:
|
|
397
|
+
band_values = interpolate.interpn(
|
|
398
|
+
sensor_points,
|
|
399
|
+
sensor_data,
|
|
400
|
+
(ind_rows_sensor, ind_cols_sensor),
|
|
401
|
+
bounds_error=False,
|
|
402
|
+
method=texture_interpolator,
|
|
403
|
+
)
|
|
404
|
+
interpolated_mask = np.logical_or(
|
|
405
|
+
interpolated_mask, ~np.isnan(band_values)
|
|
406
|
+
)
|
|
407
|
+
filled_color[output_band, interpolated_mask] += band_values
|
|
408
|
+
output_not_interpolated_mask = ~interpolated_mask
|
|
409
|
+
|
|
410
|
+
weights[interpolated_mask] += 1
|
|
400
411
|
|
|
401
412
|
if filled_classif is not None and sensor.get("classification"):
|
|
402
|
-
|
|
413
|
+
if number_of_classification_bands == len(
|
|
414
|
+
sensor["classification"]["bands"]
|
|
415
|
+
):
|
|
416
|
+
with rio.open(
|
|
417
|
+
sensor["classification"]["main_file"]
|
|
418
|
+
) as sensor_classif_image:
|
|
403
419
|
|
|
404
|
-
if sensor_classif_image.count == number_of_classification_bands:
|
|
405
420
|
first_row = np.floor(
|
|
406
421
|
max(
|
|
407
422
|
np.min(ind_rows_sensor) - classif_interpolator_margin, 0
|
|
@@ -425,95 +440,39 @@ def fill_from_one_sensor( # noqa C901
|
|
|
425
440
|
)
|
|
426
441
|
)
|
|
427
442
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
443
|
+
rio_window = rio.windows.Window.from_slices(
|
|
444
|
+
(first_row, last_row),
|
|
445
|
+
(first_col, last_col),
|
|
446
|
+
)
|
|
432
447
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
448
|
+
sensor_points = (
|
|
449
|
+
np.arange(first_row, last_row),
|
|
450
|
+
np.arange(first_col, last_col),
|
|
451
|
+
)
|
|
437
452
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
453
|
+
for output_band, band_name in enumerate(
|
|
454
|
+
sensor["classification"]["bands"]
|
|
455
|
+
):
|
|
456
|
+
# rio band convention
|
|
457
|
+
sensor_file = rio.open(
|
|
458
|
+
sensor["classification"]["bands"][band_name]["path"]
|
|
459
|
+
)
|
|
460
|
+
input_band = sensor["classification"]["bands"][band_name][
|
|
461
|
+
"band"
|
|
462
|
+
]
|
|
463
|
+
sensor_data = sensor_file.read(
|
|
464
|
+
input_band + 1, window=rio_window
|
|
465
|
+
)
|
|
443
466
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
467
|
+
filled_classif[output_band, :] = np.logical_or(
|
|
468
|
+
filled_classif[output_band, :],
|
|
469
|
+
interpolate.interpn(
|
|
470
|
+
sensor_points,
|
|
471
|
+
sensor_data,
|
|
472
|
+
(ind_rows_sensor, ind_cols_sensor),
|
|
473
|
+
bounds_error=False,
|
|
474
|
+
method=classif_interpolator,
|
|
475
|
+
),
|
|
476
|
+
)
|
|
454
477
|
|
|
455
478
|
return output_not_interpolated_mask, all_values
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
|
|
459
|
-
"""
|
|
460
|
-
Compute bounds of each input sensor that have an associated color or
|
|
461
|
-
classification image
|
|
462
|
-
|
|
463
|
-
:param sensor_inputs: dictionary containing paths to input images and models
|
|
464
|
-
:type sensor_inputs: dict
|
|
465
|
-
:param geom_plugin: geometry plugin used for inverse locations
|
|
466
|
-
:type geom_plugin: AbstractGeometry
|
|
467
|
-
:param geom_plugin: geometry plugin used for inverse locations
|
|
468
|
-
:type geom_plugin: AbstractGeometry
|
|
469
|
-
:param output_epsg: epsg of the output polygons
|
|
470
|
-
:type output_epsg: int
|
|
471
|
-
|
|
472
|
-
:return: a dictionary containing a Polygon in output geometry for each
|
|
473
|
-
valid input sensor
|
|
474
|
-
"""
|
|
475
|
-
|
|
476
|
-
sensor_bounds = {}
|
|
477
|
-
|
|
478
|
-
for sensor_name, sensor in sensor_inputs.items():
|
|
479
|
-
reference_sensor_image = sensor.get(
|
|
480
|
-
"color", sensor.get("classification", None)
|
|
481
|
-
)
|
|
482
|
-
# no data for this sensor, no need to compute its bounds
|
|
483
|
-
if reference_sensor_image is None:
|
|
484
|
-
continue
|
|
485
|
-
|
|
486
|
-
u_l, u_r, l_r, l_l = geom_plugin.image_envelope(
|
|
487
|
-
reference_sensor_image, sensor["geomodel"]
|
|
488
|
-
)
|
|
489
|
-
|
|
490
|
-
poly_geo = Polygon([u_l, u_r, l_r, l_l, u_l])
|
|
491
|
-
|
|
492
|
-
sensor_bounds[sensor_name] = polygon_projection(
|
|
493
|
-
poly_geo, 4326, output_epsg
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
return sensor_bounds
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
def filter_sensor_inputs(sensor_inputs, sensor_bounds, ground_polygon):
|
|
500
|
-
"""
|
|
501
|
-
Filter input sensors by comparing their bounds to a reference Polygon
|
|
502
|
-
|
|
503
|
-
:param sensor_inputs: dictionary containing paths to input images and models
|
|
504
|
-
:type sensor_inputs: dict
|
|
505
|
-
:param sensor_bounds: dictionary containing bounds of input sensors
|
|
506
|
-
:type sensor_bounds: dict
|
|
507
|
-
:param ground_polygon: reference polygon, in ground geometry
|
|
508
|
-
:type ground_polygon: Polygon
|
|
509
|
-
|
|
510
|
-
:return: a fitlered version of sensor_inputs
|
|
511
|
-
"""
|
|
512
|
-
|
|
513
|
-
filtered_sensor_inputs = sensor_inputs.copy()
|
|
514
|
-
|
|
515
|
-
for sensor_name, bound in sensor_bounds.items():
|
|
516
|
-
if not bound.intersects(ground_polygon):
|
|
517
|
-
del filtered_sensor_inputs[sensor_name]
|
|
518
|
-
|
|
519
|
-
return filtered_sensor_inputs
|
|
@@ -33,10 +33,13 @@ from json_checker import Checker
|
|
|
33
33
|
from shapely.geometry import Polygon
|
|
34
34
|
|
|
35
35
|
import cars.orchestrator.orchestrator as ocht
|
|
36
|
-
from cars.applications.auxiliary_filling import
|
|
36
|
+
from cars.applications.auxiliary_filling import (
|
|
37
|
+
auxiliary_filling_algo,
|
|
38
|
+
auxiliary_filling_wrappers,
|
|
39
|
+
)
|
|
37
40
|
|
|
38
41
|
# CARS imports
|
|
39
|
-
from cars.applications.auxiliary_filling.
|
|
42
|
+
from cars.applications.auxiliary_filling.abstract_auxiliary_filling_app import (
|
|
40
43
|
AuxiliaryFilling,
|
|
41
44
|
)
|
|
42
45
|
from cars.core import constants as cst
|
|
@@ -96,8 +99,8 @@ class AuxiliaryFillingFromSensors(
|
|
|
96
99
|
"and full"
|
|
97
100
|
)
|
|
98
101
|
|
|
99
|
-
overloaded_conf["
|
|
100
|
-
"
|
|
102
|
+
overloaded_conf["texture_interpolator"] = conf.get(
|
|
103
|
+
"texture_interpolator", "linear"
|
|
101
104
|
)
|
|
102
105
|
overloaded_conf["activated"] = conf.get("activated", False)
|
|
103
106
|
overloaded_conf["use_mask"] = conf.get("use_mask", True)
|
|
@@ -112,7 +115,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
112
115
|
"activated": bool,
|
|
113
116
|
"mode": str,
|
|
114
117
|
"use_mask": bool,
|
|
115
|
-
"
|
|
118
|
+
"texture_interpolator": str,
|
|
116
119
|
"save_intermediate_data": bool,
|
|
117
120
|
}
|
|
118
121
|
|
|
@@ -131,6 +134,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
131
134
|
sensor_inputs,
|
|
132
135
|
pairing,
|
|
133
136
|
geom_plugin,
|
|
137
|
+
texture_bands,
|
|
134
138
|
orchestrator=None,
|
|
135
139
|
):
|
|
136
140
|
"""
|
|
@@ -151,6 +155,8 @@ class AuxiliaryFillingFromSensors(
|
|
|
151
155
|
:type pairing: list
|
|
152
156
|
:param geom_plugin: geometry plugin used for inverse locations
|
|
153
157
|
:type geom_plugin: AbstractGeometry
|
|
158
|
+
:param texture_bands: list of band names used for output texture
|
|
159
|
+
:type texture_bands: list
|
|
154
160
|
:param orchestrator: orchestrator used
|
|
155
161
|
:type orchestrator: Orchestrator
|
|
156
162
|
"""
|
|
@@ -180,7 +186,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
180
186
|
if not os.path.exists(dump_dir):
|
|
181
187
|
os.makedirs(dump_dir)
|
|
182
188
|
|
|
183
|
-
color_not_filled_file = os.path.join(dump_dir, "
|
|
189
|
+
color_not_filled_file = os.path.join(dump_dir, "texture_not_filled.tif")
|
|
184
190
|
if os.path.exists(color_file):
|
|
185
191
|
shutil.move(color_file, color_not_filled_file)
|
|
186
192
|
|
|
@@ -219,22 +225,22 @@ class AuxiliaryFillingFromSensors(
|
|
|
219
225
|
|
|
220
226
|
# Initialize no data value
|
|
221
227
|
classification_no_data_value = 0
|
|
222
|
-
|
|
228
|
+
texture_no_data_value = 0
|
|
223
229
|
color_dtype = np.float32
|
|
224
230
|
classif_dtype = np.uint8
|
|
225
231
|
|
|
226
232
|
if os.path.exists(color_not_filled_file):
|
|
227
233
|
with rio.open(color_not_filled_file, "r") as descriptor:
|
|
228
|
-
|
|
234
|
+
texture_no_data_value = descriptor.nodata
|
|
229
235
|
color_dtype = descriptor.profile.get("dtype", np.float32)
|
|
230
236
|
|
|
231
237
|
self.orchestrator.add_to_save_lists(
|
|
232
238
|
os.path.join(dump_dir, color_file),
|
|
233
239
|
cst.RASTER_COLOR_IMG,
|
|
234
240
|
aux_filled_image,
|
|
235
|
-
nodata=
|
|
241
|
+
nodata=texture_no_data_value,
|
|
236
242
|
dtype=color_dtype,
|
|
237
|
-
cars_ds_name="
|
|
243
|
+
cars_ds_name="filled_texture",
|
|
238
244
|
)
|
|
239
245
|
|
|
240
246
|
if classif_file is not None:
|
|
@@ -262,7 +268,7 @@ class AuxiliaryFillingFromSensors(
|
|
|
262
268
|
|
|
263
269
|
# Pre-compute sensor bounds of all sensors to filter sensors that do
|
|
264
270
|
# not intersect with tile in tasks
|
|
265
|
-
sensor_bounds =
|
|
271
|
+
sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
|
|
266
272
|
sensor_inputs, geom_plugin, reference_epsg
|
|
267
273
|
)
|
|
268
274
|
|
|
@@ -293,8 +299,11 @@ class AuxiliaryFillingFromSensors(
|
|
|
293
299
|
reference_epsg,
|
|
294
300
|
full_saving_info,
|
|
295
301
|
geom_plugin,
|
|
302
|
+
texture_bands,
|
|
296
303
|
mode=self.used_config["mode"],
|
|
297
|
-
|
|
304
|
+
texture_interpolator=self.used_config[
|
|
305
|
+
"texture_interpolator"
|
|
306
|
+
],
|
|
298
307
|
use_mask=self.used_config["use_mask"],
|
|
299
308
|
)
|
|
300
309
|
|
|
@@ -318,12 +327,13 @@ def filling_from_sensor_wrapper(
|
|
|
318
327
|
epsg,
|
|
319
328
|
saving_info,
|
|
320
329
|
geom_plugin,
|
|
330
|
+
texture_bands,
|
|
321
331
|
mode,
|
|
322
|
-
|
|
332
|
+
texture_interpolator,
|
|
323
333
|
use_mask,
|
|
324
334
|
):
|
|
325
335
|
"""
|
|
326
|
-
|
|
336
|
+
Fill color and classification from sensor information for a terrain tile
|
|
327
337
|
|
|
328
338
|
:param dsm_file: path to the filled dsm file
|
|
329
339
|
:type dsm_file: str
|
|
@@ -347,11 +357,13 @@ def filling_from_sensor_wrapper(
|
|
|
347
357
|
:type saving_info: dict
|
|
348
358
|
:param geom_plugin: geometry plugin used for inverse locations
|
|
349
359
|
:type geom_plugin: AbstractGeometry
|
|
360
|
+
:param texture_bands: list of band names used for output texture
|
|
361
|
+
:type texture_bands: list
|
|
350
362
|
:param mode: geometry plugin used for inverse locations
|
|
351
363
|
:type mode: str
|
|
352
|
-
:param
|
|
364
|
+
:param texture_interpolator: scipy interpolator use to interpolate color
|
|
353
365
|
values
|
|
354
|
-
:type
|
|
366
|
+
:type texture_interpolator: str
|
|
355
367
|
:param use_mask: use mask information from sensors in color computation
|
|
356
368
|
:type use_mask: bool
|
|
357
369
|
|
|
@@ -432,13 +444,13 @@ def filling_from_sensor_wrapper(
|
|
|
432
444
|
else:
|
|
433
445
|
profile = dsm_profile
|
|
434
446
|
number_of_color_bands = inputs.rasterio_get_nb_bands(
|
|
435
|
-
sensor_inputs[list(sensor_inputs.keys())[0]].get("
|
|
447
|
+
sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
|
|
436
448
|
)
|
|
437
449
|
color_values = np.full(
|
|
438
450
|
(number_of_color_bands, *target_mask.shape), np.nan
|
|
439
451
|
)
|
|
440
452
|
color_band_names = inputs.get_descriptions_bands(
|
|
441
|
-
sensor_inputs[list(sensor_inputs.keys())[0]].get("
|
|
453
|
+
sensor_inputs[list(sensor_inputs.keys())[0]].get("texture", None)
|
|
442
454
|
)
|
|
443
455
|
# update profile
|
|
444
456
|
profile.update(count=number_of_color_bands)
|
|
@@ -481,14 +493,14 @@ def filling_from_sensor_wrapper(
|
|
|
481
493
|
index_1d = target_mask.flatten().nonzero()[0]
|
|
482
494
|
|
|
483
495
|
# Remove sensor that don't intesects with current tile
|
|
484
|
-
filtered_sensor_inputs =
|
|
496
|
+
filtered_sensor_inputs = auxiliary_filling_wrappers.filter_sensor_inputs(
|
|
485
497
|
sensor_inputs, sensor_bounds, ground_polygon
|
|
486
498
|
)
|
|
487
499
|
|
|
488
500
|
if len(index_1d) > 0:
|
|
489
501
|
# Fill required pixels
|
|
490
502
|
color_values_filled, classification_values_filled = (
|
|
491
|
-
|
|
503
|
+
auxiliary_filling_algo.fill_auxiliary(
|
|
492
504
|
filtered_sensor_inputs,
|
|
493
505
|
pairing,
|
|
494
506
|
lon_lat[index_1d, 0],
|
|
@@ -497,7 +509,8 @@ def filling_from_sensor_wrapper(
|
|
|
497
509
|
geom_plugin,
|
|
498
510
|
number_of_color_bands,
|
|
499
511
|
number_of_classification_bands,
|
|
500
|
-
|
|
512
|
+
texture_bands,
|
|
513
|
+
texture_interpolator=texture_interpolator,
|
|
501
514
|
use_mask=use_mask,
|
|
502
515
|
)
|
|
503
516
|
)
|