cars 1.0.0a2__cp310-cp310-win_amd64.whl → 1.0.0a4__cp310-cp310-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.cp310-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp310-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.cp310-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp310-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
cars/core/projection.py
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
Projection module:
|
|
23
23
|
contains some general purpose functions using polygons and data projections
|
|
24
24
|
"""
|
|
25
|
-
# pylint: disable=too-many-lines
|
|
25
|
+
# pylint: disable=C0302(too-many-lines)
|
|
26
26
|
|
|
27
27
|
# Standard imports
|
|
28
28
|
import logging
|
|
@@ -42,6 +42,7 @@ from shapely.ops import transform
|
|
|
42
42
|
|
|
43
43
|
from cars.core import constants as cst
|
|
44
44
|
from cars.core import inputs, outputs, utils
|
|
45
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
45
46
|
|
|
46
47
|
|
|
47
48
|
def compute_dem_intersection_with_poly( # noqa: C901
|
|
@@ -182,6 +183,22 @@ def polygon_projection(poly: Polygon, epsg_in: int, epsg_out: int) -> Polygon:
|
|
|
182
183
|
return poly
|
|
183
184
|
|
|
184
185
|
|
|
186
|
+
def polygon_projection_crs(poly: Polygon, crs_in: CRS, crs_out: CRS) -> Polygon:
|
|
187
|
+
"""
|
|
188
|
+
Projects a polygon from an initial crs to another
|
|
189
|
+
|
|
190
|
+
:param poly: poly to project
|
|
191
|
+
:param crs_in: initial crs
|
|
192
|
+
:param crs_out: final crs
|
|
193
|
+
:return: The polygon in the final projection
|
|
194
|
+
"""
|
|
195
|
+
# Project polygon between CRS (keep always_xy for compatibility)
|
|
196
|
+
project = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
|
|
197
|
+
poly = transform(project.transform, poly)
|
|
198
|
+
|
|
199
|
+
return poly
|
|
200
|
+
|
|
201
|
+
|
|
185
202
|
def geo_to_ecef(
|
|
186
203
|
lat: np.ndarray, lon: np.ndarray, alt: np.ndarray
|
|
187
204
|
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
@@ -203,7 +220,7 @@ def geo_to_ecef(
|
|
|
203
220
|
)[0]
|
|
204
221
|
|
|
205
222
|
|
|
206
|
-
def ecef_to_enu(
|
|
223
|
+
def ecef_to_enu( # pylint: disable=too-many-positional-arguments
|
|
207
224
|
x_ecef: np.ndarray,
|
|
208
225
|
y_ecef: np.ndarray,
|
|
209
226
|
z_ecef: np.ndarray,
|
|
@@ -253,7 +270,7 @@ def ecef_to_enu(
|
|
|
253
270
|
return x_east, y_north, z_up
|
|
254
271
|
|
|
255
272
|
|
|
256
|
-
def geo_to_enu(
|
|
273
|
+
def geo_to_enu( # pylint: disable=too-many-positional-arguments
|
|
257
274
|
lat: np.ndarray,
|
|
258
275
|
lon: np.ndarray,
|
|
259
276
|
alt: np.ndarray,
|
|
@@ -302,7 +319,7 @@ def enu_to_aer(
|
|
|
302
319
|
return azimuth, elevation, xyz_range
|
|
303
320
|
|
|
304
321
|
|
|
305
|
-
def geo_to_aer(
|
|
322
|
+
def geo_to_aer( # pylint: disable=too-many-positional-arguments
|
|
306
323
|
lat: np.ndarray,
|
|
307
324
|
lon: np.ndarray,
|
|
308
325
|
alt: np.ndarray,
|
|
@@ -351,6 +368,27 @@ def point_cloud_conversion(
|
|
|
351
368
|
return cloud_in
|
|
352
369
|
|
|
353
370
|
|
|
371
|
+
def point_cloud_conversion_crs(
|
|
372
|
+
cloud_in: np.ndarray, crs_in: int, crs_out: int
|
|
373
|
+
) -> np.ndarray:
|
|
374
|
+
"""
|
|
375
|
+
Convert a point cloud from a SRS to another one.
|
|
376
|
+
|
|
377
|
+
:param cloud_in: cloud to project
|
|
378
|
+
:param crs_in: crs of the input SRS
|
|
379
|
+
:param crs_out: crs of the output SRS
|
|
380
|
+
:return: Projected point cloud
|
|
381
|
+
"""
|
|
382
|
+
# Project point cloud between CRS (keep always_xy for compatibility)
|
|
383
|
+
cloud_in = np.array(cloud_in).T
|
|
384
|
+
transformer = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
|
|
385
|
+
|
|
386
|
+
cloud_in = transformer.transform(*cloud_in)
|
|
387
|
+
cloud_in = np.array(cloud_in).T
|
|
388
|
+
|
|
389
|
+
return cloud_in
|
|
390
|
+
|
|
391
|
+
|
|
354
392
|
def get_xyz_np_array_from_dataset(
|
|
355
393
|
cloud_in: xr.Dataset,
|
|
356
394
|
) -> Tuple[np.array, List[int]]:
|
|
@@ -492,6 +530,8 @@ def ground_polygon_from_envelopes(
|
|
|
492
530
|
return inter, inter.bounds
|
|
493
531
|
|
|
494
532
|
|
|
533
|
+
# pylint: disable=too-many-positional-arguments
|
|
534
|
+
@cars_profile(name="Ground intersection envelopes", interval=0.5)
|
|
495
535
|
def ground_intersection_envelopes(
|
|
496
536
|
sensor1,
|
|
497
537
|
sensor2,
|
|
@@ -558,7 +598,7 @@ def ground_intersection_envelopes(
|
|
|
558
598
|
return inter_poly, (inter_xmin, inter_ymin, inter_xmax, inter_ymax)
|
|
559
599
|
|
|
560
600
|
|
|
561
|
-
def get_ground_direction(
|
|
601
|
+
def get_ground_direction( # pylint: disable=too-many-positional-arguments
|
|
562
602
|
sensor,
|
|
563
603
|
geomodel,
|
|
564
604
|
geometry_plugin: str,
|
|
@@ -631,7 +671,7 @@ def get_ground_direction(
|
|
|
631
671
|
return np.array([lat0, lon0, alt0, lat, lon, alt])
|
|
632
672
|
|
|
633
673
|
|
|
634
|
-
def get_ground_angles(
|
|
674
|
+
def get_ground_angles( # pylint: disable=too-many-positional-arguments
|
|
635
675
|
sensor1,
|
|
636
676
|
sensor2,
|
|
637
677
|
geomodel1,
|
|
@@ -721,3 +761,83 @@ def get_ground_angles(
|
|
|
721
761
|
convergence_angle = np.degrees(utils.angle_vectors(enu1, enu2))
|
|
722
762
|
|
|
723
763
|
return az1, elev_angle1, az2, elev_angle2, convergence_angle
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
def get_output_crs(epsg, out_conf):
|
|
767
|
+
"""
|
|
768
|
+
Détermine le CRS de sortie en fonction de la config.
|
|
769
|
+
"""
|
|
770
|
+
geoid = out_conf.get("geoid")
|
|
771
|
+
crs_epsg = CRS(f"EPSG:{epsg}")
|
|
772
|
+
|
|
773
|
+
if len(crs_epsg.axis_info) != 2:
|
|
774
|
+
return crs_epsg # the user himself set a 3D CRS
|
|
775
|
+
|
|
776
|
+
geoid_is_path = isinstance(geoid, str)
|
|
777
|
+
|
|
778
|
+
if geoid_is_path: # user given geoid
|
|
779
|
+
vepsg = guess_vcrs_from_file_name(geoid)
|
|
780
|
+
if vepsg is None:
|
|
781
|
+
custom_wkt = (
|
|
782
|
+
'VERTCRS["Custom geoid height",'
|
|
783
|
+
+ f' VDATUM["Custom geoid model (file: {geoid})"],'
|
|
784
|
+
+ " CS[vertical,1],"
|
|
785
|
+
+ ' AXIS["gravity-related height (h)", up],'
|
|
786
|
+
+ ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
|
|
787
|
+
"]"
|
|
788
|
+
)
|
|
789
|
+
logging.warning(
|
|
790
|
+
"Could not create a known VCRS from the geoid file."
|
|
791
|
+
)
|
|
792
|
+
return CRS.from_wkt(
|
|
793
|
+
f'COMPOUNDCRS["EPSG:{epsg} + Custom geoid height",'
|
|
794
|
+
f" {crs_epsg.to_wkt()},"
|
|
795
|
+
f" {custom_wkt}]"
|
|
796
|
+
)
|
|
797
|
+
# a vepsg was found using the geoid file
|
|
798
|
+
return CRS(f"EPSG:{epsg}+{vepsg}")
|
|
799
|
+
|
|
800
|
+
if geoid: # geoid == True
|
|
801
|
+
return CRS(f"EPSG:{epsg}+5773")
|
|
802
|
+
|
|
803
|
+
# geoid == False
|
|
804
|
+
wgs84_wkt = (
|
|
805
|
+
'VERTCRS["WGS 84 ellipsoidal height",'
|
|
806
|
+
+ ' VDATUM["WGS 84"],'
|
|
807
|
+
+ " CS[vertical,1],"
|
|
808
|
+
+ ' AXIS["ellipsoidal height (h)", up],'
|
|
809
|
+
+ ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
|
|
810
|
+
"]"
|
|
811
|
+
)
|
|
812
|
+
logging.warning("The output VCRS is WGS84.")
|
|
813
|
+
|
|
814
|
+
return CRS.from_wkt(
|
|
815
|
+
f'COMPOUNDCRS["EPSG:{epsg} + WGS84 ellipsoidal height",'
|
|
816
|
+
f" {crs_epsg.to_wkt()},"
|
|
817
|
+
f" {wgs84_wkt}]"
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
def guess_vcrs_from_file_name(filepath):
|
|
822
|
+
"""
|
|
823
|
+
Tries to detect the geoid's EPSG from the file name
|
|
824
|
+
"""
|
|
825
|
+
filename = os.path.basename(filepath).lower()
|
|
826
|
+
|
|
827
|
+
known_models = {
|
|
828
|
+
"egm96": 5773, # EGM96 height
|
|
829
|
+
"egm_96": 5773, # alias
|
|
830
|
+
"egm 96": 5773, # alias
|
|
831
|
+
"egm1996": 5773, # alias
|
|
832
|
+
"egm08": 3855, # EGM2008 height
|
|
833
|
+
"egm_08": 3855, # alias
|
|
834
|
+
"egm 08": 3855, # alias
|
|
835
|
+
"egm2008": 3855, # alias
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
for key, vepsg in known_models.items():
|
|
839
|
+
if key in filename:
|
|
840
|
+
return vepsg
|
|
841
|
+
|
|
842
|
+
# aucun match connu
|
|
843
|
+
return None
|
cars/core/tiling.py
CHANGED
|
@@ -40,8 +40,10 @@ from scipy.spatial import tsearch # pylint: disable=no-name-in-module
|
|
|
40
40
|
from shapely.geometry import box, mapping
|
|
41
41
|
from shapely.geometry.multipolygon import MultiPolygon
|
|
42
42
|
|
|
43
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
|
|
46
|
+
def grid( # pylint: disable=too-many-positional-arguments
|
|
45
47
|
xmin: float, ymin: float, xmax: float, ymax: float, xsplit: int, ysplit: int
|
|
46
48
|
) -> np.ndarray:
|
|
47
49
|
"""
|
|
@@ -74,6 +76,7 @@ def grid(
|
|
|
74
76
|
return out_grid
|
|
75
77
|
|
|
76
78
|
|
|
79
|
+
@cars_profile(name="Transform four layers to two layers grid", interval=0.5)
|
|
77
80
|
def transform_four_layers_to_two_layers_grid(tiling_grid, terrain=False):
|
|
78
81
|
"""
|
|
79
82
|
Transform a 4 layer grid: (N, M, 4) containing
|
|
@@ -115,6 +118,7 @@ def transform_four_layers_to_two_layers_grid(tiling_grid, terrain=False):
|
|
|
115
118
|
return arr
|
|
116
119
|
|
|
117
120
|
|
|
121
|
+
@cars_profile(name="Transform disp range grid to two layers", interval=0.5)
|
|
118
122
|
def transform_disp_range_grid_to_two_layers(disp_min_grid, disp_max_grid):
|
|
119
123
|
"""
|
|
120
124
|
Transform tiling disp min and max to N+1 M+1 array corresponding
|
|
@@ -154,7 +158,7 @@ def transform_disp_range_grid_to_two_layers(disp_min_grid, disp_max_grid):
|
|
|
154
158
|
return disp_min, disp_max
|
|
155
159
|
|
|
156
160
|
|
|
157
|
-
def generate_tiling_grid(
|
|
161
|
+
def generate_tiling_grid( # pylint: disable=too-many-positional-arguments
|
|
158
162
|
row_min: float,
|
|
159
163
|
col_min: float,
|
|
160
164
|
row_max: float,
|
|
@@ -199,7 +203,9 @@ def generate_tiling_grid(
|
|
|
199
203
|
return out_grid
|
|
200
204
|
|
|
201
205
|
|
|
202
|
-
def split(
|
|
206
|
+
def split(
|
|
207
|
+
xmin, ymin, xmax, ymax, xsplit, ysplit
|
|
208
|
+
): # pylint: disable=too-many-positional-arguments
|
|
203
209
|
"""
|
|
204
210
|
Split a region defined by [xmin, xmax] x [ymin, ymax]
|
|
205
211
|
in splits of xsplit x ysplit size
|
|
@@ -561,6 +567,7 @@ def region_hash_string(region: Tuple):
|
|
|
561
567
|
return "{}_{}_{}_{}".format(region[0], region[1], region[2], region[3])
|
|
562
568
|
|
|
563
569
|
|
|
570
|
+
# pylint: disable=too-many-positional-arguments
|
|
564
571
|
def get_corresponding_tiles_row_col(
|
|
565
572
|
terrain_tiling_grid: np.ndarray,
|
|
566
573
|
row: int,
|
|
@@ -38,6 +38,7 @@ from typing import Dict
|
|
|
38
38
|
# Third party imports
|
|
39
39
|
import numpy as np
|
|
40
40
|
import pandas
|
|
41
|
+
import pyproj
|
|
41
42
|
import rasterio as rio
|
|
42
43
|
import xarray as xr
|
|
43
44
|
from rasterio.profiles import DefaultGTiffProfile
|
|
@@ -338,7 +339,7 @@ class CarsDataset:
|
|
|
338
339
|
|
|
339
340
|
return new_window
|
|
340
341
|
|
|
341
|
-
def create_grid(
|
|
342
|
+
def create_grid( # pylint: disable=too-many-positional-arguments
|
|
342
343
|
self,
|
|
343
344
|
nb_col: int,
|
|
344
345
|
nb_row: int,
|
|
@@ -434,7 +435,7 @@ class CarsDataset:
|
|
|
434
435
|
tiles_row.append(None)
|
|
435
436
|
self.tiles.append(tiles_row)
|
|
436
437
|
|
|
437
|
-
def generate_descriptor(
|
|
438
|
+
def generate_descriptor( # pylint: disable=too-many-positional-arguments
|
|
438
439
|
self, future_result, file_name, tag=None, dtype=None, nodata=None
|
|
439
440
|
):
|
|
440
441
|
"""
|
|
@@ -578,7 +579,7 @@ def run_save_arrays(future_result, file_name, tag=None, descriptor=None):
|
|
|
578
579
|
)
|
|
579
580
|
|
|
580
581
|
|
|
581
|
-
def run_save_points(
|
|
582
|
+
def run_save_points( # pylint: disable=too-many-positional-arguments
|
|
582
583
|
future_result,
|
|
583
584
|
file_name,
|
|
584
585
|
overwrite=False,
|
|
@@ -839,7 +840,7 @@ def save_single_tile_dict(dict_cars, tile_path_name: str):
|
|
|
839
840
|
dict_cars.attrs = saved_dict_cars_attrs
|
|
840
841
|
|
|
841
842
|
|
|
842
|
-
def fill_dataset(
|
|
843
|
+
def fill_dataset( # pylint: disable=too-many-positional-arguments
|
|
843
844
|
dataset,
|
|
844
845
|
saving_info=None,
|
|
845
846
|
window=None,
|
|
@@ -938,7 +939,7 @@ def fill_dict(data_dict, saving_info=None, attributes=None):
|
|
|
938
939
|
data_dict.attrs[SAVING_INFO] = saving_info
|
|
939
940
|
|
|
940
941
|
|
|
941
|
-
def save_all_dataframe(
|
|
942
|
+
def save_all_dataframe( # pylint: disable=too-many-positional-arguments
|
|
942
943
|
dataframe,
|
|
943
944
|
file_name,
|
|
944
945
|
save_by_pair=False,
|
|
@@ -1327,12 +1328,13 @@ def dict_profile_to_rio_profile(dict_profile: Dict) -> Dict:
|
|
|
1327
1328
|
crs = None
|
|
1328
1329
|
if "crs" in dict_profile:
|
|
1329
1330
|
if dict_profile["crs"] is not None:
|
|
1330
|
-
if
|
|
1331
|
-
crs
|
|
1332
|
-
|
|
1333
|
-
|
|
1331
|
+
if (
|
|
1332
|
+
isinstance(dict_profile["crs"], str)
|
|
1333
|
+
and "EPSG:" in dict_profile["crs"]
|
|
1334
|
+
):
|
|
1335
|
+
crs = pyproj.CRS(dict_profile["crs"].replace("EPSG:", ""))
|
|
1334
1336
|
else:
|
|
1335
|
-
crs =
|
|
1337
|
+
crs = pyproj.CRS(dict_profile["crs"])
|
|
1336
1338
|
|
|
1337
1339
|
rio_profile["crs"] = crs
|
|
1338
1340
|
rio_profile["transform"] = transform
|
|
@@ -27,8 +27,6 @@ Contains functions for array reconstructions and crop for multiple tiles
|
|
|
27
27
|
import numpy as np
|
|
28
28
|
import xarray as xr
|
|
29
29
|
|
|
30
|
-
import cars.core.constants as cst
|
|
31
|
-
|
|
32
30
|
|
|
33
31
|
def reconstruct_data(tiles, window, overlap): # noqa: C901
|
|
34
32
|
"""
|
|
@@ -186,104 +184,3 @@ def reconstruct_data(tiles, window, overlap): # noqa: C901
|
|
|
186
184
|
dims=dims,
|
|
187
185
|
).astype(data_type)
|
|
188
186
|
return new_dataset, row_min - ol_row_min, col_min - ol_col_min
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def find_tile_dataset(corresponding_tiles, window):
|
|
192
|
-
"""
|
|
193
|
-
Find the dataset corresponding to window, in the list of tiles.
|
|
194
|
-
|
|
195
|
-
:param corresponding_tiles: list of tiles
|
|
196
|
-
:type corresponding_tiles: list(tuple)
|
|
197
|
-
:param window: window of base tile [row min, row max, col min col max]
|
|
198
|
-
:type window: list
|
|
199
|
-
|
|
200
|
-
:return: dataset corresponding to window
|
|
201
|
-
:rtype: xr.Dataset
|
|
202
|
-
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
dataset = None
|
|
206
|
-
for tile_window, _, tile_dataset in corresponding_tiles:
|
|
207
|
-
if tuple(tile_window) == tuple(window):
|
|
208
|
-
dataset = tile_dataset
|
|
209
|
-
|
|
210
|
-
return dataset
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
def crop_dataset(full_dataset, in_dataset, window, overlap, row_min, col_min):
|
|
214
|
-
"""
|
|
215
|
-
Crop full dataset to fit with a given tile dataset
|
|
216
|
-
|
|
217
|
-
:param full_dataset: Combined dataset
|
|
218
|
-
:type full_dataset: xr.Dataset
|
|
219
|
-
:param in_dataset: dataset to use as template dataset
|
|
220
|
-
:type in_dataset: xr.Dataset
|
|
221
|
-
:param window: window of base tile [row min, row max, col min col max]
|
|
222
|
-
:type window: list
|
|
223
|
-
:param overlap: overlap of base tile [row min, row max, col min col max]
|
|
224
|
-
:type overlap: list
|
|
225
|
-
:param row_min: position of row min in full image
|
|
226
|
-
:type row_min: int
|
|
227
|
-
:param col_min: position of col min in full image
|
|
228
|
-
:type col_min: int
|
|
229
|
-
|
|
230
|
-
:return: cropped dataset
|
|
231
|
-
:rtype: xr.Dataset
|
|
232
|
-
|
|
233
|
-
"""
|
|
234
|
-
cropped = xr.Dataset()
|
|
235
|
-
|
|
236
|
-
coords = {}
|
|
237
|
-
if cst.ROW in in_dataset:
|
|
238
|
-
coords[cst.ROW] = in_dataset.coords[cst.ROW]
|
|
239
|
-
if cst.COL in in_dataset:
|
|
240
|
-
coords[cst.COL] = in_dataset.coords[cst.COL]
|
|
241
|
-
|
|
242
|
-
list_tags = list(full_dataset.keys())
|
|
243
|
-
|
|
244
|
-
for tag in list_tags:
|
|
245
|
-
full_data = full_dataset[tag].values
|
|
246
|
-
|
|
247
|
-
offset_row = int(window[0] - overlap[0] - row_min)
|
|
248
|
-
offset_col = int(window[2] - overlap[2] - col_min)
|
|
249
|
-
|
|
250
|
-
if len(full_data.shape) == 2:
|
|
251
|
-
nb_row = int(in_dataset[tag].values.shape[0])
|
|
252
|
-
nb_col = int(in_dataset[tag].values.shape[1])
|
|
253
|
-
|
|
254
|
-
values = np.ascontiguousarray(
|
|
255
|
-
full_data[
|
|
256
|
-
offset_row : offset_row + nb_row,
|
|
257
|
-
offset_col : offset_col + nb_col,
|
|
258
|
-
]
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
else:
|
|
262
|
-
nb_row = int(in_dataset[tag].values.shape[1])
|
|
263
|
-
nb_col = int(in_dataset[tag].values.shape[2])
|
|
264
|
-
|
|
265
|
-
values = np.ascontiguousarray(
|
|
266
|
-
full_data[
|
|
267
|
-
:,
|
|
268
|
-
offset_row : offset_row + nb_row,
|
|
269
|
-
offset_col : offset_col + nb_col,
|
|
270
|
-
]
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
xarray_coords = {}
|
|
274
|
-
for coord_tag in full_dataset[tag].coords:
|
|
275
|
-
if coord_tag in coords:
|
|
276
|
-
xarray_coords[coord_tag] = coords[coord_tag]
|
|
277
|
-
else:
|
|
278
|
-
xarray_coords[coord_tag] = full_dataset[tag].coords[coord_tag]
|
|
279
|
-
|
|
280
|
-
dims = full_dataset[tag].dims
|
|
281
|
-
|
|
282
|
-
data_array = xr.DataArray(values, coords=xarray_coords, dims=dims)
|
|
283
|
-
if tag in in_dataset:
|
|
284
|
-
data_array.attrs = in_dataset[tag].attrs
|
|
285
|
-
cropped[tag] = data_array
|
|
286
|
-
|
|
287
|
-
cropped.attrs = in_dataset.attrs
|
|
288
|
-
|
|
289
|
-
return cropped
|
|
@@ -30,9 +30,12 @@ import math
|
|
|
30
30
|
import numpy as np
|
|
31
31
|
import xarray as xr
|
|
32
32
|
|
|
33
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
34
|
+
|
|
33
35
|
# CARS imports
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
@cars_profile(name="Grid margins 2 overlaps", interval=0.5)
|
|
36
39
|
def grid_margins_2_overlaps(grid, margins_fun):
|
|
37
40
|
"""
|
|
38
41
|
Convert margins to overlap grid format used in CarsDatasets
|
|
@@ -48,7 +51,7 @@ def grid_margins_2_overlaps(grid, margins_fun):
|
|
|
48
51
|
|
|
49
52
|
"""
|
|
50
53
|
|
|
51
|
-
def fill_overlap(
|
|
54
|
+
def fill_overlap( # pylint: disable=too-many-positional-arguments
|
|
52
55
|
cars_ds_overlaps,
|
|
53
56
|
margins,
|
|
54
57
|
row_up,
|
cars/devibrate.py
CHANGED
|
@@ -95,7 +95,7 @@ def acquisition_direction(
|
|
|
95
95
|
return time_direction_vector, vec1, vec2
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def get_time_ground_direction(
|
|
98
|
+
def get_time_ground_direction( # pylint: disable=too-many-positional-arguments
|
|
99
99
|
sensor,
|
|
100
100
|
geomodel,
|
|
101
101
|
geometry_plugin,
|
|
@@ -180,6 +180,7 @@ def project_coordinates_on_line(
|
|
|
180
180
|
return dist_to_origin * np.cos(proj_angle)
|
|
181
181
|
|
|
182
182
|
|
|
183
|
+
# pylint: disable=too-many-positional-arguments
|
|
183
184
|
def lowres_initial_dem_splines_fit(
|
|
184
185
|
lowres_dsm_from_matches: xr.Dataset,
|
|
185
186
|
lowres_initial_dem: xr.Dataset,
|
|
@@ -379,7 +380,7 @@ def read_lowres_dsm(srtm_path, startx, starty, endx, endy):
|
|
|
379
380
|
return dsm_as_ds, newstartx, newstarty, sizex, sizey, resolution
|
|
380
381
|
|
|
381
382
|
|
|
382
|
-
def compute_splines(
|
|
383
|
+
def compute_splines( # pylint: disable=too-many-positional-arguments
|
|
383
384
|
sensor1,
|
|
384
385
|
geomodel1,
|
|
385
386
|
sensor2,
|
|
@@ -507,7 +508,7 @@ def compute_splines(
|
|
|
507
508
|
}
|
|
508
509
|
|
|
509
510
|
|
|
510
|
-
def cars_devibrate(
|
|
511
|
+
def cars_devibrate( # pylint: disable=too-many-positional-arguments
|
|
511
512
|
used_conf,
|
|
512
513
|
srtm_path,
|
|
513
514
|
geoid_path,
|
|
@@ -594,6 +595,8 @@ def cars_devibrate(
|
|
|
594
595
|
)
|
|
595
596
|
|
|
596
597
|
x_values_2d, y_values_2d = np.meshgrid(x_values_1d, y_values_1d)
|
|
598
|
+
|
|
599
|
+
positions = None
|
|
597
600
|
if src.crs != "EPSG:4326":
|
|
598
601
|
transformer = pyproj.Transformer.from_crs(
|
|
599
602
|
src.crs, "EPSG:4326", always_xy=True
|
cars/extractroi.py
CHANGED
|
@@ -29,6 +29,7 @@ import numpy as np
|
|
|
29
29
|
import rasterio as rio
|
|
30
30
|
from affine import Affine
|
|
31
31
|
from shapely.geometry import box
|
|
32
|
+
from shareloc.geomodels.rpc_writers import write_rio_rpc_as_rpb
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
def is_bbx_in_image(bbx, image_dataset):
|
|
@@ -75,7 +76,7 @@ def get_slices_from_bbx(image_dataset, bbx, rpc_options):
|
|
|
75
76
|
|
|
76
77
|
|
|
77
78
|
def process_image_file(
|
|
78
|
-
bbx, input_image_path, output_image_path,
|
|
79
|
+
bbx, input_image_path, output_image_path, rpb_file_path, rpc_options
|
|
79
80
|
):
|
|
80
81
|
"""
|
|
81
82
|
Processes an image file by extracting a region based on the given geometry.
|
|
@@ -84,7 +85,7 @@ def process_image_file(
|
|
|
84
85
|
region_geometry (dict): GeoJSON-like dictionary defining the region.
|
|
85
86
|
input_image_path (str): Path to the input image file.
|
|
86
87
|
output_image_path (str): Path to save the output image.
|
|
87
|
-
|
|
88
|
+
rpb_file_path (str): Path to save the .RPB file.
|
|
88
89
|
rpc_options (dict): Options for GDALCreateRPCTransformer.
|
|
89
90
|
"""
|
|
90
91
|
|
|
@@ -110,7 +111,8 @@ def process_image_file(
|
|
|
110
111
|
# copy rpc
|
|
111
112
|
dst.rpcs = image_dataset.rpcs
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
if rpb_file_path is not None:
|
|
115
|
+
create_rpb_file(image_dataset, rpb_file_path)
|
|
114
116
|
|
|
115
117
|
|
|
116
118
|
def get_human_readable_bbox(image_dataset, rpc_options):
|
|
@@ -167,34 +169,23 @@ def validate_bounding_box(bbx, image_dataset, rpc_options):
|
|
|
167
169
|
image_dataset, rpc_options
|
|
168
170
|
)
|
|
169
171
|
raise ValueError(
|
|
170
|
-
f"Coordinates must between "
|
|
172
|
+
f"Coordinates must be between "
|
|
171
173
|
f"({min_x}, {min_y}) and ({max_x}, {max_y})"
|
|
172
174
|
)
|
|
173
175
|
|
|
174
176
|
|
|
175
|
-
def
|
|
177
|
+
def create_rpb_file(image_dataset, rpb_filename):
|
|
176
178
|
"""
|
|
177
|
-
Create and save a .
|
|
179
|
+
Create and save a .RPB file from a rasterio dataset
|
|
178
180
|
|
|
179
181
|
Parameters:
|
|
180
182
|
image_dataset (rio.DatasetReader): Opened image dataset.
|
|
181
|
-
|
|
183
|
+
rpb_filename (str): Path to save the .RPB file.
|
|
182
184
|
"""
|
|
183
185
|
if not image_dataset.rpcs:
|
|
184
186
|
raise ValueError("Image dataset has no RPCs")
|
|
185
187
|
rpcs_as_dict = image_dataset.rpcs.to_dict()
|
|
186
|
-
|
|
187
|
-
for key in rpcs_as_dict:
|
|
188
|
-
if isinstance(rpcs_as_dict[key], list):
|
|
189
|
-
for idx, coef in enumerate(rpcs_as_dict[key]):
|
|
190
|
-
writer.write(key + "_%02d" % idx + ": " + str(coef))
|
|
191
|
-
writer.write("\n")
|
|
192
|
-
else:
|
|
193
|
-
writer.write(key + ": " + str(rpcs_as_dict[key]))
|
|
194
|
-
writer.write("\n")
|
|
195
|
-
|
|
196
|
-
writer.write("type: ossimRpcModel\n")
|
|
197
|
-
writer.write("polynomial_format: B\n")
|
|
188
|
+
write_rio_rpc_as_rpb(rpcs_as_dict, rpb_filename)
|
|
198
189
|
|
|
199
190
|
|
|
200
191
|
def main():
|
|
@@ -240,6 +231,12 @@ def main():
|
|
|
240
231
|
help="Digital Elevation Model used for projection",
|
|
241
232
|
)
|
|
242
233
|
|
|
234
|
+
parser.add_argument(
|
|
235
|
+
"--generate_rpb",
|
|
236
|
+
action="store_true",
|
|
237
|
+
help="Generate RPB file",
|
|
238
|
+
)
|
|
239
|
+
|
|
243
240
|
args = parser.parse_args()
|
|
244
241
|
if not os.path.exists(args.out):
|
|
245
242
|
os.makedirs(args.out)
|
|
@@ -254,10 +251,12 @@ def main():
|
|
|
254
251
|
# check first input in list to determine pipeline
|
|
255
252
|
for idx, image_path in enumerate(args.il):
|
|
256
253
|
output_image_path = os.path.join(args.out, "ext_%03d.tif" % idx)
|
|
257
|
-
|
|
254
|
+
rpb_file_path = None
|
|
255
|
+
if args.generate_rpb:
|
|
256
|
+
rpb_file_path = os.path.splitext(output_image_path)[0] + ".RPB"
|
|
258
257
|
|
|
259
258
|
process_image_file(
|
|
260
|
-
args.bbx, image_path, output_image_path,
|
|
259
|
+
args.bbx, image_path, output_image_path, rpb_file_path, rpc_options
|
|
261
260
|
)
|
|
262
261
|
|
|
263
262
|
|
|
@@ -48,8 +48,13 @@ class AbstractCluster(metaclass=ABCMeta):
|
|
|
48
48
|
# cluster mode output directory
|
|
49
49
|
out_dir: str
|
|
50
50
|
|
|
51
|
-
def __new__( # pylint: disable=
|
|
52
|
-
cls,
|
|
51
|
+
def __new__( # pylint: disable=too-many-positional-arguments
|
|
52
|
+
cls,
|
|
53
|
+
conf_cluster,
|
|
54
|
+
out_dir,
|
|
55
|
+
log_dir,
|
|
56
|
+
launch_worker=True,
|
|
57
|
+
data_to_propagate=None,
|
|
53
58
|
):
|
|
54
59
|
"""
|
|
55
60
|
Return the required cluster
|
|
@@ -98,8 +103,13 @@ class AbstractCluster(metaclass=ABCMeta):
|
|
|
98
103
|
|
|
99
104
|
return decorator
|
|
100
105
|
|
|
101
|
-
def __init__(
|
|
102
|
-
self,
|
|
106
|
+
def __init__( # pylint: disable=too-many-positional-arguments
|
|
107
|
+
self,
|
|
108
|
+
conf_cluster,
|
|
109
|
+
out_dir,
|
|
110
|
+
log_dir,
|
|
111
|
+
launch_worker=True,
|
|
112
|
+
data_to_propagate=None,
|
|
103
113
|
): # pylint: disable=W0613
|
|
104
114
|
"""
|
|
105
115
|
Init function of AbstractCluster
|
|
@@ -114,7 +124,7 @@ class AbstractCluster(metaclass=ABCMeta):
|
|
|
114
124
|
# data to propagate
|
|
115
125
|
self.data_to_propagate = data_to_propagate
|
|
116
126
|
|
|
117
|
-
self.worker_log_dir = os.path.join(
|
|
127
|
+
self.worker_log_dir = os.path.join(log_dir, "workers_log")
|
|
118
128
|
if not os.path.exists(self.worker_log_dir):
|
|
119
129
|
os.makedirs(self.worker_log_dir)
|
|
120
130
|
|
|
@@ -56,7 +56,7 @@ class AbstractDaskCluster(
|
|
|
56
56
|
AbstractDaskCluster
|
|
57
57
|
"""
|
|
58
58
|
|
|
59
|
-
def __init__(self, conf_cluster, out_dir, launch_worker=True):
|
|
59
|
+
def __init__(self, conf_cluster, out_dir, log_dir, launch_worker=True):
|
|
60
60
|
"""
|
|
61
61
|
Init function of AbstractDaskCluster
|
|
62
62
|
|
|
@@ -64,8 +64,12 @@ class AbstractDaskCluster(
|
|
|
64
64
|
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
+
print("cluster log_dir", log_dir)
|
|
68
|
+
|
|
67
69
|
# call parent init
|
|
68
|
-
super().__init__(
|
|
70
|
+
super().__init__(
|
|
71
|
+
conf_cluster, out_dir, log_dir, launch_worker=launch_worker
|
|
72
|
+
)
|
|
69
73
|
# retrieve parameters
|
|
70
74
|
self.nb_workers = self.checked_conf_cluster["nb_workers"]
|
|
71
75
|
self.task_timeout = self.checked_conf_cluster["task_timeout"]
|