cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a4__cp313-cp313-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 +3 -3
- cars/applications/__init__.py +0 -3
- cars/applications/application.py +14 -6
- cars/applications/application_template.py +42 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
- cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
- cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
- cars/applications/dem_generation/rasterization_app.py +112 -43
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-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 +95 -79
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
- cars/applications/dsm_filling/border_interpolation_app.py +11 -12
- cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
- cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
- cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
- cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +88 -116
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +60 -53
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +5 -25
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +364 -22
- cars/core/geometry/shareloc_geometry.py +112 -82
- cars/core/inputs.py +72 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +126 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +12 -10
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +149 -22
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +15 -4
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +461 -1052
- cars/pipelines/parameters/advanced_parameters.py +91 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +122 -73
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +676 -1070
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
- 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.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-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.0a2.dist-info/DELVEWHEEL +0 -2
- cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
- cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
- cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -30,7 +30,7 @@ import numpy as np
|
|
|
30
30
|
import rasterio as rio
|
|
31
31
|
import shareloc.geofunctions.rectification as rectif
|
|
32
32
|
import xarray as xr
|
|
33
|
-
from json_checker import Checker
|
|
33
|
+
from json_checker import And, Checker
|
|
34
34
|
from shareloc.dtm_reader import dtm_reader
|
|
35
35
|
from shareloc.geofunctions import localization
|
|
36
36
|
from shareloc.geofunctions.rectification_grid import RectificationGrid
|
|
@@ -41,7 +41,7 @@ from shareloc.geomodels.rpc import RPC
|
|
|
41
41
|
from shareloc.image import Image
|
|
42
42
|
|
|
43
43
|
from cars.core import constants as cst
|
|
44
|
-
from cars.core import
|
|
44
|
+
from cars.core import projection
|
|
45
45
|
from cars.core.geometry.abstract_geometry import AbstractGeometry
|
|
46
46
|
|
|
47
47
|
GRID_TYPE = "GRID"
|
|
@@ -56,13 +56,15 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
56
56
|
Shareloc geometry class
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
|
-
def __init__(
|
|
59
|
+
def __init__( # pylint: disable=too-many-positional-arguments
|
|
60
60
|
self,
|
|
61
61
|
geometry_plugin_conf,
|
|
62
62
|
dem=None,
|
|
63
63
|
geoid=None,
|
|
64
64
|
default_alt=None,
|
|
65
65
|
pairs_for_roi=None,
|
|
66
|
+
scaling_coeff=1,
|
|
67
|
+
output_dem_dir=None,
|
|
66
68
|
):
|
|
67
69
|
|
|
68
70
|
super().__init__(
|
|
@@ -71,50 +73,28 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
71
73
|
geoid=geoid,
|
|
72
74
|
default_alt=default_alt,
|
|
73
75
|
pairs_for_roi=pairs_for_roi,
|
|
76
|
+
scaling_coeff=scaling_coeff,
|
|
77
|
+
output_dem_dir=output_dem_dir,
|
|
74
78
|
)
|
|
75
79
|
|
|
76
|
-
self.dem_roi = None
|
|
77
|
-
self.roi_shareloc = None
|
|
78
|
-
self.elevation = None
|
|
79
|
-
|
|
80
|
-
# a margin is needed for cubic interpolation
|
|
81
|
-
self.rectification_grid_margin = 0
|
|
82
|
-
if self.interpolator == "cubic":
|
|
83
|
-
self.rectification_grid_margin = 5
|
|
84
|
-
|
|
85
|
-
# compute roi only when generating geometry object with dem
|
|
86
|
-
# even if dem is None
|
|
87
|
-
if geoid is not None and pairs_for_roi is not None:
|
|
88
|
-
self.dem_roi_epsg = 4326
|
|
89
|
-
if dem is not None:
|
|
90
|
-
# Get dem epsg
|
|
91
|
-
self.dem_roi_epsg = inputs.rasterio_get_epsg(dem)
|
|
92
|
-
|
|
93
|
-
self.roi_shareloc = self.get_roi(
|
|
94
|
-
pairs_for_roi,
|
|
95
|
-
self.dem_roi_epsg,
|
|
96
|
-
z_min=0,
|
|
97
|
-
z_max=0,
|
|
98
|
-
margin=self.dem_roi_margin,
|
|
99
|
-
)
|
|
100
|
-
# change convention
|
|
101
|
-
self.dem_roi = [
|
|
102
|
-
self.roi_shareloc[1],
|
|
103
|
-
self.roi_shareloc[0],
|
|
104
|
-
self.roi_shareloc[3],
|
|
105
|
-
self.roi_shareloc[2],
|
|
106
|
-
]
|
|
107
|
-
|
|
108
80
|
if dem is not None:
|
|
109
|
-
|
|
110
81
|
# fill_nodata option should be set when dealing with void in DTM
|
|
111
|
-
# see shareloc DTM limitations in sphinx doc for further
|
|
112
|
-
|
|
82
|
+
# see shareloc DTM limitations in sphinx doc for further detailsd
|
|
113
83
|
try:
|
|
84
|
+
if self.dem_roi is None:
|
|
85
|
+
roi_shareloc = None
|
|
86
|
+
else:
|
|
87
|
+
# From (x, y) to (y, x)
|
|
88
|
+
roi_shareloc = [
|
|
89
|
+
self.dem_roi[1],
|
|
90
|
+
self.dem_roi[0],
|
|
91
|
+
self.dem_roi[3],
|
|
92
|
+
self.dem_roi[2],
|
|
93
|
+
]
|
|
114
94
|
dtm_image = dtm_reader(
|
|
115
|
-
dem,
|
|
116
|
-
geoid,
|
|
117
|
-
roi=
|
|
95
|
+
self.dem,
|
|
96
|
+
self.geoid,
|
|
97
|
+
roi=roi_shareloc,
|
|
118
98
|
roi_is_in_physical_space=True,
|
|
119
99
|
fill_nodata="mean",
|
|
120
100
|
fill_value=0.0,
|
|
@@ -141,7 +121,56 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
141
121
|
else:
|
|
142
122
|
self.elevation = default_alt
|
|
143
123
|
|
|
144
|
-
def
|
|
124
|
+
def check_conf(self, conf):
|
|
125
|
+
"""
|
|
126
|
+
Check configuration
|
|
127
|
+
|
|
128
|
+
:param conf: configuration to check
|
|
129
|
+
:type conf: str or dict
|
|
130
|
+
|
|
131
|
+
:return: full dict
|
|
132
|
+
:rtype: dict
|
|
133
|
+
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
if conf is None:
|
|
137
|
+
raise RuntimeError("Geometry plugin configuration is None")
|
|
138
|
+
|
|
139
|
+
overloaded_conf = {}
|
|
140
|
+
|
|
141
|
+
if isinstance(conf, str):
|
|
142
|
+
conf = {"plugin_name": conf}
|
|
143
|
+
|
|
144
|
+
# overload conf
|
|
145
|
+
overloaded_conf["plugin_name"] = conf.get(
|
|
146
|
+
"plugin_name", "SharelocGeometry"
|
|
147
|
+
)
|
|
148
|
+
overloaded_conf["interpolator"] = conf.get("interpolator", "cubic")
|
|
149
|
+
overloaded_conf["dem_roi_margin"] = conf.get(
|
|
150
|
+
"dem_roi_margin", [0.25, 0.02]
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
geometry_schema = {
|
|
154
|
+
"plugin_name": str,
|
|
155
|
+
"interpolator": And(str, lambda x: x in ["cubic", "linear"]),
|
|
156
|
+
"dem_roi_margin": [float],
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Check conf
|
|
160
|
+
checker = Checker(geometry_schema)
|
|
161
|
+
checker.validate(overloaded_conf)
|
|
162
|
+
|
|
163
|
+
return overloaded_conf
|
|
164
|
+
|
|
165
|
+
def get_roi( # pylint: disable=too-many-positional-arguments
|
|
166
|
+
self,
|
|
167
|
+
pairs_for_roi,
|
|
168
|
+
epsg,
|
|
169
|
+
z_min=0,
|
|
170
|
+
z_max=0,
|
|
171
|
+
linear_margin=0,
|
|
172
|
+
constant_margin=0.012,
|
|
173
|
+
):
|
|
145
174
|
"""
|
|
146
175
|
Compute region of interest for intersection of DEM
|
|
147
176
|
|
|
@@ -149,35 +178,17 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
149
178
|
:type pairs_for_roi: List[(str, dict, str, dict)]
|
|
150
179
|
:param dem_epsg: output EPSG code for ROI
|
|
151
180
|
:type dem_epsg: int
|
|
152
|
-
:param
|
|
153
|
-
:type
|
|
181
|
+
:param linear_margin: margin for ROI (factor of initial ROI size)
|
|
182
|
+
:type linear_margin: float
|
|
183
|
+
:param constant_margin: margin for ROI in degrees
|
|
184
|
+
:type constant_margin: float
|
|
154
185
|
"""
|
|
186
|
+
base_roi = super().get_roi(
|
|
187
|
+
pairs_for_roi, epsg, z_min, z_max, linear_margin, constant_margin
|
|
188
|
+
)
|
|
189
|
+
|
|
155
190
|
coords_list = []
|
|
156
|
-
for image1, geomodel1,
|
|
157
|
-
# Footprint of left image with altitude z_min
|
|
158
|
-
coords_list.extend(
|
|
159
|
-
self.image_envelope(
|
|
160
|
-
image1["main_file"], geomodel1, elevation=z_min
|
|
161
|
-
)
|
|
162
|
-
)
|
|
163
|
-
# Footprint of left image with altitude z_max
|
|
164
|
-
coords_list.extend(
|
|
165
|
-
self.image_envelope(
|
|
166
|
-
image1["main_file"], geomodel1, elevation=z_max
|
|
167
|
-
)
|
|
168
|
-
)
|
|
169
|
-
# Footprint of right image with altitude z_min
|
|
170
|
-
coords_list.extend(
|
|
171
|
-
self.image_envelope(
|
|
172
|
-
image2["main_file"], geomodel2, elevation=z_min
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
# Footprint of right image with altitude z_max
|
|
176
|
-
coords_list.extend(
|
|
177
|
-
self.image_envelope(
|
|
178
|
-
image2["main_file"], geomodel2, elevation=z_max
|
|
179
|
-
)
|
|
180
|
-
)
|
|
191
|
+
for image1, geomodel1, _, geomodel2 in pairs_for_roi:
|
|
181
192
|
# Footprint of rectification grid (with margins)
|
|
182
193
|
image1 = SharelocGeometry.load_image(image1["main_file"])
|
|
183
194
|
geomodel1 = self.load_geom_model(geomodel1)
|
|
@@ -204,28 +215,45 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
204
215
|
)
|
|
205
216
|
lat_min, lon_min, lat_max, lon_max = list(epipolar_extent)
|
|
206
217
|
coords_list.extend([(lon_min, lat_min), (lon_max, lat_max)])
|
|
218
|
+
|
|
207
219
|
lon_list, lat_list = list(zip(*coords_list)) # noqa: B905
|
|
208
220
|
roi = [
|
|
209
|
-
min(
|
|
210
|
-
min(
|
|
211
|
-
max(
|
|
212
|
-
max(
|
|
221
|
+
min(lon_list) - constant_margin,
|
|
222
|
+
min(lat_list) - constant_margin,
|
|
223
|
+
max(lon_list) + constant_margin,
|
|
224
|
+
max(lat_list) + constant_margin,
|
|
213
225
|
]
|
|
214
226
|
points = np.array(
|
|
215
227
|
[
|
|
216
|
-
(roi[
|
|
217
|
-
(roi[
|
|
218
|
-
(roi[
|
|
219
|
-
(roi[
|
|
228
|
+
(roi[0], roi[1], 0),
|
|
229
|
+
(roi[2], roi[3], 0),
|
|
230
|
+
(roi[0], roi[1], 0),
|
|
231
|
+
(roi[2], roi[3], 0),
|
|
220
232
|
]
|
|
221
233
|
)
|
|
222
234
|
new_points = projection.point_cloud_conversion(points, 4326, epsg)
|
|
223
235
|
roi = [
|
|
224
|
-
min(new_points[:, 1]),
|
|
225
236
|
min(new_points[:, 0]),
|
|
226
|
-
|
|
237
|
+
min(new_points[:, 1]),
|
|
227
238
|
max(new_points[:, 0]),
|
|
239
|
+
max(new_points[:, 1]),
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
lon_size = roi[2] - roi[0]
|
|
243
|
+
lat_size = roi[3] - roi[1]
|
|
244
|
+
|
|
245
|
+
roi[0] -= linear_margin * lon_size
|
|
246
|
+
roi[1] -= linear_margin * lat_size
|
|
247
|
+
roi[2] += linear_margin * lon_size
|
|
248
|
+
roi[3] += linear_margin * lat_size
|
|
249
|
+
|
|
250
|
+
roi = [
|
|
251
|
+
min(roi[0], base_roi[0]),
|
|
252
|
+
min(roi[1], base_roi[1]),
|
|
253
|
+
max(roi[2], base_roi[2]),
|
|
254
|
+
max(roi[3], base_roi[3]),
|
|
228
255
|
]
|
|
256
|
+
|
|
229
257
|
return roi
|
|
230
258
|
|
|
231
259
|
@staticmethod
|
|
@@ -304,7 +332,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
304
332
|
|
|
305
333
|
return sensor, overloaded_geomodel
|
|
306
334
|
|
|
307
|
-
def triangulate(
|
|
335
|
+
def triangulate( # pylint: disable=too-many-positional-arguments
|
|
308
336
|
self,
|
|
309
337
|
sensor1,
|
|
310
338
|
sensor2,
|
|
@@ -315,6 +343,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
315
343
|
grid1: Union[dict, RectificationGrid],
|
|
316
344
|
grid2: Union[dict, RectificationGrid],
|
|
317
345
|
roi_key: Union[None, str] = None,
|
|
346
|
+
interpolation_method=None,
|
|
318
347
|
) -> np.ndarray:
|
|
319
348
|
"""
|
|
320
349
|
Performs triangulation from cars disparity or matches dataset
|
|
@@ -396,6 +425,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
396
425
|
|
|
397
426
|
return llh
|
|
398
427
|
|
|
428
|
+
# pylint: disable=too-many-positional-arguments
|
|
399
429
|
def generate_epipolar_grids(
|
|
400
430
|
self,
|
|
401
431
|
sensor1,
|
|
@@ -479,7 +509,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
479
509
|
disp_to_alt_ratio,
|
|
480
510
|
)
|
|
481
511
|
|
|
482
|
-
def direct_loc(
|
|
512
|
+
def direct_loc( # pylint: disable=too-many-positional-arguments
|
|
483
513
|
self,
|
|
484
514
|
sensor,
|
|
485
515
|
geomodel,
|
|
@@ -524,7 +554,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
524
554
|
)
|
|
525
555
|
return latlonalt
|
|
526
556
|
|
|
527
|
-
def inverse_loc(
|
|
557
|
+
def inverse_loc( # pylint: disable=too-many-positional-arguments
|
|
528
558
|
self,
|
|
529
559
|
sensor,
|
|
530
560
|
geomodel,
|
cars/core/inputs.py
CHANGED
|
@@ -35,7 +35,9 @@ import fiona
|
|
|
35
35
|
import numpy as np
|
|
36
36
|
import rasterio as rio
|
|
37
37
|
import xarray as xr
|
|
38
|
+
from affine import Affine
|
|
38
39
|
from json_checker import Checker
|
|
40
|
+
from pyproj import CRS
|
|
39
41
|
from rasterio.warp import Resampling, calculate_default_transform, reproject
|
|
40
42
|
from rasterio.windows import Window
|
|
41
43
|
from shapely.geometry import shape
|
|
@@ -106,7 +108,7 @@ def rasterio_get_values(raster_file: str, x_list, y_list, proj_function):
|
|
|
106
108
|
cloud_out = proj_function(cloud_in, 4326, file_espg)
|
|
107
109
|
|
|
108
110
|
# get the transform and inverse
|
|
109
|
-
aff_tr =
|
|
111
|
+
aff_tr = rasterio_get_transform(raster_file)
|
|
110
112
|
np_tr = np.array(
|
|
111
113
|
[
|
|
112
114
|
[aff_tr[0], aff_tr[1], aff_tr[2]],
|
|
@@ -119,17 +121,28 @@ def rasterio_get_values(raster_file: str, x_list, y_list, proj_function):
|
|
|
119
121
|
# convert sensor to pixel coordinates
|
|
120
122
|
pix_pos = np.hstack([cloud_out, np.ones((len(cloud_out), 1))])
|
|
121
123
|
pix_pos = inv_tr @ pix_pos.T
|
|
122
|
-
pix_pos = pix_pos.T[:, [1, 0]].astype(
|
|
124
|
+
pix_pos = pix_pos.T[:, [1, 0]].astype(
|
|
125
|
+
int
|
|
126
|
+
) # convention (row, col) i.e. (y, x)
|
|
127
|
+
|
|
128
|
+
# crop to dem bounds
|
|
129
|
+
ul_corner = np.array([0, 0])
|
|
130
|
+
lr_corner = np.array([descriptor.height, descriptor.width])
|
|
131
|
+
pix_pos_clipped = np.clip(pix_pos, ul_corner, lr_corner)
|
|
132
|
+
out_of_bounds_pix = np.any(pix_pos != pix_pos_clipped, axis=1)
|
|
133
|
+
pix_pos = pix_pos_clipped
|
|
123
134
|
|
|
124
135
|
# get the data needed
|
|
125
136
|
min_pt = pix_pos.min(axis=0)
|
|
126
137
|
max_pt = pix_pos.max(axis=0)
|
|
127
138
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
window = Window(min_pt[1], min_pt[0],
|
|
139
|
+
height = max_pt[0] - min_pt[0] + 1
|
|
140
|
+
width = max_pt[1] - min_pt[1] + 1
|
|
141
|
+
window = Window(min_pt[1], min_pt[0], width, height)
|
|
131
142
|
|
|
132
143
|
data = descriptor.read(1, window=window)
|
|
144
|
+
if data.size == 0:
|
|
145
|
+
return None
|
|
133
146
|
|
|
134
147
|
# read the data for all points
|
|
135
148
|
max_sampled_pos = np.array(data.shape)[:2] - 1
|
|
@@ -141,6 +154,7 @@ def rasterio_get_values(raster_file: str, x_list, y_list, proj_function):
|
|
|
141
154
|
|
|
142
155
|
if nodata_value is not None:
|
|
143
156
|
z_list[z_list == nodata_value] = np.nan
|
|
157
|
+
z_list[out_of_bounds_pix] = np.nan
|
|
144
158
|
|
|
145
159
|
return z_list
|
|
146
160
|
|
|
@@ -252,19 +266,32 @@ def rasterio_get_pixel_points(raster_file: str, terrain_points) -> list:
|
|
|
252
266
|
|
|
253
267
|
pixel_points = []
|
|
254
268
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
terrain_points[row, 1],
|
|
262
|
-
)
|
|
269
|
+
for row in range(terrain_points.shape[0]):
|
|
270
|
+
pixel_points.append(
|
|
271
|
+
rio.transform.rowcol(
|
|
272
|
+
rasterio_get_transform(raster_file),
|
|
273
|
+
terrain_points[row, 0],
|
|
274
|
+
terrain_points[row, 1],
|
|
263
275
|
)
|
|
276
|
+
)
|
|
264
277
|
|
|
265
278
|
return np.array(pixel_points)
|
|
266
279
|
|
|
267
280
|
|
|
281
|
+
def rasterio_get_resolution(raster_file: str) -> Tuple[float, float]:
|
|
282
|
+
"""
|
|
283
|
+
Get the resolution of raster_file
|
|
284
|
+
|
|
285
|
+
:param raster_file: Image file
|
|
286
|
+
:return: The resolution (res_x, res_y)
|
|
287
|
+
:rtype: tuple
|
|
288
|
+
"""
|
|
289
|
+
transform = list(rasterio_get_transform(raster_file))
|
|
290
|
+
res_x = transform[0]
|
|
291
|
+
res_y = transform[4]
|
|
292
|
+
return (abs(res_x), abs(res_y))
|
|
293
|
+
|
|
294
|
+
|
|
268
295
|
def rasterio_get_bounds(
|
|
269
296
|
raster_file: str, apply_resolution_sign=False
|
|
270
297
|
) -> Tuple[int, int]:
|
|
@@ -277,8 +304,7 @@ def rasterio_get_bounds(
|
|
|
277
304
|
|
|
278
305
|
# get sign of resolution
|
|
279
306
|
if apply_resolution_sign:
|
|
280
|
-
|
|
281
|
-
transform = list(profile["transform"])
|
|
307
|
+
transform = list(rasterio_get_transform(raster_file))
|
|
282
308
|
res_x = transform[0]
|
|
283
309
|
res_y = transform[4]
|
|
284
310
|
res_x /= abs(res_x)
|
|
@@ -353,15 +379,28 @@ def rasterio_get_profile(raster_file: str) -> Dict:
|
|
|
353
379
|
return descriptor.profile
|
|
354
380
|
|
|
355
381
|
|
|
356
|
-
def rasterio_get_transform(raster_file: str) -> Dict:
|
|
382
|
+
def rasterio_get_transform(raster_file: str, convention: str = None) -> Dict:
|
|
357
383
|
"""
|
|
358
384
|
Get the transform of an image file
|
|
359
385
|
|
|
360
386
|
:param raster_file: Image file
|
|
387
|
+
:param convention: The convention to follow: None, "north" or "south"
|
|
361
388
|
:return: The transform of the given image
|
|
362
389
|
"""
|
|
363
|
-
with rio.open(raster_file, "r") as
|
|
364
|
-
|
|
390
|
+
with rio.open(raster_file, "r") as dsc:
|
|
391
|
+
src_tr = dsc.transform
|
|
392
|
+
|
|
393
|
+
if convention == "north" and src_tr.e < 0:
|
|
394
|
+
src_tr = Affine(
|
|
395
|
+
src_tr.a, src_tr.b, src_tr.c, -src_tr.d, -src_tr.e, -src_tr.f
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
elif convention == "south" and src_tr.e > 0:
|
|
399
|
+
src_tr = Affine(
|
|
400
|
+
src_tr.a, src_tr.b, src_tr.c, -src_tr.d, -src_tr.e, -src_tr.f
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
return src_tr
|
|
365
404
|
|
|
366
405
|
|
|
367
406
|
def rasterio_get_epsg(raster_file: str) -> int:
|
|
@@ -378,6 +417,20 @@ def rasterio_get_epsg(raster_file: str) -> int:
|
|
|
378
417
|
return epsg
|
|
379
418
|
|
|
380
419
|
|
|
420
|
+
def rasterio_get_crs(raster_file: str) -> CRS:
|
|
421
|
+
"""
|
|
422
|
+
Get the crs of an image file
|
|
423
|
+
|
|
424
|
+
:param raster_file: Image file
|
|
425
|
+
:return: The crs of the given image
|
|
426
|
+
"""
|
|
427
|
+
crs = None
|
|
428
|
+
with rio.open(raster_file, "r") as descriptor:
|
|
429
|
+
crs = descriptor.crs
|
|
430
|
+
|
|
431
|
+
return crs
|
|
432
|
+
|
|
433
|
+
|
|
381
434
|
def rasterio_transform_epsg(file_name, new_epsg):
|
|
382
435
|
"""
|
|
383
436
|
Modify epsg of raster file
|
|
@@ -408,7 +461,7 @@ def rasterio_transform_epsg(file_name, new_epsg):
|
|
|
408
461
|
reproject(
|
|
409
462
|
source=rio.band(src, i),
|
|
410
463
|
destination=rio.band(dst, i),
|
|
411
|
-
src_transform=
|
|
464
|
+
src_transform=rasterio_get_transform(file_name),
|
|
412
465
|
src_crs=src.crs,
|
|
413
466
|
dst_transform=transform,
|
|
414
467
|
dst_crs=new_epsg,
|
cars/core/outputs.py
CHANGED
|
@@ -110,7 +110,7 @@ def write_vector(polys, path_to_file, epsg, driver="GPKG"):
|
|
|
110
110
|
vector_file.write(poly_dict)
|
|
111
111
|
|
|
112
112
|
|
|
113
|
-
def rasterio_write_georaster(
|
|
113
|
+
def rasterio_write_georaster( # pylint: disable=too-many-positional-arguments
|
|
114
114
|
raster_file: str,
|
|
115
115
|
data: np.ndarray,
|
|
116
116
|
profile: dict = None,
|
cars/core/preprocessing.py
CHANGED
|
@@ -72,13 +72,26 @@ def get_utm_zone_as_epsg_code(lon, lat):
|
|
|
72
72
|
)
|
|
73
73
|
return 32632
|
|
74
74
|
|
|
75
|
+
if lat > 84:
|
|
76
|
+
logging.warning(
|
|
77
|
+
"Since the latitude is above 84°, the EPSG 32661 will be used."
|
|
78
|
+
)
|
|
79
|
+
return 32661
|
|
80
|
+
|
|
81
|
+
if lat < -80:
|
|
82
|
+
logging.warning(
|
|
83
|
+
"Since the latitude is under -80°, the EPSG 32761 will be used."
|
|
84
|
+
)
|
|
85
|
+
return 32761
|
|
86
|
+
|
|
75
87
|
zone = utm.from_latlon(lat, lon)[2]
|
|
76
88
|
|
|
77
89
|
north_south = 600 if lat >= 0 else 700
|
|
78
90
|
return 32000 + north_south + zone
|
|
79
91
|
|
|
80
92
|
|
|
81
|
-
|
|
93
|
+
@cars_profile(name="Compute terrain bbox")
|
|
94
|
+
def compute_terrain_bbox( # pylint: disable=too-many-positional-arguments # noqa: 751
|
|
82
95
|
sensor_image_left,
|
|
83
96
|
sensor_image_right,
|
|
84
97
|
epipolar_image_left,
|
|
@@ -375,7 +388,7 @@ def compute_roi_poly(input_roi_poly, input_roi_epsg, epsg):
|
|
|
375
388
|
|
|
376
389
|
|
|
377
390
|
@cars_profile(name="Compute epsg")
|
|
378
|
-
def compute_epsg(
|
|
391
|
+
def compute_epsg( # pylint: disable=too-many-positional-arguments
|
|
379
392
|
sensor_image_left,
|
|
380
393
|
sensor_image_right,
|
|
381
394
|
grid_left,
|
|
@@ -518,6 +531,7 @@ def crop_terrain_bounds_with_roi(roi_poly, xmin, ymin, xmax, ymax):
|
|
|
518
531
|
return new_xmin, new_ymin, new_xmax, new_ymax
|
|
519
532
|
|
|
520
533
|
|
|
534
|
+
@cars_profile(name="Compute terrain bounds")
|
|
521
535
|
def compute_terrain_bounds(list_of_terrain_roi, roi_poly=None, resolution=0.5):
|
|
522
536
|
"""
|
|
523
537
|
Compute Terrain bounds of merged pairs
|
|
@@ -650,7 +664,7 @@ def convert_optimal_tile_size_with_epsg(
|
|
|
650
664
|
|
|
651
665
|
|
|
652
666
|
@cars_profile(name="Compute epipolar roi")
|
|
653
|
-
def compute_epipolar_roi(
|
|
667
|
+
def compute_epipolar_roi( # pylint: disable=too-many-positional-arguments
|
|
654
668
|
terrain_roi_poly,
|
|
655
669
|
terrain_roi_epsg,
|
|
656
670
|
geometry_plugin,
|