cars 1.0.0a2__cp312-cp312-win_amd64.whl → 1.0.0a4__cp312-cp312-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.

Files changed (144) hide show
  1. cars/__init__.py +3 -3
  2. cars/applications/__init__.py +0 -3
  3. cars/applications/application.py +14 -6
  4. cars/applications/application_template.py +42 -0
  5. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
  6. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
  7. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
  8. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  9. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  10. cars/applications/dem_generation/dem_generation_algo.py +1 -1
  11. cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
  12. cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
  13. cars/applications/dem_generation/rasterization_app.py +112 -43
  14. cars/applications/dense_match_filling/__init__.py +1 -1
  15. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
  16. cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
  17. cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
  18. cars/applications/dense_match_filling/zero_padding_app.py +10 -5
  19. cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
  20. cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
  21. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.dll.a +0 -0
  22. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.pyd +0 -0
  23. cars/applications/dense_matching/dense_matching_algo.py +48 -14
  24. cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
  25. cars/applications/dense_matching/disparity_grid_algo.py +95 -79
  26. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  27. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  28. cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
  29. cars/applications/dsm_filling/border_interpolation_app.py +11 -12
  30. cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
  31. cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
  32. cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
  33. cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
  34. cars/applications/grid_generation/grid_correction_app.py +4 -1
  35. cars/applications/grid_generation/grid_generation_algo.py +7 -2
  36. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
  37. cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
  38. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
  39. cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
  40. cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
  41. cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
  42. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
  43. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
  44. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
  45. cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
  46. cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
  47. cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
  48. cars/applications/rasterization/rasterization_algo.py +18 -6
  49. cars/applications/rasterization/rasterization_wrappers.py +2 -1
  50. cars/applications/rasterization/simple_gaussian_app.py +88 -116
  51. cars/applications/resampling/abstract_resampling_app.py +1 -1
  52. cars/applications/resampling/bicubic_resampling_app.py +3 -1
  53. cars/applications/resampling/resampling_algo.py +60 -53
  54. cars/applications/resampling/resampling_wrappers.py +3 -1
  55. cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
  56. cars/applications/sparse_matching/sift_app.py +5 -25
  57. cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
  58. cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
  59. cars/applications/triangulation/abstract_triangulation_app.py +1 -1
  60. cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
  61. cars/applications/triangulation/pc_transform.py +552 -0
  62. cars/applications/triangulation/triangulation_algo.py +6 -4
  63. cars/applications/triangulation/triangulation_wrappers.py +1 -0
  64. cars/bundleadjustment.py +6 -6
  65. cars/cars.py +11 -9
  66. cars/core/cars_logging.py +80 -49
  67. cars/core/constants.py +0 -1
  68. cars/core/datasets.py +5 -2
  69. cars/core/geometry/abstract_geometry.py +364 -22
  70. cars/core/geometry/shareloc_geometry.py +112 -82
  71. cars/core/inputs.py +72 -19
  72. cars/core/outputs.py +1 -1
  73. cars/core/preprocessing.py +17 -3
  74. cars/core/projection.py +126 -6
  75. cars/core/tiling.py +10 -3
  76. cars/data_structures/cars_dataset.py +12 -10
  77. cars/data_structures/corresponding_tiles_tools.py +0 -103
  78. cars/data_structures/format_transformation.py +4 -1
  79. cars/devibrate.py +6 -3
  80. cars/extractroi.py +20 -21
  81. cars/orchestrator/cluster/abstract_cluster.py +15 -5
  82. cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
  83. cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
  84. cars/orchestrator/cluster/log_wrapper.py +149 -22
  85. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
  86. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
  87. cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
  88. cars/orchestrator/cluster/sequential_cluster.py +5 -4
  89. cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
  90. cars/orchestrator/orchestrator.py +15 -4
  91. cars/orchestrator/registry/id_generator.py +1 -0
  92. cars/orchestrator/registry/saver_registry.py +2 -2
  93. cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
  94. cars/pipelines/default/default_pipeline.py +461 -1052
  95. cars/pipelines/parameters/advanced_parameters.py +91 -64
  96. cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
  97. cars/pipelines/parameters/application_parameters.py +71 -0
  98. cars/pipelines/parameters/depth_map_inputs.py +0 -314
  99. cars/pipelines/parameters/dsm_inputs.py +40 -4
  100. cars/pipelines/parameters/output_parameters.py +44 -8
  101. cars/pipelines/parameters/sensor_inputs.py +122 -73
  102. cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
  103. cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
  104. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
  105. cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
  106. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
  107. cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
  108. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
  109. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
  110. cars/pipelines/pipeline_template.py +1 -3
  111. cars/pipelines/unit/unit_pipeline.py +676 -1070
  112. cars/starter.py +4 -3
  113. cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
  114. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
  115. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
  116. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  117. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  118. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
  119. cars/applications/dense_match_filling/cpp/__init__.py +0 -0
  120. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp312-win_amd64.dll.a +0 -0
  121. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp312-win_amd64.pyd +0 -0
  122. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
  123. cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
  124. cars/applications/dense_match_filling/cpp/meson.build +0 -9
  125. cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
  126. cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
  127. cars/applications/dense_match_filling/plane_app.py +0 -556
  128. cars/applications/hole_detection/__init__.py +0 -30
  129. cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
  130. cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
  131. cars/applications/hole_detection/hole_detection_algo.py +0 -144
  132. cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
  133. cars/applications/point_cloud_denoising/__init__.py +0 -29
  134. cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
  135. cars/applications/point_cloud_fusion/__init__.py +0 -30
  136. cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
  137. cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
  138. cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
  139. cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
  140. cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
  141. cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
  142. cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
  143. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
  144. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
@@ -1,658 +0,0 @@
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
- """
22
- this module contains the epipolar cloud fusion application class.
23
- """
24
-
25
-
26
- # Standard imports
27
- import logging
28
- import os
29
- from collections import Counter
30
-
31
- # Third party imports
32
- import numpy as np
33
- from json_checker import Checker
34
- from shapely.geometry import Polygon
35
-
36
- import cars.orchestrator.orchestrator as ocht
37
- from cars.applications import application_constants
38
- from cars.applications.point_cloud_fusion import (
39
- cloud_fusion_constants,
40
- pc_fusion_algo,
41
- pc_fusion_wrappers,
42
- )
43
- from cars.applications.point_cloud_fusion.abstract_pc_fusion_app import (
44
- PointCloudFusion,
45
- )
46
- from cars.applications.triangulation.triangulation_wrappers import (
47
- generate_point_cloud_file_names,
48
- )
49
- from cars.core import constants as cst
50
- from cars.core import inputs, projection, tiling
51
- from cars.core.utils import safe_makedirs
52
- from cars.data_structures import cars_dataset
53
-
54
-
55
- class MappingToTerrainTiles(
56
- PointCloudFusion, short_name="mapping_to_terrain_tiles"
57
- ):
58
- """
59
- EpipolarCloudFusion
60
- """
61
-
62
- def __init__(self, conf=None):
63
- """
64
- Init function of EpipolarCloudFusion
65
-
66
- :param conf: configuration for fusion
67
- :return: an application_to_use object
68
- """
69
-
70
- super().__init__(conf=conf)
71
-
72
- # Cloud fusion
73
- self.used_method = self.used_config["method"]
74
-
75
- # Init orchestrator
76
- self.orchestrator = None
77
-
78
- def check_conf(self, conf):
79
- """
80
- Check configuration
81
-
82
- :param conf: configuration to check
83
- :type conf: dict
84
-
85
- :return: overloaded configuration
86
- :rtype: dict
87
-
88
- """
89
-
90
- # init conf
91
- if conf is not None:
92
- overloaded_conf = conf.copy()
93
- else:
94
- conf = {}
95
- overloaded_conf = {}
96
-
97
- # Overload conf
98
- overloaded_conf["method"] = conf.get(
99
- "method", "mapping_to_terrain_tiles"
100
- )
101
-
102
- overloaded_conf["save_by_pair"] = conf.get("save_by_pair", False)
103
-
104
- overloaded_conf[application_constants.SAVE_INTERMEDIATE_DATA] = (
105
- conf.get(application_constants.SAVE_INTERMEDIATE_DATA, False)
106
- )
107
- point_cloud_fusion_schema = {
108
- "method": str,
109
- "save_by_pair": bool,
110
- application_constants.SAVE_INTERMEDIATE_DATA: bool,
111
- }
112
-
113
- # Check conf
114
- checker = Checker(point_cloud_fusion_schema)
115
- checker.validate(overloaded_conf)
116
-
117
- return overloaded_conf
118
-
119
- def run( # noqa: C901
120
- self,
121
- list_epipolar_point_clouds,
122
- bounds,
123
- epsg,
124
- source_pc_names=None,
125
- orchestrator=None,
126
- margins=0,
127
- optimal_terrain_tile_width=500,
128
- roi=None,
129
- save_laz_output=False,
130
- ):
131
- """
132
- Run EpipolarCloudFusion application.
133
-
134
- Creates a CarsDataset corresponding to the merged point clouds,
135
- tiled with the terrain grid used during rasterization.
136
-
137
- :param list_epipolar_point_clouds: list with point clouds\
138
- Each CarsDataset contains:
139
-
140
- - N x M Delayed tiles. \
141
- Each tile will be a future xarray Dataset containing:
142
-
143
- - data : with keys : "x", "y", "z", "corr_msk" \
144
- optional: "texture", "msk",
145
- - attrs with keys: "margins", "epi_full_size", "epsg"
146
- - attributes containing: "disp_lower_bound", "disp_upper_bound" \
147
- "elevation_delta_lower_bound", "elevation_delta_upper_bound"
148
- :type list_epipolar_point_clouds: list(CarsDataset) filled with
149
- xr.Dataset
150
- :param bounds: terrain bounds
151
- :type bounds: list
152
- :param epsg: epsg to use
153
- :type epsg: str
154
- :param source_pc_names: source pc names
155
- :type source_pc_names: list[str]
156
- :param orchestrator: orchestrator used
157
- :type orchestrator: Orchestrator
158
- :param margins: margins needed for tiles, meter or degree
159
- :type margins: float
160
- :param optimal_terrain_tile_width: optimal terrain tile width
161
- :type optimal_terrain_tile_width: int
162
- :param save_laz_output: save output point cloud as laz
163
- :type save_laz_output: bool
164
-
165
-
166
- :return: Merged point clouds
167
-
168
- CarsDataset contains:
169
-
170
- - Z x W Delayed tiles\
171
- Each tile will be a future pandas DataFrame containing:
172
-
173
- - data : with keys : "x", "y", "z", "corr_msk" \
174
- optional: "clr", "msk", "data_valid","coord_epi_geom_i",\
175
- "coord_epi_geom_j","idx_im_epi"
176
- - attrs with keys: "epsg"
177
- - attributes containing: "bounds", "epsg"
178
-
179
- :rtype: CarsDataset filled with pandas.DataFrame
180
-
181
- """
182
-
183
- # Default orchestrator
184
- if orchestrator is None:
185
- # Create default sequential orchestrator for current application
186
- # be awere, no out_json will be shared between orchestrators
187
- # No files saved
188
- self.orchestrator = ocht.Orchestrator(
189
- orchestrator_conf={"mode": "sequential"}
190
- )
191
- else:
192
- self.orchestrator = orchestrator
193
-
194
- save_point_cloud_as_csv = self.used_config.get(
195
- application_constants.SAVE_INTERMEDIATE_DATA, False
196
- )
197
- save_point_cloud_as_laz = (
198
- self.used_config.get(
199
- application_constants.SAVE_INTERMEDIATE_DATA, False
200
- )
201
- or save_laz_output
202
- )
203
- save_by_pair = self.used_config.get("save_by_pair", False)
204
-
205
- if source_pc_names is None:
206
- source_pc_names = ["PAIR_0"]
207
-
208
- # Compute bounds and terrain grid
209
- [xmin, ymin, xmax, ymax] = bounds
210
-
211
- # Split terrain bounding box in pieces
212
- terrain_tiling_grid = tiling.generate_tiling_grid(
213
- xmin,
214
- ymin,
215
- xmax,
216
- ymax,
217
- optimal_terrain_tile_width,
218
- optimal_terrain_tile_width,
219
- )
220
- source_pc_names = []
221
- for point_cloud in list_epipolar_point_clouds:
222
- if "source_pc_name" in point_cloud.attributes:
223
- source_pc_names.append(point_cloud.attributes["source_pc_name"])
224
- # Get dataset type of first item in list_epipolar_point_clouds
225
- pc_dataset_type = list_epipolar_point_clouds[0].dataset_type
226
-
227
- if pc_dataset_type in (
228
- "arrays",
229
- "dict",
230
- "points",
231
- ):
232
- # Create CarsDataset
233
- merged_point_cloud = cars_dataset.CarsDataset(
234
- "points", name="point_cloud_fusion"
235
- )
236
-
237
- # Compute tiling grid
238
- merged_point_cloud.tiling_grid = terrain_tiling_grid
239
-
240
- # update attributes
241
- merged_point_cloud.attributes["bounds"] = bounds
242
- merged_point_cloud.attributes["epsg"] = epsg
243
- merged_point_cloud.attributes["source_pc_names"] = source_pc_names
244
-
245
- number_of_terrain_tiles = (
246
- merged_point_cloud.tiling_grid.shape[1]
247
- * merged_point_cloud.tiling_grid.shape[0]
248
- )
249
-
250
- logging.info(
251
- "Number of tiles in cloud fusion :"
252
- "row : {} "
253
- "col : {}".format(
254
- merged_point_cloud.shape[0],
255
- merged_point_cloud.shape[1],
256
- )
257
- )
258
-
259
- number_of_epipolar_tiles_per_terrain_tiles = []
260
-
261
- if pc_dataset_type in (
262
- "arrays",
263
- "points",
264
- ):
265
- # deal with delayed tiles, with a priori disp min and max
266
-
267
- # Add epipolar_points_min and epipolar_points_max used
268
- # in point_cloud_fusion
269
- # , to get corresponding tiles (terrain)
270
- # TODO change method for corresponding tiles
271
- list_points_min = []
272
- list_points_max = []
273
- for point_cloud in list_epipolar_point_clouds:
274
- points_min, points_max = tiling.terrain_grid_to_epipolar(
275
- terrain_tiling_grid,
276
- point_cloud.tiling_grid,
277
- point_cloud.attributes["epipolar_grid_min"],
278
- point_cloud.attributes["epipolar_grid_max"],
279
- epsg,
280
- )
281
- list_points_min.append(points_min)
282
- list_points_max.append(points_max)
283
-
284
- # Add infos to orchestrator.out_json
285
- updating_dict = {
286
- application_constants.APPLICATION_TAG: {
287
- cloud_fusion_constants.CLOUD_FUSION_RUN_TAG: {
288
- cloud_fusion_constants.EPSG_TAG: epsg,
289
- cloud_fusion_constants.MARGINS_TAG: margins,
290
- cloud_fusion_constants.NUMBER_TERRAIN_TILES: (
291
- number_of_terrain_tiles
292
- ),
293
- cloud_fusion_constants.BOUNDS: bounds,
294
- },
295
- }
296
- }
297
- orchestrator.update_out_info(updating_dict)
298
-
299
- # Generate merged point clouds
300
- logging.info(
301
- "Point clouds: Merged points number: {}".format(
302
- merged_point_cloud.shape[1] * merged_point_cloud.shape[0]
303
- )
304
- )
305
-
306
- # Compute corresponing tiles in parallel if from tif files
307
- color_type = None
308
- if pc_dataset_type == "dict":
309
- corresponding_tiles_cars_ds = (
310
- pc_fusion_algo.get_corresponding_tiles_tif(
311
- terrain_tiling_grid,
312
- list_epipolar_point_clouds,
313
- margins=margins,
314
- orchestrator=self.orchestrator,
315
- )
316
- )
317
- color_file = list_epipolar_point_clouds[0].tiles[0][0]["data"][
318
- "texture"
319
- ]
320
- if color_file is not None:
321
- color_type = inputs.rasterio_get_image_type(color_file)
322
- merged_point_cloud.attributes["color_type"] = color_type
323
-
324
- # Save objects
325
- csv_pc_dir_name = None
326
- if save_point_cloud_as_csv:
327
- # Point cloud file name
328
- csv_pc_dir_name = os.path.join(
329
- self.orchestrator.out_dir,
330
- "dump_dir",
331
- "point_cloud_fusion",
332
- "csv",
333
- )
334
- safe_makedirs(csv_pc_dir_name)
335
- self.orchestrator.add_to_compute_lists(
336
- merged_point_cloud, cars_ds_name="merged_point_cloud_csv"
337
- )
338
-
339
- laz_pc_dir_name = None
340
- if save_point_cloud_as_laz:
341
- # Point cloud file name
342
- if save_laz_output:
343
- laz_pc_dir_name = os.path.join(
344
- self.orchestrator.out_dir, "point_cloud"
345
- )
346
- else:
347
- laz_pc_dir_name = os.path.join(
348
- self.orchestrator.out_dir,
349
- "dump_dir",
350
- "point_cloud_fusion",
351
- "laz",
352
- )
353
- safe_makedirs(laz_pc_dir_name)
354
- self.orchestrator.add_to_compute_lists(
355
- merged_point_cloud, cars_ds_name="merged_point_cloud"
356
- )
357
-
358
- # Get saving infos in order to save tiles when they are computed
359
- [saving_info] = self.orchestrator.get_saving_infos(
360
- [merged_point_cloud]
361
- )
362
- pc_index = {}
363
- for col in range(merged_point_cloud.shape[1]):
364
- for row in range(merged_point_cloud.shape[0]):
365
- # update saving infos for potential replacement
366
- full_saving_info = ocht.update_saving_infos(
367
- saving_info, row=row, col=col
368
- )
369
- if pc_dataset_type in (
370
- "arrays",
371
- "points",
372
- ):
373
- # Get required point clouds
374
- (
375
- terrain_region,
376
- required_point_clouds,
377
- _rank,
378
- _pos,
379
- ) = tiling.get_corresponding_tiles_row_col(
380
- terrain_tiling_grid,
381
- row,
382
- col,
383
- list_epipolar_point_clouds,
384
- list_points_min,
385
- list_points_max,
386
- )
387
- else:
388
- # Get correspondances previously computed
389
- terrain_region = corresponding_tiles_cars_ds[row, col][
390
- "terrain_region"
391
- ]
392
- required_point_clouds = corresponding_tiles_cars_ds[
393
- row, col
394
- ]["required_point_clouds"]
395
-
396
- terrain_region_poly = Polygon(
397
- [
398
- [terrain_region[0], terrain_region[1]],
399
- [terrain_region[0], terrain_region[3]],
400
- [terrain_region[2], terrain_region[3]],
401
- [terrain_region[2], terrain_region[1]],
402
- [terrain_region[0], terrain_region[1]],
403
- ]
404
- )
405
- if len(
406
- [
407
- value
408
- for value, _ in required_point_clouds
409
- if not isinstance(value, type(None))
410
- ]
411
- ) > 0 and (
412
- roi is None or terrain_region_poly.intersects(roi)
413
- ):
414
- logging.debug(
415
- "Number of clouds to process for this terrain"
416
- " tile: {}".format(len(required_point_clouds))
417
- )
418
- number_of_epipolar_tiles_per_terrain_tiles.append(
419
- len(required_point_clouds)
420
- )
421
-
422
- csv_pc_file_name, laz_pc_file_name = (
423
- generate_point_cloud_file_names(
424
- csv_pc_dir_name,
425
- laz_pc_dir_name,
426
- row,
427
- col,
428
- pc_index,
429
- pair_key=(
430
- source_pc_names if save_by_pair else None
431
- ),
432
- )
433
- )
434
-
435
- # Delayed call to rasterization operations using all
436
- # required point clouds
437
- merged_point_cloud[
438
- row, col
439
- ] = self.orchestrator.cluster.create_task(
440
- compute_point_cloud_wrapper
441
- )(
442
- required_point_clouds,
443
- epsg,
444
- xmin=terrain_region[0],
445
- ymin=terrain_region[1],
446
- xmax=terrain_region[2],
447
- ymax=terrain_region[3],
448
- margins=margins,
449
- save_by_pair=save_by_pair,
450
- point_cloud_csv_file_name=csv_pc_file_name,
451
- point_cloud_laz_file_name=laz_pc_file_name,
452
- saving_info=full_saving_info,
453
- source_pc_names=source_pc_names,
454
- )
455
-
456
- # update point cloud index
457
- if save_laz_output:
458
- self.orchestrator.update_index(pc_index)
459
-
460
- # Sort tiles according to rank TODO remove or implement it ?
461
-
462
- # Raise an error if no tiles has been found
463
- if len(number_of_epipolar_tiles_per_terrain_tiles) < 1:
464
- raise RuntimeError(
465
- "No epipolar tiles has been found inside the ROI! "
466
- "Please try with an other ROI."
467
- )
468
-
469
- # Add delayed_dsm_tiles to orchestrator
470
- logging.info(
471
- "Submitting {} tasks to dask".format(number_of_terrain_tiles)
472
- )
473
-
474
- logging.info(
475
- "Number of epipolar tiles "
476
- "for each terrain tile (counter): {}".format(
477
- sorted(
478
- Counter(
479
- number_of_epipolar_tiles_per_terrain_tiles
480
- ).items()
481
- )
482
- )
483
- )
484
-
485
- logging.info(
486
- "Average number of epipolar tiles "
487
- "for each terrain tile: {}".format(
488
- int(
489
- np.round(
490
- np.mean(number_of_epipolar_tiles_per_terrain_tiles)
491
- )
492
- )
493
- )
494
- )
495
-
496
- logging.info(
497
- "Max number of epipolar tiles "
498
- "for each terrain tile: {}".format(
499
- np.max(number_of_epipolar_tiles_per_terrain_tiles)
500
- )
501
- )
502
-
503
- else:
504
- logging.error(
505
- "PointCloudRasterisation application doesn't "
506
- "support this input data format"
507
- )
508
-
509
- return merged_point_cloud
510
-
511
-
512
- def compute_point_cloud_wrapper(
513
- point_clouds,
514
- epsg,
515
- xmin: float = None,
516
- ymin: float = None,
517
- xmax: float = None,
518
- ymax: float = None,
519
- margins: float = 0,
520
- save_by_pair: bool = False,
521
- point_cloud_csv_file_name=None,
522
- point_cloud_laz_file_name=None,
523
- saving_info=None,
524
- source_pc_names=None,
525
- ):
526
- """
527
- Wrapper for point clouds fusion step :
528
- - Convert a list of clouds to correct epsg
529
-
530
- :param point_clouds: list of clouds, list of (dataset, dataset_id) with :
531
- - cst.X
532
- - cst.Y
533
- - cst.Z
534
- - cst.EPI_TEXTURE
535
- :type point_clouds: list((xr.Dataset, int))
536
- :param epsg_code: epsg code for the CRS of the output DSM
537
- :type epsg_code: int
538
- :param stereo_out_epsg: epsg code to convert point cloud to, if needed
539
- :type stereo_out_epsg: int
540
- :param xmin: xmin of the rasterization grid
541
- (if None, will be estimated by the function)
542
- :param xmin: xmin of the rasterization grid
543
- (if None, will be estimated by the function)
544
- :param xmax: xmax of the rasterization grid
545
- (if None, will be estimated by the function)
546
- :param ymax: ymax of the rasterization grid
547
- (if None, will be estimated by the function)
548
- :param margins: margins needed for tiles, meter or degree
549
- :type margins: float
550
- :param save_by_pair: save point cloud as pair
551
- :type save_by_pair: bool
552
- :param point_cloud_csv_file_name: write point cloud as CSV in filename
553
- (if None, the point cloud is not written as csv)
554
- :type point_cloud_csv_file_name: str
555
- :param point_cloud_laz_file_name: write point cloud as laz in filename
556
- (if None, the point cloud is not written as laz)
557
- :type point_cloud_laz_file_name: str
558
- :param saving_info: informations about CarsDataset ID.
559
- :type saving_info: dict
560
- :param source_pc_names: source point cloud name (correspond to pair_key)
561
- :type source_pc_names: list str
562
-
563
- :return: merged point cloud dataframe with:
564
- - cst.X
565
- - cst.Y
566
- - cst.Z
567
- - cst.EPI_TEXTURE
568
- - attrs : xmin, xmax, ymin, ymax, saving_info
569
- :rtype: pandas.DataFrame
570
- """
571
- # Remove None tiles
572
- clouds = []
573
- clouds_ids = []
574
- disparity_range_is_cropped = False
575
- for value, pc_id in point_clouds:
576
- if value is not None:
577
- clouds.append(value)
578
- clouds_ids.append(pc_id)
579
- # Check if disparity range was cropped during process
580
- if ocht.get_disparity_range_cropped(value):
581
- disparity_range_is_cropped = True
582
- if len(clouds) == 0:
583
- raise RuntimeError("All clouds are None")
584
-
585
- # combine clouds
586
- if not isinstance(clouds[0], dict):
587
- pc_pandas, cloud_epsg = pc_fusion_algo.create_combined_cloud(
588
- clouds,
589
- clouds_ids,
590
- epsg,
591
- xmin=xmin,
592
- xmax=xmax,
593
- ymin=ymin,
594
- ymax=ymax,
595
- margin=margins,
596
- with_coords=True,
597
- )
598
- # get color type list
599
- color_type = pc_fusion_wrappers.get_color_type(clouds)
600
- else:
601
- # combined pc from tif files
602
- (
603
- pc_pandas,
604
- cloud_epsg,
605
- color_type,
606
- ) = pc_fusion_algo.create_combined_cloud_from_tif(
607
- clouds,
608
- clouds_ids,
609
- epsg,
610
- xmin=xmin,
611
- xmax=xmax,
612
- ymin=ymin,
613
- ymax=ymax,
614
- margin=margins,
615
- )
616
-
617
- # Conversion to UTM
618
- if cloud_epsg != epsg:
619
- projection.point_cloud_conversion_dataframe(pc_pandas, cloud_epsg, epsg)
620
- cloud_epsg = epsg
621
-
622
- # Fill attributes for rasterization
623
- attributes = {
624
- "epsg": cloud_epsg,
625
- "xmin": xmin,
626
- "xmax": xmax,
627
- "ymin": ymin,
628
- "ymax": ymax,
629
- "color_type": color_type,
630
- "source_pc_names": source_pc_names,
631
- "number_of_pc": len(source_pc_names),
632
- cst.CROPPED_DISPARITY_RANGE: disparity_range_is_cropped,
633
- }
634
- cars_dataset.fill_dataframe(
635
- pc_pandas, saving_info=saving_info, attributes=attributes
636
- )
637
-
638
- # save point cloud in worker
639
- if point_cloud_csv_file_name:
640
- cars_dataset.run_save_points(
641
- pc_pandas,
642
- point_cloud_csv_file_name,
643
- save_by_pair=save_by_pair,
644
- overwrite=True,
645
- point_cloud_format="csv",
646
- overwrite_file_name=False,
647
- )
648
- if point_cloud_laz_file_name:
649
- cars_dataset.run_save_points(
650
- pc_pandas,
651
- point_cloud_laz_file_name,
652
- save_by_pair=save_by_pair,
653
- overwrite=True,
654
- point_cloud_format="laz",
655
- overwrite_file_name=False,
656
- )
657
-
658
- return pc_pandas