cars 1.0.0rc3__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
- cars/__init__.py +74 -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 +46 -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.cpython-313-x86_64-linux-gnu.so +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
- cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
- cars/applications/dense_matching/cpp/meson.build +9 -0
- cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
- cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
- cars/applications/dense_matching/dense_matching_algo.py +401 -0
- cars/applications/dense_matching/dense_matching_constants.py +89 -0
- cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
- cars/applications/dense_matching/disparity_grid_algo.py +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 +1130 -0
- cars/core/geometry/shareloc_geometry.py +604 -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 +1095 -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 +190 -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 +435 -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.0rc3.dist-info/METADATA +289 -0
- cars-1.0.0rc3.dist-info/RECORD +220 -0
- cars-1.0.0rc3.dist-info/WHEEL +6 -0
- cars-1.0.0rc3.dist-info/entry_points.txt +8 -0
|
@@ -0,0 +1,1243 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# coding: utf8
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
|
|
5
|
+
#
|
|
6
|
+
# This file is part of CARS
|
|
7
|
+
# (see https://github.com/CNES/cars).
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
# pylint: disable=too-many-lines
|
|
22
|
+
"""
|
|
23
|
+
this module contains the LineOfSightIntersection application class.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Standard imports
|
|
27
|
+
import logging
|
|
28
|
+
import os
|
|
29
|
+
from typing import Dict, Tuple
|
|
30
|
+
|
|
31
|
+
# Third party imports
|
|
32
|
+
import numpy as np
|
|
33
|
+
import pandas
|
|
34
|
+
import xarray as xr
|
|
35
|
+
from json_checker import Checker
|
|
36
|
+
from shareloc.geofunctions.rectification_grid import RectificationGrid
|
|
37
|
+
|
|
38
|
+
# CARS imports
|
|
39
|
+
import cars.orchestrator.orchestrator as ocht
|
|
40
|
+
from cars.applications import application_constants
|
|
41
|
+
from cars.applications.grid_generation import grid_generation_algo
|
|
42
|
+
from cars.applications.triangulation import (
|
|
43
|
+
pc_transform,
|
|
44
|
+
triangulation_algo,
|
|
45
|
+
triangulation_constants,
|
|
46
|
+
)
|
|
47
|
+
from cars.applications.triangulation import (
|
|
48
|
+
triangulation_wrappers as triangulation_wrap,
|
|
49
|
+
)
|
|
50
|
+
from cars.applications.triangulation.abstract_triangulation_app import (
|
|
51
|
+
Triangulation,
|
|
52
|
+
)
|
|
53
|
+
from cars.core import constants as cst
|
|
54
|
+
from cars.core import inputs, projection, tiling
|
|
55
|
+
from cars.core.utils import safe_makedirs
|
|
56
|
+
from cars.data_structures import cars_dataset
|
|
57
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
58
|
+
from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class LineOfSightIntersection(
|
|
62
|
+
Triangulation, short_name="line_of_sight_intersection"
|
|
63
|
+
):
|
|
64
|
+
"""
|
|
65
|
+
Triangulation
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, conf=None):
|
|
69
|
+
"""
|
|
70
|
+
Init function of Triangulation
|
|
71
|
+
|
|
72
|
+
:param conf: configuration for triangulation
|
|
73
|
+
:return: an application_to_use object
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
super().__init__(conf=conf)
|
|
77
|
+
# check conf
|
|
78
|
+
self.used_method = self.used_config["method"]
|
|
79
|
+
self.snap_to_img1 = self.used_config["snap_to_img1"]
|
|
80
|
+
# Saving files
|
|
81
|
+
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
82
|
+
|
|
83
|
+
# global value for left image to check if snap_to_img1 can
|
|
84
|
+
# be applied : Need than same application object is run
|
|
85
|
+
# for all pairs
|
|
86
|
+
self.ref_left_img = None
|
|
87
|
+
|
|
88
|
+
# Init orchestrator
|
|
89
|
+
self.orchestrator = None
|
|
90
|
+
|
|
91
|
+
def check_conf(self, conf):
|
|
92
|
+
"""
|
|
93
|
+
Check configuration
|
|
94
|
+
|
|
95
|
+
:param conf: configuration to check
|
|
96
|
+
:type conf: dict
|
|
97
|
+
|
|
98
|
+
:return: overloaded configuration
|
|
99
|
+
:rtype: dict
|
|
100
|
+
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
# init conf
|
|
104
|
+
if conf is not None:
|
|
105
|
+
overloaded_conf = conf.copy()
|
|
106
|
+
else:
|
|
107
|
+
conf = {}
|
|
108
|
+
overloaded_conf = {}
|
|
109
|
+
|
|
110
|
+
# Overload conf
|
|
111
|
+
overloaded_conf["method"] = conf.get(
|
|
112
|
+
"method", "line_of_sight_intersection"
|
|
113
|
+
)
|
|
114
|
+
overloaded_conf["snap_to_img1"] = conf.get("snap_to_img1", False)
|
|
115
|
+
|
|
116
|
+
# Saving files
|
|
117
|
+
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
118
|
+
"save_intermediate_data", False
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
triangulation_schema = {
|
|
122
|
+
"method": str,
|
|
123
|
+
"snap_to_img1": bool,
|
|
124
|
+
"save_intermediate_data": bool,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# Check conf
|
|
128
|
+
checker = Checker(triangulation_schema)
|
|
129
|
+
checker.validate(overloaded_conf)
|
|
130
|
+
|
|
131
|
+
return overloaded_conf
|
|
132
|
+
|
|
133
|
+
# pylint: disable=too-many-positional-arguments
|
|
134
|
+
@cars_profile(name="Save triangulation output", interval=0.5)
|
|
135
|
+
def save_triangulation_output( # noqa: C901 function is too complex
|
|
136
|
+
self,
|
|
137
|
+
epipolar_point_cloud,
|
|
138
|
+
sensor_image_left,
|
|
139
|
+
output_dir,
|
|
140
|
+
dump_dir=None,
|
|
141
|
+
performance_maps_to_generate=None,
|
|
142
|
+
save_output_coordinates=True,
|
|
143
|
+
save_output_color=True,
|
|
144
|
+
save_output_classification=False,
|
|
145
|
+
save_output_filling=False,
|
|
146
|
+
save_output_performance_map=False,
|
|
147
|
+
save_output_ambiguity=False,
|
|
148
|
+
):
|
|
149
|
+
"""
|
|
150
|
+
Save the triangulation output. The different TIFs composing the depth
|
|
151
|
+
map are written to the output directory. Auxiliary products can be
|
|
152
|
+
requested or not using the parameters. A dump directory can also be
|
|
153
|
+
provided to write any additionnal files that have not been written
|
|
154
|
+
to the output directory (because they are not part of the depth map
|
|
155
|
+
definition, or because they have not been requested).
|
|
156
|
+
|
|
157
|
+
:param epipolar_point_cloud: tiled epipolar left image
|
|
158
|
+
:type epipolar_point_cloud: CarsDataset
|
|
159
|
+
:param sensor_image_left: tiled sensor left image
|
|
160
|
+
Dict Must contain keys : "image", "texture", "geomodel",
|
|
161
|
+
"no_data", "mask". Paths must be absolutes
|
|
162
|
+
:type sensor_image_left: CarsDataset
|
|
163
|
+
:param output_dir: directory to write triangulation output depth
|
|
164
|
+
map.
|
|
165
|
+
:type output_dir: None or str
|
|
166
|
+
:param dump_dir: folder used as dump directory for current pair, None to
|
|
167
|
+
deactivate intermediate data writing
|
|
168
|
+
:type dump_dir: str
|
|
169
|
+
:param performance_maps_to_generate: None or list containing
|
|
170
|
+
"risk" or "intervals"
|
|
171
|
+
:type performance_maps_to_generate: None or list containing
|
|
172
|
+
"risk" or "intervals"
|
|
173
|
+
:param save_output_coordinates: Save X, Y and Z coords in output_dir
|
|
174
|
+
:type save_output_coordinates: bool
|
|
175
|
+
:param save_output_color: Save color depth map in output_dir
|
|
176
|
+
:type save_output_color: bool
|
|
177
|
+
:param save_output_classification: Save classification depth map in
|
|
178
|
+
output_dir
|
|
179
|
+
:type save_output_classification: bool
|
|
180
|
+
:param save_output_filling: Save filling depth map in output_dir
|
|
181
|
+
:type save_output_filling: bool
|
|
182
|
+
:param save_output_performance_map: Save performance map in output_dir
|
|
183
|
+
:type save_output_performance_map: bool
|
|
184
|
+
:param save_output_ambiguity: Save ambiguity in output_dir
|
|
185
|
+
:type save_output_ambiguity: bool
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
if dump_dir:
|
|
189
|
+
safe_makedirs(dump_dir)
|
|
190
|
+
|
|
191
|
+
# Propagate color type in output file
|
|
192
|
+
color_type = inputs.rasterio_get_image_type(
|
|
193
|
+
sensor_image_left[sens_cst.INPUT_IMG]["bands"]["b0"]["path"]
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
if output_dir is None:
|
|
197
|
+
output_dir = dump_dir
|
|
198
|
+
|
|
199
|
+
if save_output_coordinates or dump_dir:
|
|
200
|
+
coords_output_dir = (
|
|
201
|
+
output_dir if save_output_coordinates else dump_dir
|
|
202
|
+
)
|
|
203
|
+
self.orchestrator.add_to_save_lists(
|
|
204
|
+
os.path.join(coords_output_dir, "X.tif"),
|
|
205
|
+
cst.X,
|
|
206
|
+
epipolar_point_cloud,
|
|
207
|
+
cars_ds_name="depth_map_x",
|
|
208
|
+
dtype=np.float64,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
self.orchestrator.add_to_save_lists(
|
|
212
|
+
os.path.join(coords_output_dir, "Y.tif"),
|
|
213
|
+
cst.Y,
|
|
214
|
+
epipolar_point_cloud,
|
|
215
|
+
cars_ds_name="depth_map_y",
|
|
216
|
+
dtype=np.float64,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
self.orchestrator.add_to_save_lists(
|
|
220
|
+
os.path.join(coords_output_dir, "Z.tif"),
|
|
221
|
+
cst.Z,
|
|
222
|
+
epipolar_point_cloud,
|
|
223
|
+
cars_ds_name="depth_map_z",
|
|
224
|
+
dtype=np.float64,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
if save_output_color or dump_dir:
|
|
228
|
+
color_output_dir = output_dir if save_output_color else dump_dir
|
|
229
|
+
self.orchestrator.add_to_save_lists(
|
|
230
|
+
os.path.join(color_output_dir, "image.tif"),
|
|
231
|
+
cst.EPI_TEXTURE,
|
|
232
|
+
epipolar_point_cloud,
|
|
233
|
+
cars_ds_name="depth_map_color",
|
|
234
|
+
dtype=color_type,
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
if save_output_performance_map or dump_dir:
|
|
238
|
+
map_output_dir = (
|
|
239
|
+
output_dir if save_output_performance_map else dump_dir
|
|
240
|
+
)
|
|
241
|
+
performance_map_tail_path = "performance_map.tif"
|
|
242
|
+
if "intervals" in performance_maps_to_generate:
|
|
243
|
+
tail_path = performance_map_tail_path
|
|
244
|
+
if len(performance_maps_to_generate) == 2:
|
|
245
|
+
tail_path = "performance_map_from_intervals.tif"
|
|
246
|
+
self.orchestrator.add_to_save_lists(
|
|
247
|
+
os.path.join(map_output_dir, tail_path),
|
|
248
|
+
cst.POINT_CLOUD_PERFORMANCE_MAP_FROM_INTERVALS,
|
|
249
|
+
epipolar_point_cloud,
|
|
250
|
+
cars_ds_name="depth_map_performance_map_from_intervals",
|
|
251
|
+
optional_data=True,
|
|
252
|
+
dtype=np.float64,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
if "risk" in performance_maps_to_generate:
|
|
256
|
+
tail_path = performance_map_tail_path
|
|
257
|
+
if len(performance_maps_to_generate) == 2:
|
|
258
|
+
tail_path = "performance_map_from_risk.tif"
|
|
259
|
+
self.orchestrator.add_to_save_lists(
|
|
260
|
+
os.path.join(map_output_dir, tail_path),
|
|
261
|
+
cst.POINT_CLOUD_PERFORMANCE_MAP_FROM_RISK,
|
|
262
|
+
epipolar_point_cloud,
|
|
263
|
+
cars_ds_name="depth_map_performance_map_from_risk",
|
|
264
|
+
optional_data=True,
|
|
265
|
+
dtype=np.float64,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
if save_output_ambiguity or dump_dir:
|
|
269
|
+
map_output_dir = output_dir if save_output_ambiguity else dump_dir
|
|
270
|
+
self.orchestrator.add_to_save_lists(
|
|
271
|
+
os.path.join(map_output_dir, "ambiguity.tif"),
|
|
272
|
+
cst.EPI_AMBIGUITY,
|
|
273
|
+
epipolar_point_cloud,
|
|
274
|
+
cars_ds_name="depth_map_ambiguity",
|
|
275
|
+
optional_data=True,
|
|
276
|
+
dtype=np.float64,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
if save_output_classification or dump_dir:
|
|
280
|
+
classif_output_dir = (
|
|
281
|
+
output_dir if save_output_classification else dump_dir
|
|
282
|
+
)
|
|
283
|
+
self.orchestrator.add_to_save_lists(
|
|
284
|
+
os.path.join(classif_output_dir, "classification.tif"),
|
|
285
|
+
cst.EPI_CLASSIFICATION,
|
|
286
|
+
epipolar_point_cloud,
|
|
287
|
+
cars_ds_name="depth_map_classification",
|
|
288
|
+
optional_data=True,
|
|
289
|
+
dtype=np.uint8,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
if save_output_filling or dump_dir:
|
|
293
|
+
filling_output_dir = output_dir if save_output_filling else dump_dir
|
|
294
|
+
self.orchestrator.add_to_save_lists(
|
|
295
|
+
os.path.join(filling_output_dir, "filling.tif"),
|
|
296
|
+
cst.EPI_FILLING,
|
|
297
|
+
epipolar_point_cloud,
|
|
298
|
+
cars_ds_name="depth_map_filling",
|
|
299
|
+
optional_data=True,
|
|
300
|
+
dtype=np.uint8,
|
|
301
|
+
nodata=255,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
if dump_dir and performance_maps_to_generate is not None:
|
|
305
|
+
if "intervals" in performance_maps_to_generate:
|
|
306
|
+
self.orchestrator.add_to_save_lists(
|
|
307
|
+
os.path.join(dump_dir, "Z_inf_from_intervals.tif"),
|
|
308
|
+
cst.POINT_CLOUD_LAYER_INF_FROM_INTERVALS,
|
|
309
|
+
epipolar_point_cloud,
|
|
310
|
+
cars_ds_name="depth_map_z_inf_from_intervals",
|
|
311
|
+
)
|
|
312
|
+
self.orchestrator.add_to_save_lists(
|
|
313
|
+
os.path.join(dump_dir, "Z_sup_from_intervals.tif"),
|
|
314
|
+
cst.POINT_CLOUD_LAYER_SUP_FROM_INTERVALS,
|
|
315
|
+
epipolar_point_cloud,
|
|
316
|
+
cars_ds_name="depth_map_z_sup_from_intervals",
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
if "risk" in performance_maps_to_generate:
|
|
320
|
+
self.orchestrator.add_to_save_lists(
|
|
321
|
+
os.path.join(dump_dir, "Z_inf_from_risk.tif"),
|
|
322
|
+
cst.POINT_CLOUD_LAYER_INF_FROM_RISK,
|
|
323
|
+
epipolar_point_cloud,
|
|
324
|
+
cars_ds_name="depth_map_z_inf_from_risk",
|
|
325
|
+
)
|
|
326
|
+
self.orchestrator.add_to_save_lists(
|
|
327
|
+
os.path.join(dump_dir, "Z_sup_from_risk.tif"),
|
|
328
|
+
cst.POINT_CLOUD_LAYER_SUP_FROM_RISK,
|
|
329
|
+
epipolar_point_cloud,
|
|
330
|
+
cars_ds_name="depth_map_z_sup_from_risk",
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
if dump_dir:
|
|
334
|
+
self.orchestrator.add_to_save_lists(
|
|
335
|
+
os.path.join(dump_dir, "corr_mask.tif"),
|
|
336
|
+
cst.POINT_CLOUD_CORR_MSK,
|
|
337
|
+
epipolar_point_cloud,
|
|
338
|
+
cars_ds_name="depth_map_corr_msk",
|
|
339
|
+
optional_data=True,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
@cars_profile(name="Fill index", interval=0.5)
|
|
343
|
+
def fill_index( # pylint: disable=too-many-positional-arguments
|
|
344
|
+
self,
|
|
345
|
+
save_output_coordinates=True,
|
|
346
|
+
save_output_color=True,
|
|
347
|
+
save_output_classification=False,
|
|
348
|
+
save_output_filling=False,
|
|
349
|
+
save_output_performance_map=False,
|
|
350
|
+
save_output_ambiguity=False,
|
|
351
|
+
pair_key="PAIR_0",
|
|
352
|
+
):
|
|
353
|
+
"""
|
|
354
|
+
Fill depth map index for current pair, according to which product
|
|
355
|
+
should be saved
|
|
356
|
+
|
|
357
|
+
:param save_output_coordinates: Save X, Y and Z coords in output_dir
|
|
358
|
+
:type save_output_coordinates: bool
|
|
359
|
+
:param save_output_color: Save color depth map in output_dir
|
|
360
|
+
:type save_output_color: bool
|
|
361
|
+
:param save_output_classification: Save classification depth map in
|
|
362
|
+
output_dir
|
|
363
|
+
:type save_output_classification: bool
|
|
364
|
+
:param save_output_filling: Save filling depth map in output_dir
|
|
365
|
+
:type save_output_filling: bool
|
|
366
|
+
:param save_output_performance_map: Save performance map in output_dir
|
|
367
|
+
:type save_output_performance_map: bool
|
|
368
|
+
:param save_output_ambiguity: Save ambiguity in output_dir
|
|
369
|
+
:type save_output_ambiguity: bool
|
|
370
|
+
:param pair_key: name of the current pair
|
|
371
|
+
:type pair_key: str
|
|
372
|
+
"""
|
|
373
|
+
|
|
374
|
+
# index file for this depth map
|
|
375
|
+
index = {}
|
|
376
|
+
|
|
377
|
+
if save_output_coordinates:
|
|
378
|
+
index[cst.INDEX_DEPTH_MAP_X] = os.path.join(pair_key, "X.tif")
|
|
379
|
+
index[cst.INDEX_DEPTH_MAP_Y] = os.path.join(pair_key, "Y.tif")
|
|
380
|
+
index[cst.INDEX_DEPTH_MAP_Z] = os.path.join(pair_key, "Z.tif")
|
|
381
|
+
|
|
382
|
+
if save_output_color:
|
|
383
|
+
index[cst.INDEX_DEPTH_MAP_COLOR] = os.path.join(
|
|
384
|
+
pair_key, "image.tif"
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
if save_output_performance_map:
|
|
388
|
+
index[cst.INDEX_DEPTH_MAP_PERFORMANCE_MAP] = os.path.join(
|
|
389
|
+
pair_key, "performance_map.tif"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
if save_output_ambiguity:
|
|
393
|
+
index[cst.INDEX_DEPTH_MAP_AMBIGUITY] = os.path.join(
|
|
394
|
+
pair_key, "ambiguity.tif"
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
if save_output_classification:
|
|
398
|
+
index[cst.INDEX_DEPTH_MAP_CLASSIFICATION] = os.path.join(
|
|
399
|
+
pair_key, "classification.tif"
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
if save_output_filling:
|
|
403
|
+
index[cst.INDEX_DEPTH_MAP_FILLING] = os.path.join(
|
|
404
|
+
pair_key, "filling.tif"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# update orchestrator index if it has been filled
|
|
408
|
+
if index:
|
|
409
|
+
# Add epsg code (always lon/lat in triangulation)
|
|
410
|
+
index[cst.INDEX_DEPTH_MAP_EPSG] = 4326
|
|
411
|
+
self.orchestrator.update_index({"depth_map": {pair_key: index}})
|
|
412
|
+
|
|
413
|
+
def create_point_cloud_directories(
|
|
414
|
+
self, pair_dump_dir, point_cloud_dir, point_cloud
|
|
415
|
+
):
|
|
416
|
+
"""
|
|
417
|
+
Set and create directories for point cloud disk output (laz and csv)
|
|
418
|
+
The function return None path if the point cloud should not be saved
|
|
419
|
+
|
|
420
|
+
:param pair_dump_dir: folder used as dump directory for current pair
|
|
421
|
+
:type pair_dump_dir: str
|
|
422
|
+
:param point_cloud_dir: folder used for laz official product directory
|
|
423
|
+
:type point_cloud_dir: str
|
|
424
|
+
:param point_cloud: input point cloud (for orchestrator registration)
|
|
425
|
+
:type point_cloud: Dataset
|
|
426
|
+
"""
|
|
427
|
+
|
|
428
|
+
csv_pc_dir_name = None
|
|
429
|
+
if self.save_intermediate_data:
|
|
430
|
+
csv_pc_dir_name = os.path.join(pair_dump_dir, "csv")
|
|
431
|
+
safe_makedirs(csv_pc_dir_name)
|
|
432
|
+
self.orchestrator.add_to_compute_lists(
|
|
433
|
+
point_cloud, cars_ds_name="point_cloud_csv"
|
|
434
|
+
)
|
|
435
|
+
laz_pc_dir_name = None
|
|
436
|
+
if self.save_intermediate_data or point_cloud_dir is not None:
|
|
437
|
+
if point_cloud_dir is not None:
|
|
438
|
+
laz_pc_dir_name = point_cloud_dir
|
|
439
|
+
else:
|
|
440
|
+
laz_pc_dir_name = os.path.join(pair_dump_dir, "laz")
|
|
441
|
+
safe_makedirs(laz_pc_dir_name)
|
|
442
|
+
self.orchestrator.add_to_compute_lists(
|
|
443
|
+
point_cloud, cars_ds_name="point_cloud_laz"
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
return csv_pc_dir_name, laz_pc_dir_name
|
|
447
|
+
|
|
448
|
+
def run( # pylint: disable=too-many-positional-arguments # noqa: C901
|
|
449
|
+
self,
|
|
450
|
+
sensor_image_left,
|
|
451
|
+
sensor_image_right,
|
|
452
|
+
grid_left,
|
|
453
|
+
grid_right,
|
|
454
|
+
epipolar_disparity_map,
|
|
455
|
+
geometry_plugin,
|
|
456
|
+
epipolar_image,
|
|
457
|
+
epsg=None,
|
|
458
|
+
denoising_overload_fun=None,
|
|
459
|
+
source_pc_names=None,
|
|
460
|
+
orchestrator=None,
|
|
461
|
+
pair_dump_dir=None,
|
|
462
|
+
pair_key="PAIR_0",
|
|
463
|
+
uncorrected_grid_right=None,
|
|
464
|
+
geoid_path=None,
|
|
465
|
+
cloud_id=None,
|
|
466
|
+
performance_maps_param=None,
|
|
467
|
+
depth_map_dir=None,
|
|
468
|
+
point_cloud_dir=None,
|
|
469
|
+
save_output_coordinates=False,
|
|
470
|
+
save_output_color=False,
|
|
471
|
+
save_output_classification=False,
|
|
472
|
+
save_output_filling=False,
|
|
473
|
+
save_output_performance_map=False,
|
|
474
|
+
save_output_ambiguity=False,
|
|
475
|
+
):
|
|
476
|
+
"""
|
|
477
|
+
Run Triangulation application.
|
|
478
|
+
|
|
479
|
+
Created left and right CarsDataset filled with xarray.Dataset,
|
|
480
|
+
corresponding to 3D point clouds, stored on epipolar geometry grid.
|
|
481
|
+
|
|
482
|
+
:param sensor_image_left: tiled sensor left image
|
|
483
|
+
Dict Must contain keys : "image", "texture", "geomodel",
|
|
484
|
+
"no_data", "mask". Paths must be absolutes
|
|
485
|
+
:type sensor_image_left: CarsDataset
|
|
486
|
+
:param sensor_image_right: tiled sensor right image
|
|
487
|
+
Dict Must contain keys : "image", "texture", "geomodel",
|
|
488
|
+
"no_data", "mask". Paths must be absolutes
|
|
489
|
+
:type sensor_image_right: CarsDataset
|
|
490
|
+
:param grid_left: left epipolar grid. Grid dict contains :
|
|
491
|
+
- "grid_spacing", "grid_origin",\
|
|
492
|
+
"epipolar_size_x", epipolar_size_y", "epipolar_origin_x",\
|
|
493
|
+
"epipolar_origin_y","epipolar_spacing_x",\
|
|
494
|
+
"epipolar_spacing", "disp_to_alt_ratio", "path"
|
|
495
|
+
:type grid_left: dict
|
|
496
|
+
:param grid_right: right epipolar grid. Grid dict contains :
|
|
497
|
+
- "grid_spacing", "grid_origin",\
|
|
498
|
+
"epipolar_size_x", epipolar_size_y", "epipolar_origin_x",\
|
|
499
|
+
"epipolar_origin_y","epipolar_spacing_x",\
|
|
500
|
+
"epipolar_spacing", "disp_to_alt_ratio", "path"
|
|
501
|
+
:type grid_right: dict
|
|
502
|
+
:param epipolar_disparity_map: tiled left disparity map or \
|
|
503
|
+
sparse matches:
|
|
504
|
+
|
|
505
|
+
- if CarsDataset is instance of "arrays", CarsDataset contains:
|
|
506
|
+
|
|
507
|
+
- N x M Delayed tiles \
|
|
508
|
+
Each tile will be a future xarray Dataset containing:
|
|
509
|
+
|
|
510
|
+
- data with keys : "disp", "disp_msk"
|
|
511
|
+
- attrs with keys: profile, window, overlaps
|
|
512
|
+
- attributes containing:"largest_epipolar_region"\
|
|
513
|
+
"opt_epipolar_tile_size"
|
|
514
|
+
|
|
515
|
+
- if CarsDataset is instance of "points", CarsDataset contains:
|
|
516
|
+
|
|
517
|
+
- N x M Delayed tiles \
|
|
518
|
+
Each tile will be a future pandas DataFrame containing:
|
|
519
|
+
|
|
520
|
+
- data : (L, 4) shape matches
|
|
521
|
+
- attributes containing:"disp_lower_bound","disp_upper_bound",\
|
|
522
|
+
"elevation_delta_lower_bound","elevation_delta_upper_bound"
|
|
523
|
+
|
|
524
|
+
:type epipolar_disparity_map: CarsDataset
|
|
525
|
+
:param epipolar_image: tiled epipolar left image
|
|
526
|
+
:type epipolar_image: CarsDataset
|
|
527
|
+
:param denoising_overload_fun: function to overload dataset
|
|
528
|
+
:type denoising_overload_fun: fun
|
|
529
|
+
:param source_pc_names: source pc names
|
|
530
|
+
:type source_pc_names: list[str]
|
|
531
|
+
:param orchestrator: orchestrator used
|
|
532
|
+
:param pair_dump_dir: folder used as dump directory for current pair
|
|
533
|
+
:type pair_dump_dir: str
|
|
534
|
+
:param pair_key: pair key id
|
|
535
|
+
:type pair_key: str
|
|
536
|
+
:param uncorrected_grid_right: not corrected right epipolar grid
|
|
537
|
+
used if self.snap_to_img1
|
|
538
|
+
:type uncorrected_grid_right: CarsDataset
|
|
539
|
+
:param geoid_path: geoid path
|
|
540
|
+
:type geoid_path: str
|
|
541
|
+
:param performance_maps_param: parameters used
|
|
542
|
+
to generate performance map
|
|
543
|
+
:type performance_maps_param: dict or None
|
|
544
|
+
:param depth_map_dir: directory to write triangulation output depth
|
|
545
|
+
map.
|
|
546
|
+
:type depth_map_dir: None or str
|
|
547
|
+
:param save_output_coordinates: Save X, Y, Z coords in depth_map_dir
|
|
548
|
+
:type save_output_coordinates: bool
|
|
549
|
+
:param save_output_color: Save color depth map in depth_map_dir
|
|
550
|
+
:type save_output_color: bool
|
|
551
|
+
:param save_output_classification: Save classification depth map in
|
|
552
|
+
depth_map_dir
|
|
553
|
+
:type save_output_classification: bool
|
|
554
|
+
:param save_output_filling: Save filling depth map in depth_map_dir
|
|
555
|
+
:type save_output_filling: bool
|
|
556
|
+
:param save_output_performance_map: Save performance map in
|
|
557
|
+
depth_map_dir
|
|
558
|
+
:type save_output_performance_map: bool
|
|
559
|
+
:param save_output_ambiguity: Save ambiguity in
|
|
560
|
+
depth_map_dir
|
|
561
|
+
:type save_output_ambiguity: bool
|
|
562
|
+
|
|
563
|
+
:return: point cloud \
|
|
564
|
+
The CarsDataset contains:
|
|
565
|
+
|
|
566
|
+
- N x M Delayed tiles \
|
|
567
|
+
Each tile will be a future xarray Dataset containing:
|
|
568
|
+
|
|
569
|
+
- data : with keys : "x", "y", "z", "corr_msk"\
|
|
570
|
+
optional: "texture", "msk", "z_inf", "z_sup"
|
|
571
|
+
- attrs with keys: "margins", "epi_full_size", "epsg"
|
|
572
|
+
- attributes containing: "disp_lower_bound", "disp_upper_bound", \
|
|
573
|
+
"elevation_delta_lower_bound","elevation_delta_upper_bound"
|
|
574
|
+
|
|
575
|
+
:rtype: Tuple(CarsDataset, CarsDataset)
|
|
576
|
+
"""
|
|
577
|
+
# Default orchestrator
|
|
578
|
+
if orchestrator is None:
|
|
579
|
+
# Create default sequential orchestrator for current application
|
|
580
|
+
# be awere, no out_json will be shared between orchestrators
|
|
581
|
+
# No files saved
|
|
582
|
+
self.orchestrator = ocht.Orchestrator(
|
|
583
|
+
orchestrator_conf={"mode": "sequential"}
|
|
584
|
+
)
|
|
585
|
+
else:
|
|
586
|
+
self.orchestrator = orchestrator
|
|
587
|
+
|
|
588
|
+
if epipolar_disparity_map.dataset_type not in ("arrays", "points"):
|
|
589
|
+
raise RuntimeError(
|
|
590
|
+
"Triangulation application doesn't support this input "
|
|
591
|
+
"data format"
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
# Interpolate grid
|
|
595
|
+
interpolated_grid_left = RectificationGrid(
|
|
596
|
+
grid_left["path"],
|
|
597
|
+
interpolator=geometry_plugin.interpolator,
|
|
598
|
+
)
|
|
599
|
+
interpolated_grid_right = RectificationGrid(
|
|
600
|
+
grid_right["path"],
|
|
601
|
+
interpolator=geometry_plugin.interpolator,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
broadcasted_interpolated_grid_left = self.orchestrator.cluster.scatter(
|
|
605
|
+
interpolated_grid_left
|
|
606
|
+
)
|
|
607
|
+
broadcasted_interpolated_grid_right = self.orchestrator.cluster.scatter(
|
|
608
|
+
interpolated_grid_right
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
sensor1 = sensor_image_left[sens_cst.INPUT_IMG]
|
|
612
|
+
sensor2 = sensor_image_right[sens_cst.INPUT_IMG]
|
|
613
|
+
geomodel1 = sensor_image_left[sens_cst.INPUT_GEO_MODEL]
|
|
614
|
+
geomodel2 = sensor_image_right[sens_cst.INPUT_GEO_MODEL]
|
|
615
|
+
|
|
616
|
+
if epipolar_disparity_map.dataset_type != "points":
|
|
617
|
+
if source_pc_names is None:
|
|
618
|
+
source_pc_names = ["PAIR_0"]
|
|
619
|
+
|
|
620
|
+
if pair_dump_dir is None:
|
|
621
|
+
pair_dump_dir = os.path.join(self.orchestrator.out_dir, "tmp")
|
|
622
|
+
|
|
623
|
+
# Get local conf left image for this in_json iteration
|
|
624
|
+
conf_left_img = sensor_image_left[sens_cst.INPUT_IMG]
|
|
625
|
+
# Check left image and raise a warning
|
|
626
|
+
# if different left images are used along with snap_to_img1 mode
|
|
627
|
+
if self.ref_left_img is None:
|
|
628
|
+
self.ref_left_img = conf_left_img
|
|
629
|
+
else:
|
|
630
|
+
if self.snap_to_img1 and self.ref_left_img != conf_left_img:
|
|
631
|
+
logging.warning(
|
|
632
|
+
"snap_to_left_image mode is used but inputs "
|
|
633
|
+
"have different images as their "
|
|
634
|
+
"left image in pair. This may result in "
|
|
635
|
+
"increasing registration discrepancies between pairs"
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
# Add log about geoid
|
|
639
|
+
if geoid_path is not None:
|
|
640
|
+
alt_reference = "geoid"
|
|
641
|
+
else:
|
|
642
|
+
alt_reference = "ellipsoid"
|
|
643
|
+
|
|
644
|
+
# Add infos to orchestrator.out_json
|
|
645
|
+
updating_dict = {
|
|
646
|
+
application_constants.APPLICATION_TAG: {
|
|
647
|
+
triangulation_constants.TRIANGULATION_RUN_TAG: {
|
|
648
|
+
pair_key: {
|
|
649
|
+
triangulation_constants.ALT_REFERENCE_TAG: (
|
|
650
|
+
alt_reference
|
|
651
|
+
)
|
|
652
|
+
},
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
self.orchestrator.update_out_info(updating_dict)
|
|
657
|
+
|
|
658
|
+
if self.snap_to_img1:
|
|
659
|
+
grid_right = uncorrected_grid_right
|
|
660
|
+
if grid_right is None:
|
|
661
|
+
logging.error(
|
|
662
|
+
"Uncorrected grid was not given in order "
|
|
663
|
+
"to snap it to img1"
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
# Compute disp_min and disp_max location for epipolar grid
|
|
667
|
+
|
|
668
|
+
# Transform
|
|
669
|
+
disp_min_tiling = epipolar_disparity_map.attributes[
|
|
670
|
+
"disp_min_tiling"
|
|
671
|
+
]
|
|
672
|
+
disp_max_tiling = epipolar_disparity_map.attributes[
|
|
673
|
+
"disp_max_tiling"
|
|
674
|
+
]
|
|
675
|
+
|
|
676
|
+
# change to N+1 M+1 dimension, fitting to tiling
|
|
677
|
+
(
|
|
678
|
+
disp_min_tiling,
|
|
679
|
+
disp_max_tiling,
|
|
680
|
+
) = tiling.transform_disp_range_grid_to_two_layers(
|
|
681
|
+
disp_min_tiling, disp_max_tiling
|
|
682
|
+
)
|
|
683
|
+
(
|
|
684
|
+
epipolar_grid_min,
|
|
685
|
+
epipolar_grid_max,
|
|
686
|
+
) = grid_generation_algo.compute_epipolar_grid_min_max(
|
|
687
|
+
geometry_plugin,
|
|
688
|
+
tiling.transform_four_layers_to_two_layers_grid(
|
|
689
|
+
epipolar_image.tiling_grid
|
|
690
|
+
),
|
|
691
|
+
sensor1,
|
|
692
|
+
sensor2,
|
|
693
|
+
geomodel1,
|
|
694
|
+
geomodel2,
|
|
695
|
+
grid_left,
|
|
696
|
+
grid_right,
|
|
697
|
+
epsg,
|
|
698
|
+
disp_min_tiling,
|
|
699
|
+
disp_max_tiling,
|
|
700
|
+
)
|
|
701
|
+
# update attributes for corresponding tiles in cloud fusion
|
|
702
|
+
# TODO remove with refactoring
|
|
703
|
+
pc_attributes = {
|
|
704
|
+
"used_epsg_for_terrain_grid": epsg,
|
|
705
|
+
"epipolar_grid_min": epipolar_grid_min,
|
|
706
|
+
"epipolar_grid_max": epipolar_grid_max,
|
|
707
|
+
"largest_epipolar_region": epipolar_image.attributes[
|
|
708
|
+
"largest_epipolar_region"
|
|
709
|
+
],
|
|
710
|
+
"source_pc_names": source_pc_names,
|
|
711
|
+
"source_pc_name": pair_key,
|
|
712
|
+
"color_type": epipolar_image.attributes["image_type"],
|
|
713
|
+
"opt_epipolar_tile_size": epipolar_image.attributes[
|
|
714
|
+
"tile_width"
|
|
715
|
+
],
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
if geoid_path:
|
|
719
|
+
pc_attributes["geoid"] = (geoid_path,)
|
|
720
|
+
|
|
721
|
+
if epipolar_disparity_map.dataset_type not in ("arrays", "points"):
|
|
722
|
+
raise RuntimeError(
|
|
723
|
+
"Triangulation application doesn't support this input "
|
|
724
|
+
"data format"
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
# Check performance_maps_parameters
|
|
728
|
+
performance_maps_to_generate = None
|
|
729
|
+
if performance_maps_param is not None:
|
|
730
|
+
if "performance_map_method" not in performance_maps_param:
|
|
731
|
+
raise RuntimeError("No performance_map_method specified")
|
|
732
|
+
performance_maps_to_generate = performance_maps_param[
|
|
733
|
+
"performance_map_method"
|
|
734
|
+
]
|
|
735
|
+
if "perf_ambiguity_threshold" not in performance_maps_param:
|
|
736
|
+
raise RuntimeError("No perf_ambiguity_threshold specified")
|
|
737
|
+
|
|
738
|
+
# Create CarsDataset
|
|
739
|
+
# Epipolar_point_cloud
|
|
740
|
+
epipolar_point_cloud = cars_dataset.CarsDataset(
|
|
741
|
+
epipolar_disparity_map.dataset_type,
|
|
742
|
+
name="triangulation_" + pair_key,
|
|
743
|
+
)
|
|
744
|
+
epipolar_point_cloud.create_empty_copy(epipolar_disparity_map)
|
|
745
|
+
|
|
746
|
+
# Update attributes to get epipolar info
|
|
747
|
+
epipolar_point_cloud.attributes.update(pc_attributes)
|
|
748
|
+
|
|
749
|
+
# Save objects
|
|
750
|
+
# Save as depth map
|
|
751
|
+
self.save_triangulation_output(
|
|
752
|
+
epipolar_point_cloud,
|
|
753
|
+
sensor_image_left,
|
|
754
|
+
depth_map_dir,
|
|
755
|
+
pair_dump_dir if self.save_intermediate_data else None,
|
|
756
|
+
performance_maps_to_generate,
|
|
757
|
+
save_output_coordinates,
|
|
758
|
+
save_output_color,
|
|
759
|
+
save_output_classification,
|
|
760
|
+
save_output_filling,
|
|
761
|
+
save_output_performance_map,
|
|
762
|
+
save_output_ambiguity,
|
|
763
|
+
)
|
|
764
|
+
self.fill_index(
|
|
765
|
+
save_output_coordinates,
|
|
766
|
+
save_output_color,
|
|
767
|
+
save_output_classification,
|
|
768
|
+
save_output_filling,
|
|
769
|
+
save_output_performance_map,
|
|
770
|
+
save_output_ambiguity,
|
|
771
|
+
pair_key,
|
|
772
|
+
)
|
|
773
|
+
# Save as point cloud
|
|
774
|
+
point_cloud = cars_dataset.CarsDataset(
|
|
775
|
+
"points",
|
|
776
|
+
name="triangulation_flatten_" + pair_key,
|
|
777
|
+
)
|
|
778
|
+
point_cloud.create_empty_copy(epipolar_point_cloud)
|
|
779
|
+
point_cloud.attributes = epipolar_point_cloud.attributes
|
|
780
|
+
|
|
781
|
+
csv_pc_dir_name, laz_pc_dir_name = (
|
|
782
|
+
self.create_point_cloud_directories(
|
|
783
|
+
pair_dump_dir, point_cloud_dir, point_cloud
|
|
784
|
+
)
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
# Get saving infos in order to save tiles when they are computed
|
|
788
|
+
[saving_info_epipolar] = self.orchestrator.get_saving_infos(
|
|
789
|
+
[epipolar_point_cloud]
|
|
790
|
+
)
|
|
791
|
+
saving_info_flatten = None
|
|
792
|
+
if self.save_intermediate_data or point_cloud_dir is not None:
|
|
793
|
+
[saving_info_flatten] = self.orchestrator.get_saving_infos(
|
|
794
|
+
[point_cloud]
|
|
795
|
+
)
|
|
796
|
+
|
|
797
|
+
# Generate Point clouds
|
|
798
|
+
|
|
799
|
+
# initialize empty index file for point cloud product if official
|
|
800
|
+
# product is requested
|
|
801
|
+
pc_index = None
|
|
802
|
+
if point_cloud_dir:
|
|
803
|
+
pc_index = {}
|
|
804
|
+
|
|
805
|
+
for col in range(epipolar_disparity_map.shape[1]):
|
|
806
|
+
for row in range(epipolar_disparity_map.shape[0]):
|
|
807
|
+
if epipolar_disparity_map[row, col] is not None:
|
|
808
|
+
# update saving infos for potential replacement
|
|
809
|
+
full_saving_info_epipolar = ocht.update_saving_infos(
|
|
810
|
+
saving_info_epipolar, row=row, col=col
|
|
811
|
+
)
|
|
812
|
+
full_saving_info_flatten = None
|
|
813
|
+
if saving_info_flatten is not None:
|
|
814
|
+
full_saving_info_flatten = ocht.update_saving_infos(
|
|
815
|
+
saving_info_flatten, row=row, col=col
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
csv_pc_file_name, laz_pc_file_name = (
|
|
819
|
+
triangulation_wrap.generate_point_cloud_file_names(
|
|
820
|
+
csv_pc_dir_name,
|
|
821
|
+
laz_pc_dir_name,
|
|
822
|
+
row,
|
|
823
|
+
col,
|
|
824
|
+
pc_index,
|
|
825
|
+
pair_key,
|
|
826
|
+
)
|
|
827
|
+
)
|
|
828
|
+
|
|
829
|
+
# Compute points
|
|
830
|
+
(
|
|
831
|
+
epipolar_point_cloud[row][col],
|
|
832
|
+
point_cloud[row][col],
|
|
833
|
+
) = self.orchestrator.cluster.create_task(
|
|
834
|
+
triangulation_wrapper, nout=2
|
|
835
|
+
)(
|
|
836
|
+
epipolar_disparity_map[row, col],
|
|
837
|
+
sensor1,
|
|
838
|
+
sensor2,
|
|
839
|
+
geomodel1,
|
|
840
|
+
geomodel2,
|
|
841
|
+
broadcasted_interpolated_grid_left,
|
|
842
|
+
broadcasted_interpolated_grid_right,
|
|
843
|
+
geometry_plugin,
|
|
844
|
+
epsg,
|
|
845
|
+
geoid_path=geoid_path,
|
|
846
|
+
denoising_overload_fun=denoising_overload_fun,
|
|
847
|
+
cloud_id=cloud_id,
|
|
848
|
+
performance_maps_to_generate=(
|
|
849
|
+
performance_maps_to_generate
|
|
850
|
+
),
|
|
851
|
+
performance_maps_parameters=performance_maps_param,
|
|
852
|
+
point_cloud_csv_file_name=csv_pc_file_name,
|
|
853
|
+
point_cloud_laz_file_name=laz_pc_file_name,
|
|
854
|
+
saving_info_epipolar=full_saving_info_epipolar,
|
|
855
|
+
saving_info_flatten=full_saving_info_flatten,
|
|
856
|
+
)
|
|
857
|
+
|
|
858
|
+
# update point cloud index
|
|
859
|
+
if point_cloud_dir:
|
|
860
|
+
self.orchestrator.update_index(pc_index)
|
|
861
|
+
|
|
862
|
+
else:
|
|
863
|
+
epipolar_point_cloud = cars_dataset.CarsDataset(
|
|
864
|
+
"points", name="pandora_sparse_matching_" + pair_key
|
|
865
|
+
)
|
|
866
|
+
epipolar_point_cloud.create_empty_copy(epipolar_disparity_map)
|
|
867
|
+
|
|
868
|
+
# Update attributes to get epipolar info
|
|
869
|
+
epipolar_point_cloud.attributes.update(epipolar_image.attributes)
|
|
870
|
+
|
|
871
|
+
# Add to replace list so tiles will be readable at the same time
|
|
872
|
+
self.orchestrator.add_to_replace_lists(
|
|
873
|
+
epipolar_point_cloud,
|
|
874
|
+
cars_ds_name="triangulated_matches",
|
|
875
|
+
)
|
|
876
|
+
|
|
877
|
+
# Get saving infos in order to save tiles when they are computed
|
|
878
|
+
[saving_info_matches] = self.orchestrator.get_saving_infos(
|
|
879
|
+
[epipolar_point_cloud]
|
|
880
|
+
)
|
|
881
|
+
for col in range(epipolar_disparity_map.shape[1]):
|
|
882
|
+
for row in range(epipolar_disparity_map.shape[0]):
|
|
883
|
+
if epipolar_disparity_map[row, col] is not None:
|
|
884
|
+
# initialize list of matches
|
|
885
|
+
full_saving_info_matches = ocht.update_saving_infos(
|
|
886
|
+
saving_info_matches, row=row, col=col
|
|
887
|
+
)
|
|
888
|
+
|
|
889
|
+
# Compute points
|
|
890
|
+
(
|
|
891
|
+
epipolar_point_cloud[row][col]
|
|
892
|
+
) = self.orchestrator.cluster.create_task(
|
|
893
|
+
triangulation_wrapper_matches, nout=1
|
|
894
|
+
)(
|
|
895
|
+
epipolar_disparity_map[row, col],
|
|
896
|
+
sensor1,
|
|
897
|
+
sensor2,
|
|
898
|
+
geomodel1,
|
|
899
|
+
geomodel2,
|
|
900
|
+
broadcasted_interpolated_grid_left,
|
|
901
|
+
broadcasted_interpolated_grid_right,
|
|
902
|
+
geometry_plugin,
|
|
903
|
+
full_saving_info_matches,
|
|
904
|
+
epsg,
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
return epipolar_point_cloud
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
def triangulation_wrapper( # pylint: disable=too-many-positional-arguments
|
|
911
|
+
disparity_object: xr.Dataset,
|
|
912
|
+
sensor1,
|
|
913
|
+
sensor2,
|
|
914
|
+
geomodel1,
|
|
915
|
+
geomodel2,
|
|
916
|
+
grid1,
|
|
917
|
+
grid2,
|
|
918
|
+
geometry_plugin,
|
|
919
|
+
epsg,
|
|
920
|
+
geoid_path=None,
|
|
921
|
+
denoising_overload_fun=None,
|
|
922
|
+
cloud_id=None,
|
|
923
|
+
performance_maps_to_generate=None,
|
|
924
|
+
performance_maps_parameters=None,
|
|
925
|
+
point_cloud_csv_file_name=None,
|
|
926
|
+
point_cloud_laz_file_name=None,
|
|
927
|
+
saving_info_epipolar=None,
|
|
928
|
+
saving_info_flatten=None,
|
|
929
|
+
) -> Dict[str, Tuple[xr.Dataset, xr.Dataset]]:
|
|
930
|
+
"""
|
|
931
|
+
Compute point clouds from image objects and disparity objects.
|
|
932
|
+
|
|
933
|
+
:param disparity_object: Left disparity map dataset with :
|
|
934
|
+
- cst_disp.MAP
|
|
935
|
+
- cst_disp.VALID
|
|
936
|
+
- cst.EPI_TEXTURE
|
|
937
|
+
:type disparity_object: xr.Dataset
|
|
938
|
+
:param sensor1: path to left sensor image
|
|
939
|
+
:type sensor1: str
|
|
940
|
+
:param sensor2: path to right sensor image
|
|
941
|
+
:type sensor2: str
|
|
942
|
+
:param geomodel1: path and attributes for left geomodel
|
|
943
|
+
:type geomodel1: dict
|
|
944
|
+
:param geomodel2: path and attributes for right geomodel
|
|
945
|
+
:type geomodel2: dict
|
|
946
|
+
:param grid1: dataset of the reference image grid file
|
|
947
|
+
:type grid1: CarsDataset
|
|
948
|
+
:param grid2: dataset of the secondary image grid file
|
|
949
|
+
:type grid2: CarsDataset
|
|
950
|
+
:param geometry_plugin: geometry plugin to use
|
|
951
|
+
:type geometry_plugin: AbstractGeometry
|
|
952
|
+
:param geoid_path: Geoid used for altimetric reference. Defaults to None
|
|
953
|
+
for using ellipsoid as altimetric reference.
|
|
954
|
+
:type geoid_path: str
|
|
955
|
+
:param performance_maps_to_generate: None or list containing
|
|
956
|
+
"risk" or "intervals"
|
|
957
|
+
:param performance_maps_parameters: parameters used to
|
|
958
|
+
generate performance map
|
|
959
|
+
:type performance_maps_parameters: dict or None
|
|
960
|
+
:param denoising_overload_fun: function to overload dataset
|
|
961
|
+
:type denoising_overload_fun: fun
|
|
962
|
+
|
|
963
|
+
:return: Left disparity object
|
|
964
|
+
|
|
965
|
+
Returned object is composed of :
|
|
966
|
+
- dataset with :
|
|
967
|
+
- cst.X
|
|
968
|
+
- cst.Y
|
|
969
|
+
- cst.Z
|
|
970
|
+
- cst.EPI_TEXTURE
|
|
971
|
+
- cst.Z_INF (optional)
|
|
972
|
+
- cst.Z_SUP (optional)
|
|
973
|
+
"""
|
|
974
|
+
|
|
975
|
+
# Get disparity maps
|
|
976
|
+
disp_ref = disparity_object
|
|
977
|
+
|
|
978
|
+
# Triangulate
|
|
979
|
+
if isinstance(disp_ref, xr.Dataset):
|
|
980
|
+
# Triangulate epipolar dense disparities
|
|
981
|
+
points = triangulation_algo.triangulate(
|
|
982
|
+
geometry_plugin,
|
|
983
|
+
sensor1,
|
|
984
|
+
sensor2,
|
|
985
|
+
geomodel1,
|
|
986
|
+
geomodel2,
|
|
987
|
+
grid1,
|
|
988
|
+
grid2,
|
|
989
|
+
disp_ref,
|
|
990
|
+
)
|
|
991
|
+
|
|
992
|
+
if performance_maps_to_generate is not None:
|
|
993
|
+
for perf_method in performance_maps_to_generate:
|
|
994
|
+
# Generate keys to use
|
|
995
|
+
if perf_method == "risk":
|
|
996
|
+
# From pandora loader overload
|
|
997
|
+
disp_keys = [
|
|
998
|
+
"confidence_from_disp_inf_from_risk.cars_2",
|
|
999
|
+
"confidence_from_disp_sup_from_risk.cars_2",
|
|
1000
|
+
]
|
|
1001
|
+
cars_inf_key = cst.POINT_CLOUD_LAYER_INF_FROM_RISK
|
|
1002
|
+
cars_sup_key = cst.POINT_CLOUD_LAYER_SUP_FROM_RISK
|
|
1003
|
+
cars_perf_key = cst.POINT_CLOUD_PERFORMANCE_MAP_FROM_RISK
|
|
1004
|
+
use_ambiguity = True
|
|
1005
|
+
else:
|
|
1006
|
+
# From pandora loader overload
|
|
1007
|
+
disp_keys = [
|
|
1008
|
+
"confidence_from_interval_bounds_inf.cars_3",
|
|
1009
|
+
"confidence_from_interval_bounds_sup.cars_3",
|
|
1010
|
+
]
|
|
1011
|
+
cars_inf_key = cst.POINT_CLOUD_LAYER_INF_FROM_INTERVALS
|
|
1012
|
+
cars_sup_key = cst.POINT_CLOUD_LAYER_SUP_FROM_INTERVALS
|
|
1013
|
+
cars_perf_key = (
|
|
1014
|
+
cst.POINT_CLOUD_PERFORMANCE_MAP_FROM_INTERVALS
|
|
1015
|
+
)
|
|
1016
|
+
use_ambiguity = False
|
|
1017
|
+
|
|
1018
|
+
ambiguity_map = None
|
|
1019
|
+
perf_ambiguity_threshold = None
|
|
1020
|
+
if use_ambiguity:
|
|
1021
|
+
ambiguity_map = disp_ref["ambiguity"]
|
|
1022
|
+
perf_ambiguity_threshold = performance_maps_parameters[
|
|
1023
|
+
"perf_ambiguity_threshold"
|
|
1024
|
+
]
|
|
1025
|
+
# triangulate disp inf and supp
|
|
1026
|
+
points_inf = triangulation_algo.triangulate(
|
|
1027
|
+
geometry_plugin,
|
|
1028
|
+
sensor1,
|
|
1029
|
+
sensor2,
|
|
1030
|
+
geomodel1,
|
|
1031
|
+
geomodel2,
|
|
1032
|
+
grid1,
|
|
1033
|
+
grid2,
|
|
1034
|
+
disp_ref,
|
|
1035
|
+
disp_key=disp_keys[0],
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
points_sup = triangulation_algo.triangulate(
|
|
1039
|
+
geometry_plugin,
|
|
1040
|
+
sensor1,
|
|
1041
|
+
sensor2,
|
|
1042
|
+
geomodel1,
|
|
1043
|
+
geomodel2,
|
|
1044
|
+
grid1,
|
|
1045
|
+
grid2,
|
|
1046
|
+
disp_ref,
|
|
1047
|
+
disp_key=disp_keys[1],
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
points[cst.STEREO_REF][cars_inf_key] = points_inf[
|
|
1051
|
+
cst.STEREO_REF
|
|
1052
|
+
][cst.Z]
|
|
1053
|
+
points[cst.STEREO_REF][cars_sup_key] = points_sup[
|
|
1054
|
+
cst.STEREO_REF
|
|
1055
|
+
][cst.Z]
|
|
1056
|
+
# Generate performance map
|
|
1057
|
+
points[cst.STEREO_REF][cars_perf_key] = (
|
|
1058
|
+
triangulation_wrap.compute_performance_map(
|
|
1059
|
+
points[cst.STEREO_REF][cst.Z],
|
|
1060
|
+
points[cst.STEREO_REF][cars_inf_key],
|
|
1061
|
+
points[cst.STEREO_REF][cars_sup_key],
|
|
1062
|
+
ambiguity_map=ambiguity_map,
|
|
1063
|
+
perf_ambiguity_threshold=perf_ambiguity_threshold,
|
|
1064
|
+
)
|
|
1065
|
+
)
|
|
1066
|
+
|
|
1067
|
+
elif isinstance(disp_ref, pandas.DataFrame):
|
|
1068
|
+
# Triangulate epipolar sparse matches
|
|
1069
|
+
points = {}
|
|
1070
|
+
points[cst.STEREO_REF] = triangulation_algo.triangulate_matches(
|
|
1071
|
+
geometry_plugin,
|
|
1072
|
+
sensor1,
|
|
1073
|
+
sensor2,
|
|
1074
|
+
geomodel1,
|
|
1075
|
+
geomodel2,
|
|
1076
|
+
grid1,
|
|
1077
|
+
grid2,
|
|
1078
|
+
disp_ref.to_numpy(),
|
|
1079
|
+
)
|
|
1080
|
+
else:
|
|
1081
|
+
logging.error(
|
|
1082
|
+
"Disp ref is neither xarray Dataset nor pandas DataFrame"
|
|
1083
|
+
)
|
|
1084
|
+
raise TypeError(
|
|
1085
|
+
"Disp ref is neither xarray Dataset nor pandas DataFrame"
|
|
1086
|
+
)
|
|
1087
|
+
|
|
1088
|
+
if geoid_path is not None: # if user pass a geoid, use it as alt reference
|
|
1089
|
+
for key, point in points.items():
|
|
1090
|
+
points[key] = triangulation_wrap.geoid_offset(point, geoid_path)
|
|
1091
|
+
|
|
1092
|
+
# Fill datasets
|
|
1093
|
+
pc_dataset = points[cst.STEREO_REF]
|
|
1094
|
+
pc_dataset.attrs["cloud_id"] = cloud_id
|
|
1095
|
+
|
|
1096
|
+
# Overload dataset with denoising fun
|
|
1097
|
+
if denoising_overload_fun is not None:
|
|
1098
|
+
if isinstance(pc_dataset, xr.Dataset):
|
|
1099
|
+
denoising_overload_fun(
|
|
1100
|
+
pc_dataset,
|
|
1101
|
+
sensor1,
|
|
1102
|
+
sensor2,
|
|
1103
|
+
geomodel1,
|
|
1104
|
+
geomodel2,
|
|
1105
|
+
grid1,
|
|
1106
|
+
grid2,
|
|
1107
|
+
geometry_plugin,
|
|
1108
|
+
disp_ref,
|
|
1109
|
+
)
|
|
1110
|
+
else:
|
|
1111
|
+
raise RuntimeError("wrong pc type for denoising func")
|
|
1112
|
+
|
|
1113
|
+
attributes = {
|
|
1114
|
+
cst.CROPPED_DISPARITY_RANGE: (
|
|
1115
|
+
ocht.get_disparity_range_cropped(disparity_object)
|
|
1116
|
+
)
|
|
1117
|
+
}
|
|
1118
|
+
cars_dataset.fill_dataset(
|
|
1119
|
+
pc_dataset,
|
|
1120
|
+
saving_info=saving_info_epipolar,
|
|
1121
|
+
window=cars_dataset.get_window_dataset(disparity_object),
|
|
1122
|
+
profile=cars_dataset.get_profile_rasterio(disparity_object),
|
|
1123
|
+
attributes=attributes,
|
|
1124
|
+
overlaps=cars_dataset.get_overlaps_dataset(disparity_object),
|
|
1125
|
+
)
|
|
1126
|
+
|
|
1127
|
+
# Flatten point cloud to save it as LAZ
|
|
1128
|
+
flatten_pc_dataset = None
|
|
1129
|
+
if point_cloud_csv_file_name or point_cloud_laz_file_name:
|
|
1130
|
+
# Convert epipolar array into point cloud
|
|
1131
|
+
flatten_pc_dataset, cloud_epsg = (
|
|
1132
|
+
pc_transform.depth_map_dataset_to_dataframe(pc_dataset, epsg)
|
|
1133
|
+
)
|
|
1134
|
+
# Convert to wanted epsg
|
|
1135
|
+
if epsg is not None and cloud_epsg != epsg:
|
|
1136
|
+
projection.point_cloud_conversion_dataframe(
|
|
1137
|
+
flatten_pc_dataset, cloud_epsg, epsg
|
|
1138
|
+
)
|
|
1139
|
+
cloud_epsg = epsg
|
|
1140
|
+
|
|
1141
|
+
# Fill attributes for LAZ saving
|
|
1142
|
+
color_type = pc_transform.get_color_type([pc_dataset])
|
|
1143
|
+
attributes = {
|
|
1144
|
+
"epsg": cloud_epsg,
|
|
1145
|
+
"color_type": color_type,
|
|
1146
|
+
}
|
|
1147
|
+
cars_dataset.fill_dataframe(
|
|
1148
|
+
flatten_pc_dataset,
|
|
1149
|
+
saving_info=saving_info_flatten,
|
|
1150
|
+
attributes=attributes,
|
|
1151
|
+
)
|
|
1152
|
+
# Save point cloud in worker
|
|
1153
|
+
if point_cloud_csv_file_name:
|
|
1154
|
+
cars_dataset.run_save_points(
|
|
1155
|
+
flatten_pc_dataset,
|
|
1156
|
+
point_cloud_csv_file_name,
|
|
1157
|
+
overwrite=True,
|
|
1158
|
+
point_cloud_format="csv",
|
|
1159
|
+
overwrite_file_name=False,
|
|
1160
|
+
)
|
|
1161
|
+
if point_cloud_laz_file_name:
|
|
1162
|
+
cars_dataset.run_save_points(
|
|
1163
|
+
flatten_pc_dataset,
|
|
1164
|
+
point_cloud_laz_file_name,
|
|
1165
|
+
overwrite=True,
|
|
1166
|
+
point_cloud_format="laz",
|
|
1167
|
+
overwrite_file_name=False,
|
|
1168
|
+
)
|
|
1169
|
+
|
|
1170
|
+
return pc_dataset, flatten_pc_dataset
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
# pylint: disable=too-many-positional-arguments
|
|
1174
|
+
def triangulation_wrapper_matches(
|
|
1175
|
+
matches,
|
|
1176
|
+
sensor1,
|
|
1177
|
+
sensor2,
|
|
1178
|
+
geomodel1,
|
|
1179
|
+
geomodel2,
|
|
1180
|
+
grid1,
|
|
1181
|
+
grid2,
|
|
1182
|
+
geometry_plugin,
|
|
1183
|
+
full_saving_info_matches,
|
|
1184
|
+
epsg,
|
|
1185
|
+
):
|
|
1186
|
+
"""
|
|
1187
|
+
:param matches: matches
|
|
1188
|
+
:type matches: cars_dataset
|
|
1189
|
+
:param sensor1: path to left sensor image
|
|
1190
|
+
:type sensor1: str
|
|
1191
|
+
:param sensor2: path to right sensor image
|
|
1192
|
+
:type sensor2: str
|
|
1193
|
+
:param interpolated_grid1: rectification grid left
|
|
1194
|
+
:type interpolated_grid1: shareloc.rectificationGrid
|
|
1195
|
+
:param interpolated_grid2: rectification grid right
|
|
1196
|
+
:type interpolated_grid2: shareloc.rectificationGrid
|
|
1197
|
+
:param geometry_plugin: geometry plugin to use
|
|
1198
|
+
:type geometry_plugin: AbstractGeometry
|
|
1199
|
+
:param epsg: ground epsg
|
|
1200
|
+
:type epsg: int
|
|
1201
|
+
"""
|
|
1202
|
+
|
|
1203
|
+
# Ignore this tile if there are not match
|
|
1204
|
+
if matches is None or matches.empty:
|
|
1205
|
+
return None
|
|
1206
|
+
|
|
1207
|
+
epipolar_matches = matches.to_numpy()
|
|
1208
|
+
|
|
1209
|
+
sensor_matches = geometry_plugin.matches_to_sensor_coords(
|
|
1210
|
+
grid1,
|
|
1211
|
+
grid2,
|
|
1212
|
+
epipolar_matches,
|
|
1213
|
+
cst.MATCHES_MODE,
|
|
1214
|
+
)
|
|
1215
|
+
sensor_matches = np.concatenate(sensor_matches, axis=1)
|
|
1216
|
+
matches = np.concatenate(
|
|
1217
|
+
[
|
|
1218
|
+
epipolar_matches,
|
|
1219
|
+
sensor_matches,
|
|
1220
|
+
],
|
|
1221
|
+
axis=1,
|
|
1222
|
+
)
|
|
1223
|
+
|
|
1224
|
+
# Triangulate matches
|
|
1225
|
+
triangulated_matches = triangulation_algo.triangulate_sparse_matches(
|
|
1226
|
+
sensor1,
|
|
1227
|
+
sensor2,
|
|
1228
|
+
geomodel1,
|
|
1229
|
+
geomodel2,
|
|
1230
|
+
grid1,
|
|
1231
|
+
grid2,
|
|
1232
|
+
matches,
|
|
1233
|
+
geometry_plugin,
|
|
1234
|
+
epsg,
|
|
1235
|
+
)
|
|
1236
|
+
|
|
1237
|
+
cars_dataset.fill_dataframe(
|
|
1238
|
+
triangulated_matches,
|
|
1239
|
+
saving_info=full_saving_info_matches,
|
|
1240
|
+
attributes={"epsg": triangulated_matches.attrs["epsg"]},
|
|
1241
|
+
)
|
|
1242
|
+
|
|
1243
|
+
return triangulated_matches
|