cars 1.0.0a3__cp39-cp39-win_amd64.whl → 1.0.0a4__cp39-cp39-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 +5 -5
- cars/applications/__init__.py +0 -3
- cars/applications/application_template.py +20 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +80 -36
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +23 -57
- cars/applications/dem_generation/dichotomic_generation_app.py +3 -3
- cars/applications/dem_generation/rasterization_app.py +100 -41
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +38 -39
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-win_amd64.pyd +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +48 -14
- cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
- cars/applications/dense_matching/disparity_grid_algo.py +84 -62
- cars/applications/dense_matching/loaders/pandora_loader.py +91 -33
- cars/applications/dsm_filling/border_interpolation_app.py +1 -7
- cars/applications/dsm_filling/bulldozer_filling_app.py +2 -8
- cars/applications/dsm_filling/exogenous_filling_app.py +4 -9
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +2 -1
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +96 -267
- cars/applications/point_cloud_outlier_removal/statistical_app.py +116 -275
- cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +60 -113
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +16 -4
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +3 -3
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +256 -25
- cars/core/geometry/shareloc_geometry.py +110 -82
- cars/core/inputs.py +57 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +9 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +5 -5
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +148 -21
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +11 -3
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +14 -3
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +462 -1073
- cars/pipelines/parameters/advanced_parameters.py +74 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +2 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +2 -2
- cars/pipelines/parameters/sensor_inputs.py +30 -75
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +527 -1016
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/RECORD +116 -132
- cars.libs/.load-order-cars-1.0.0a4 +3 -0
- cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
- cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
- cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
- cars/applications/dense_match_filling/cpp/__init__.py +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp39-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp39-win_amd64.pyd +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
- cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
- cars/applications/dense_match_filling/cpp/meson.build +0 -9
- cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
- cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
- cars/applications/dense_match_filling/plane_app.py +0 -556
- cars/applications/hole_detection/__init__.py +0 -30
- cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
- cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
- cars/applications/hole_detection/hole_detection_algo.py +0 -144
- cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
- cars/applications/point_cloud_denoising/__init__.py +0 -29
- cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
- cars/applications/point_cloud_fusion/__init__.py +0 -30
- cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
- cars-1.0.0a3.dist-info/DELVEWHEEL +0 -2
- cars.libs/.load-order-cars-1.0.0a3 +0 -3
- cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
- cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
- cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -33,7 +33,10 @@ from typing import Dict, List, Tuple, Union
|
|
|
33
33
|
import numpy as np
|
|
34
34
|
import rasterio as rio
|
|
35
35
|
import xarray as xr
|
|
36
|
-
from
|
|
36
|
+
from affine import Affine
|
|
37
|
+
from json_checker import And, Checker
|
|
38
|
+
from rasterio.enums import Resampling
|
|
39
|
+
from rasterio.warp import reproject
|
|
37
40
|
from scipy import interpolate
|
|
38
41
|
from scipy.interpolate import LinearNDInterpolator
|
|
39
42
|
from shapely.geometry import Polygon
|
|
@@ -41,19 +44,26 @@ from shareloc import proj_utils
|
|
|
41
44
|
from shareloc.geofunctions.rectification_grid import RectificationGrid
|
|
42
45
|
|
|
43
46
|
from cars.core import constants as cst
|
|
44
|
-
from cars.core import inputs, outputs
|
|
47
|
+
from cars.core import inputs, outputs, projection
|
|
45
48
|
from cars.core.utils import safe_makedirs
|
|
46
49
|
from cars.data_structures import cars_dataset
|
|
50
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
47
51
|
|
|
48
52
|
|
|
49
|
-
class AbstractGeometry(metaclass=ABCMeta):
|
|
53
|
+
class AbstractGeometry(metaclass=ABCMeta): # pylint: disable=R0902
|
|
50
54
|
"""
|
|
51
55
|
AbstractGeometry
|
|
52
56
|
"""
|
|
53
57
|
|
|
54
58
|
available_plugins: Dict = {}
|
|
55
59
|
|
|
56
|
-
def __new__(
|
|
60
|
+
def __new__(
|
|
61
|
+
cls,
|
|
62
|
+
geometry_plugin_conf=None,
|
|
63
|
+
pairs_for_roi=None,
|
|
64
|
+
scaling_coeff=1,
|
|
65
|
+
**kwargs,
|
|
66
|
+
):
|
|
57
67
|
"""
|
|
58
68
|
Return the required plugin
|
|
59
69
|
:raises:
|
|
@@ -99,31 +109,218 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
99
109
|
)
|
|
100
110
|
return super().__new__(cls)
|
|
101
111
|
|
|
102
|
-
def __init__(
|
|
112
|
+
def __init__( # pylint: disable=too-many-positional-arguments
|
|
103
113
|
self,
|
|
104
114
|
geometry_plugin_conf,
|
|
105
115
|
dem=None,
|
|
106
116
|
geoid=None,
|
|
107
117
|
default_alt=None,
|
|
118
|
+
pairs_for_roi=None,
|
|
108
119
|
scaling_coeff=1,
|
|
120
|
+
output_dem_dir=None,
|
|
109
121
|
**kwargs,
|
|
110
122
|
):
|
|
111
|
-
|
|
112
123
|
self.scaling_coeff = scaling_coeff
|
|
113
124
|
|
|
114
|
-
|
|
125
|
+
self.used_config = self.check_conf(geometry_plugin_conf)
|
|
115
126
|
|
|
116
|
-
self.plugin_name =
|
|
117
|
-
self.interpolator =
|
|
118
|
-
self.dem_roi_margin =
|
|
119
|
-
|
|
120
|
-
self.dem = dem
|
|
127
|
+
self.plugin_name = self.used_config["plugin_name"]
|
|
128
|
+
self.interpolator = self.used_config["interpolator"]
|
|
129
|
+
self.dem_roi_margin = self.used_config["dem_roi_margin"]
|
|
130
|
+
self.dem = None
|
|
121
131
|
self.dem_roi = None
|
|
122
132
|
self.dem_roi_epsg = None
|
|
123
133
|
self.geoid = geoid
|
|
124
134
|
self.default_alt = default_alt
|
|
135
|
+
self.elevation = default_alt
|
|
136
|
+
# a margin is needed for cubic interpolation
|
|
137
|
+
self.rectification_grid_margin = 0
|
|
138
|
+
if self.interpolator == "cubic":
|
|
139
|
+
self.rectification_grid_margin = 5
|
|
125
140
|
self.kwargs = kwargs
|
|
126
141
|
|
|
142
|
+
# compute roi only when generating geometry object with dem
|
|
143
|
+
if dem is not None:
|
|
144
|
+
self.dem = dem
|
|
145
|
+
self.default_alt = self.get_dem_median_value()
|
|
146
|
+
self.elevation = self.default_alt
|
|
147
|
+
logging.info(
|
|
148
|
+
"Median value of DEM ({}) will be used as default_alt".format(
|
|
149
|
+
self.default_alt
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
if pairs_for_roi is not None:
|
|
153
|
+
self.dem_roi_epsg = inputs.rasterio_get_epsg(dem)
|
|
154
|
+
self.dem_roi = self.get_roi(
|
|
155
|
+
pairs_for_roi,
|
|
156
|
+
self.dem_roi_epsg,
|
|
157
|
+
z_min=-1000,
|
|
158
|
+
z_max=9000,
|
|
159
|
+
linear_margin=self.dem_roi_margin[0],
|
|
160
|
+
constant_margin=self.dem_roi_margin[1],
|
|
161
|
+
)
|
|
162
|
+
if output_dem_dir is not None:
|
|
163
|
+
self.dem = self.extend_dem_to_roi(dem, output_dem_dir)
|
|
164
|
+
|
|
165
|
+
def get_dem_median_value(self):
|
|
166
|
+
"""
|
|
167
|
+
Compute dem median value
|
|
168
|
+
:param dem: path of DEM
|
|
169
|
+
"""
|
|
170
|
+
with rio.open(self.dem) as dem_file:
|
|
171
|
+
dem_data = dem_file.read(1)
|
|
172
|
+
median_value = np.nanmedian(dem_data)
|
|
173
|
+
median_value = float(median_value)
|
|
174
|
+
return median_value
|
|
175
|
+
|
|
176
|
+
def get_roi( # pylint: disable=too-many-positional-arguments
|
|
177
|
+
self,
|
|
178
|
+
pairs_for_roi,
|
|
179
|
+
epsg,
|
|
180
|
+
z_min=0,
|
|
181
|
+
z_max=0,
|
|
182
|
+
linear_margin=0,
|
|
183
|
+
constant_margin=0.012,
|
|
184
|
+
):
|
|
185
|
+
"""
|
|
186
|
+
Compute region of interest for intersection of DEM
|
|
187
|
+
|
|
188
|
+
:param pairs_for_roi: list of pairs of images and geomodels
|
|
189
|
+
:type pairs_for_roi: List[(str, dict, str, dict)]
|
|
190
|
+
:param dem_epsg: output EPSG code for ROI
|
|
191
|
+
:type dem_epsg: int
|
|
192
|
+
:param linear_margin: margin for ROI (factor of initial ROI size)
|
|
193
|
+
:type linear_margin: float
|
|
194
|
+
:param constant_margin: margin for ROI in degrees
|
|
195
|
+
:type constant_margin: float
|
|
196
|
+
"""
|
|
197
|
+
coords_list = []
|
|
198
|
+
z_min = np.array(z_min)
|
|
199
|
+
z_max = np.array(z_max)
|
|
200
|
+
for image1, geomodel1, image2, geomodel2 in pairs_for_roi:
|
|
201
|
+
# Footprint of left image with altitude z_min
|
|
202
|
+
coords_list.extend(
|
|
203
|
+
self.image_envelope(
|
|
204
|
+
image1["main_file"], geomodel1, elevation=z_min
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
# Footprint of left image with altitude z_max
|
|
208
|
+
coords_list.extend(
|
|
209
|
+
self.image_envelope(
|
|
210
|
+
image1["main_file"], geomodel1, elevation=z_max
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
# Footprint of right image with altitude z_min
|
|
214
|
+
coords_list.extend(
|
|
215
|
+
self.image_envelope(
|
|
216
|
+
image2["main_file"], geomodel2, elevation=z_min
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
# Footprint of right image with altitude z_max
|
|
220
|
+
coords_list.extend(
|
|
221
|
+
self.image_envelope(
|
|
222
|
+
image2["main_file"], geomodel2, elevation=z_max
|
|
223
|
+
)
|
|
224
|
+
)
|
|
225
|
+
lon_list, lat_list = list(zip(*coords_list)) # noqa: B905
|
|
226
|
+
roi = [
|
|
227
|
+
min(lon_list) - constant_margin,
|
|
228
|
+
min(lat_list) - constant_margin,
|
|
229
|
+
max(lon_list) + constant_margin,
|
|
230
|
+
max(lat_list) + constant_margin,
|
|
231
|
+
]
|
|
232
|
+
points = np.array(
|
|
233
|
+
[
|
|
234
|
+
(roi[0], roi[1], 0),
|
|
235
|
+
(roi[2], roi[3], 0),
|
|
236
|
+
(roi[0], roi[1], 0),
|
|
237
|
+
(roi[2], roi[3], 0),
|
|
238
|
+
]
|
|
239
|
+
)
|
|
240
|
+
new_points = projection.point_cloud_conversion(points, 4326, epsg)
|
|
241
|
+
roi = [
|
|
242
|
+
min(new_points[:, 0]),
|
|
243
|
+
min(new_points[:, 1]),
|
|
244
|
+
max(new_points[:, 0]),
|
|
245
|
+
max(new_points[:, 1]),
|
|
246
|
+
]
|
|
247
|
+
|
|
248
|
+
lon_size = roi[2] - roi[0]
|
|
249
|
+
lat_size = roi[3] - roi[1]
|
|
250
|
+
|
|
251
|
+
roi[0] -= linear_margin * lon_size
|
|
252
|
+
roi[1] -= linear_margin * lat_size
|
|
253
|
+
roi[2] += linear_margin * lon_size
|
|
254
|
+
roi[3] += linear_margin * lat_size
|
|
255
|
+
|
|
256
|
+
return roi
|
|
257
|
+
|
|
258
|
+
def extend_dem_to_roi(self, dem, output_dem_dir):
|
|
259
|
+
"""
|
|
260
|
+
Extend the size of the dem to the required ROI and fill
|
|
261
|
+
:param dem: path to the input DEM
|
|
262
|
+
:param output_dem_dir: path to write the output extended DEM
|
|
263
|
+
"""
|
|
264
|
+
with rio.open(dem) as in_dem:
|
|
265
|
+
src_dem = in_dem.read(1)
|
|
266
|
+
metadata = in_dem.meta
|
|
267
|
+
src_transform = in_dem.transform
|
|
268
|
+
crs = in_dem.crs
|
|
269
|
+
bounds = in_dem.bounds
|
|
270
|
+
|
|
271
|
+
logging.info(
|
|
272
|
+
"DEM bounds : {}, {}, {}, {}".format(
|
|
273
|
+
bounds.left, bounds.top, bounds.right, bounds.bottom
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
logging.info(
|
|
277
|
+
"ROI bounds : {}, {}, {}, {}".format(
|
|
278
|
+
self.dem_roi[0],
|
|
279
|
+
self.dem_roi[1],
|
|
280
|
+
self.dem_roi[2],
|
|
281
|
+
self.dem_roi[3],
|
|
282
|
+
)
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Longitude
|
|
286
|
+
lon_res = src_transform[0]
|
|
287
|
+
lon_shift = (self.dem_roi[0] - bounds.left) / lon_res
|
|
288
|
+
dst_width = int((self.dem_roi[2] - self.dem_roi[0]) / abs(lon_res)) + 1
|
|
289
|
+
# Latitude
|
|
290
|
+
lat_res = src_transform[4]
|
|
291
|
+
lat_shift = (self.dem_roi[3] - bounds.top) / lat_res
|
|
292
|
+
dst_height = int((self.dem_roi[3] - self.dem_roi[1]) / abs(lat_res)) + 1
|
|
293
|
+
|
|
294
|
+
shift = Affine.translation(lon_shift, lat_shift)
|
|
295
|
+
dst_transform = src_transform * shift
|
|
296
|
+
dst_dem = np.zeros((dst_height, dst_width))
|
|
297
|
+
|
|
298
|
+
reproject(
|
|
299
|
+
source=src_dem,
|
|
300
|
+
destination=dst_dem,
|
|
301
|
+
src_transform=src_transform,
|
|
302
|
+
src_crs=crs,
|
|
303
|
+
dst_transform=dst_transform,
|
|
304
|
+
dst_crs=crs,
|
|
305
|
+
resampling=Resampling.bilinear,
|
|
306
|
+
)
|
|
307
|
+
# Fill nodata
|
|
308
|
+
dst_dem = rio.fill.fillnodata(
|
|
309
|
+
dst_dem,
|
|
310
|
+
mask=~(dst_dem == 0),
|
|
311
|
+
)
|
|
312
|
+
metadata["transform"] = dst_transform
|
|
313
|
+
metadata["height"] = dst_height
|
|
314
|
+
metadata["width"] = dst_width
|
|
315
|
+
metadata["driver"] = "GTiff"
|
|
316
|
+
|
|
317
|
+
out_dem_path = os.path.join(output_dem_dir, "initial_elevation.tif")
|
|
318
|
+
|
|
319
|
+
with rio.open(out_dem_path, "w", **metadata) as dst:
|
|
320
|
+
dst.write(dst_dem, 1)
|
|
321
|
+
|
|
322
|
+
return out_dem_path
|
|
323
|
+
|
|
127
324
|
@classmethod
|
|
128
325
|
def register_subclass(cls, short_name: str):
|
|
129
326
|
"""
|
|
@@ -169,13 +366,13 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
169
366
|
)
|
|
170
367
|
overloaded_conf["interpolator"] = conf.get("interpolator", "cubic")
|
|
171
368
|
overloaded_conf["dem_roi_margin"] = conf.get(
|
|
172
|
-
"dem_roi_margin",
|
|
369
|
+
"dem_roi_margin", [0.75, 0.02]
|
|
173
370
|
)
|
|
174
371
|
|
|
175
372
|
geometry_schema = {
|
|
176
373
|
"plugin_name": str,
|
|
177
374
|
"interpolator": And(str, lambda x: x in ["cubic", "linear"]),
|
|
178
|
-
"dem_roi_margin":
|
|
375
|
+
"dem_roi_margin": [float],
|
|
179
376
|
}
|
|
180
377
|
|
|
181
378
|
# Check conf
|
|
@@ -185,7 +382,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
185
382
|
return overloaded_conf
|
|
186
383
|
|
|
187
384
|
@abstractmethod
|
|
188
|
-
def triangulate(
|
|
385
|
+
def triangulate( # pylint: disable=too-many-positional-arguments
|
|
189
386
|
self,
|
|
190
387
|
sensor1,
|
|
191
388
|
sensor2,
|
|
@@ -196,6 +393,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
196
393
|
grid1: str,
|
|
197
394
|
grid2: str,
|
|
198
395
|
roi_key: Union[None, str] = None,
|
|
396
|
+
interpolation_method=None,
|
|
199
397
|
) -> np.ndarray:
|
|
200
398
|
"""
|
|
201
399
|
Performs triangulation from cars disparity or matches dataset
|
|
@@ -225,6 +423,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
225
423
|
:return: True if the products are readable, False otherwise
|
|
226
424
|
"""
|
|
227
425
|
|
|
426
|
+
# pylint: disable=too-many-positional-arguments
|
|
228
427
|
@abstractmethod
|
|
229
428
|
def generate_epipolar_grids(
|
|
230
429
|
self, sensor1, sensor2, geomodel1, geomodel2, epipolar_step: int = 30
|
|
@@ -259,6 +458,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
259
458
|
"""
|
|
260
459
|
return geomodel
|
|
261
460
|
|
|
461
|
+
# pylint: disable=too-many-positional-arguments
|
|
262
462
|
def matches_to_sensor_coords(
|
|
263
463
|
self,
|
|
264
464
|
grid1: Union[str, cars_dataset.CarsDataset, RectificationGrid],
|
|
@@ -267,6 +467,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
267
467
|
matches_type: str,
|
|
268
468
|
matches_msk: np.ndarray = None,
|
|
269
469
|
ul_matches_shift: Tuple[int, int] = None,
|
|
470
|
+
interpolation_method=None,
|
|
270
471
|
) -> Tuple[np.ndarray, np.ndarray]:
|
|
271
472
|
"""
|
|
272
473
|
Convert matches (sparse or dense matches) given in epipolar
|
|
@@ -340,10 +541,10 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
340
541
|
|
|
341
542
|
# convert epipolar matches to sensor coordinates
|
|
342
543
|
sensor_pos_left = self.sensor_position_from_grid(
|
|
343
|
-
grid1, vec_epi_pos_left
|
|
544
|
+
grid1, vec_epi_pos_left, interpolation_method=interpolation_method
|
|
344
545
|
)
|
|
345
546
|
sensor_pos_right = self.sensor_position_from_grid(
|
|
346
|
-
grid2, vec_epi_pos_right
|
|
547
|
+
grid2, vec_epi_pos_right, interpolation_method=interpolation_method
|
|
347
548
|
)
|
|
348
549
|
|
|
349
550
|
if matches_type == cst.DISP_MODE:
|
|
@@ -379,6 +580,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
379
580
|
self,
|
|
380
581
|
grid: Union[dict, RectificationGrid],
|
|
381
582
|
positions: np.ndarray,
|
|
583
|
+
interpolation_method=None,
|
|
382
584
|
) -> np.ndarray:
|
|
383
585
|
"""
|
|
384
586
|
Interpolate the positions given as inputs using the grid
|
|
@@ -451,6 +653,11 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
451
653
|
min_row_idx : max_row_idx + 1, min_col_idx : max_col_idx + 1
|
|
452
654
|
]
|
|
453
655
|
|
|
656
|
+
if interpolation_method is not None:
|
|
657
|
+
method = interpolation_method
|
|
658
|
+
else:
|
|
659
|
+
method = self.interpolator
|
|
660
|
+
|
|
454
661
|
# interpolate sensor positions
|
|
455
662
|
interpolator = interpolate.RegularGridInterpolator(
|
|
456
663
|
(cols_cropped, rows_cropped),
|
|
@@ -461,13 +668,35 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
461
668
|
),
|
|
462
669
|
axis=2,
|
|
463
670
|
),
|
|
464
|
-
method=
|
|
671
|
+
method=method,
|
|
465
672
|
bounds_error=False,
|
|
466
673
|
fill_value=None,
|
|
467
674
|
)
|
|
468
675
|
|
|
469
676
|
sensor_positions = interpolator(positions)
|
|
470
677
|
|
|
678
|
+
min_row = np.min(sensor_row_positions_cropped)
|
|
679
|
+
max_row = np.max(sensor_row_positions_cropped)
|
|
680
|
+
min_col = np.min(sensor_col_positions_cropped)
|
|
681
|
+
max_col = np.max(sensor_col_positions_cropped)
|
|
682
|
+
|
|
683
|
+
valid_rows = np.logical_and(
|
|
684
|
+
sensor_positions[:, 0] > min_row,
|
|
685
|
+
sensor_positions[:, 0] < max_row,
|
|
686
|
+
)
|
|
687
|
+
valid_cols = np.logical_and(
|
|
688
|
+
sensor_positions[:, 1] > min_col,
|
|
689
|
+
sensor_positions[:, 1] < max_col,
|
|
690
|
+
)
|
|
691
|
+
valid = np.logical_and(valid_rows, valid_cols)
|
|
692
|
+
|
|
693
|
+
if np.sum(~valid) > 0:
|
|
694
|
+
logging.warning(
|
|
695
|
+
"{}/{} points are outside of epipolar grid".format(
|
|
696
|
+
np.sum(~valid), valid.size
|
|
697
|
+
)
|
|
698
|
+
)
|
|
699
|
+
|
|
471
700
|
# swap
|
|
472
701
|
sensor_positions[:, [0, 1]] = sensor_positions[:, [1, 0]]
|
|
473
702
|
|
|
@@ -527,6 +756,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
527
756
|
|
|
528
757
|
return epipolar_positions
|
|
529
758
|
|
|
759
|
+
@cars_profile(name="Transform matches", interval=0.5)
|
|
530
760
|
def transform_matches_from_grids(
|
|
531
761
|
self,
|
|
532
762
|
sensor_matches_left,
|
|
@@ -563,7 +793,8 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
563
793
|
|
|
564
794
|
return new_matches_array
|
|
565
795
|
|
|
566
|
-
|
|
796
|
+
@cars_profile(name="Get sensor matches")
|
|
797
|
+
def get_sensor_matches( # pylint: disable=too-many-positional-arguments
|
|
567
798
|
self,
|
|
568
799
|
matches_array,
|
|
569
800
|
grid_left,
|
|
@@ -572,7 +803,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
572
803
|
save_matches,
|
|
573
804
|
):
|
|
574
805
|
"""
|
|
575
|
-
|
|
806
|
+
Get sensor matches
|
|
576
807
|
|
|
577
808
|
:param grid_left: path to epipolar grid of image 1
|
|
578
809
|
:param grid_left: path to epipolar grid of image 2
|
|
@@ -605,7 +836,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
605
836
|
return sensor_matches_left, sensor_matches_right
|
|
606
837
|
|
|
607
838
|
@abstractmethod
|
|
608
|
-
def direct_loc(
|
|
839
|
+
def direct_loc( # pylint: disable=too-many-positional-arguments
|
|
609
840
|
self,
|
|
610
841
|
sensor,
|
|
611
842
|
geomodel,
|
|
@@ -627,7 +858,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
627
858
|
:return: Latitude, Longitude, Altitude coordinates list as a numpy array
|
|
628
859
|
"""
|
|
629
860
|
|
|
630
|
-
def safe_direct_loc(
|
|
861
|
+
def safe_direct_loc( # pylint: disable=too-many-positional-arguments
|
|
631
862
|
self,
|
|
632
863
|
sensor,
|
|
633
864
|
geomodel,
|
|
@@ -677,7 +908,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
677
908
|
return ground_points
|
|
678
909
|
|
|
679
910
|
@abstractmethod
|
|
680
|
-
def inverse_loc(
|
|
911
|
+
def inverse_loc( # pylint: disable=too-many-positional-arguments
|
|
681
912
|
self,
|
|
682
913
|
sensor,
|
|
683
914
|
geomodel,
|
|
@@ -699,7 +930,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
699
930
|
:return: X / Y / Z Coordinates list in input image as a numpy array
|
|
700
931
|
"""
|
|
701
932
|
|
|
702
|
-
def safe_inverse_loc(
|
|
933
|
+
def safe_inverse_loc( # pylint: disable=too-many-positional-arguments
|
|
703
934
|
self,
|
|
704
935
|
sensor,
|
|
705
936
|
geomodel,
|
|
@@ -751,7 +982,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
751
982
|
image_points[:, status] = image_points_retry
|
|
752
983
|
return image_points[0], image_points[1], image_points[2]
|
|
753
984
|
|
|
754
|
-
def image_envelope(
|
|
985
|
+
def image_envelope( # pylint: disable=too-many-positional-arguments
|
|
755
986
|
self,
|
|
756
987
|
sensor,
|
|
757
988
|
geomodel,
|