cars 1.0.0rc1__cp313-cp313-musllinux_1_2_i686.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 (202) hide show
  1. cars/__init__.py +74 -0
  2. cars/applications/__init__.py +37 -0
  3. cars/applications/application.py +117 -0
  4. cars/applications/application_constants.py +29 -0
  5. cars/applications/application_template.py +146 -0
  6. cars/applications/auxiliary_filling/__init__.py +29 -0
  7. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +104 -0
  8. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
  9. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -0
  10. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
  11. cars/applications/dem_generation/__init__.py +30 -0
  12. cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
  13. cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
  14. cars/applications/dem_generation/bulldozer_dem_app.py +655 -0
  15. cars/applications/dem_generation/bulldozer_memory.py +55 -0
  16. cars/applications/dem_generation/dem_generation_algo.py +107 -0
  17. cars/applications/dem_generation/dem_generation_constants.py +32 -0
  18. cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
  19. cars/applications/dense_match_filling/__init__.py +30 -0
  20. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
  21. cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
  22. cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
  23. cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
  24. cars/applications/dense_match_filling/zero_padding_app.py +302 -0
  25. cars/applications/dense_matching/__init__.py +30 -0
  26. cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
  27. cars/applications/dense_matching/census_mccnn_sgm_app.py +1460 -0
  28. cars/applications/dense_matching/cpp/__init__.py +0 -0
  29. cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-313-i386-linux-musl.so +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  31. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  32. cars/applications/dense_matching/cpp/meson.build +9 -0
  33. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  34. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  35. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  36. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  37. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  38. cars/applications/dense_matching/disparity_grid_algo.py +588 -0
  39. cars/applications/dense_matching/loaders/__init__.py +23 -0
  40. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  46. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  47. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  48. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  49. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  50. cars/applications/dsm_filling/__init__.py +32 -0
  51. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  52. cars/applications/dsm_filling/border_interpolation_app.py +270 -0
  53. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  54. cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
  55. cars/applications/dsm_filling/exogenous_filling_app.py +333 -0
  56. cars/applications/grid_generation/__init__.py +30 -0
  57. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  58. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  59. cars/applications/grid_generation/grid_correction_app.py +496 -0
  60. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  61. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  62. cars/applications/grid_generation/transform_grid.py +88 -0
  63. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  64. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  65. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  66. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  67. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  68. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  69. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  70. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  71. cars/applications/point_cloud_outlier_removal/small_components_app.py +527 -0
  72. cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -0
  73. cars/applications/rasterization/__init__.py +30 -0
  74. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  75. cars/applications/rasterization/rasterization_algo.py +534 -0
  76. cars/applications/rasterization/rasterization_constants.py +38 -0
  77. cars/applications/rasterization/rasterization_wrappers.py +634 -0
  78. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  79. cars/applications/resampling/__init__.py +28 -0
  80. cars/applications/resampling/abstract_resampling_app.py +187 -0
  81. cars/applications/resampling/bicubic_resampling_app.py +762 -0
  82. cars/applications/resampling/resampling_algo.py +614 -0
  83. cars/applications/resampling/resampling_constants.py +36 -0
  84. cars/applications/resampling/resampling_wrappers.py +309 -0
  85. cars/applications/sparse_matching/__init__.py +30 -0
  86. cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
  87. cars/applications/sparse_matching/sift_app.py +735 -0
  88. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  89. cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
  90. cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
  91. cars/applications/triangulation/__init__.py +32 -0
  92. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  93. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  94. cars/applications/triangulation/pc_transform.py +552 -0
  95. cars/applications/triangulation/triangulation_algo.py +371 -0
  96. cars/applications/triangulation/triangulation_constants.py +38 -0
  97. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  98. cars/bundleadjustment.py +757 -0
  99. cars/cars.py +177 -0
  100. cars/conf/__init__.py +23 -0
  101. cars/conf/geoid/egm96.grd +0 -0
  102. cars/conf/geoid/egm96.grd.hdr +15 -0
  103. cars/conf/input_parameters.py +156 -0
  104. cars/conf/mask_cst.py +35 -0
  105. cars/core/__init__.py +23 -0
  106. cars/core/cars_logging.py +402 -0
  107. cars/core/constants.py +191 -0
  108. cars/core/constants_disparity.py +50 -0
  109. cars/core/datasets.py +140 -0
  110. cars/core/geometry/__init__.py +27 -0
  111. cars/core/geometry/abstract_geometry.py +1119 -0
  112. cars/core/geometry/shareloc_geometry.py +598 -0
  113. cars/core/inputs.py +568 -0
  114. cars/core/outputs.py +176 -0
  115. cars/core/preprocessing.py +722 -0
  116. cars/core/projection.py +843 -0
  117. cars/core/roi_tools.py +215 -0
  118. cars/core/tiling.py +774 -0
  119. cars/core/utils.py +164 -0
  120. cars/data_structures/__init__.py +23 -0
  121. cars/data_structures/cars_dataset.py +1541 -0
  122. cars/data_structures/cars_dict.py +74 -0
  123. cars/data_structures/corresponding_tiles_tools.py +186 -0
  124. cars/data_structures/dataframe_converter.py +185 -0
  125. cars/data_structures/format_transformation.py +297 -0
  126. cars/devibrate.py +689 -0
  127. cars/extractroi.py +264 -0
  128. cars/orchestrator/__init__.py +23 -0
  129. cars/orchestrator/achievement_tracker.py +125 -0
  130. cars/orchestrator/cluster/__init__.py +37 -0
  131. cars/orchestrator/cluster/abstract_cluster.py +244 -0
  132. cars/orchestrator/cluster/abstract_dask_cluster.py +375 -0
  133. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  134. cars/orchestrator/cluster/dask_config/README.md +94 -0
  135. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  136. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  137. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  138. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  139. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  140. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  141. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  142. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  143. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  144. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  145. cars/orchestrator/cluster/log_wrapper.py +1075 -0
  146. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  147. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  148. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  149. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  150. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  151. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +873 -0
  152. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  153. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  154. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  155. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  156. cars/orchestrator/orchestrator.py +905 -0
  157. cars/orchestrator/orchestrator_constants.py +29 -0
  158. cars/orchestrator/registry/__init__.py +23 -0
  159. cars/orchestrator/registry/abstract_registry.py +143 -0
  160. cars/orchestrator/registry/compute_registry.py +106 -0
  161. cars/orchestrator/registry/id_generator.py +116 -0
  162. cars/orchestrator/registry/replacer_registry.py +213 -0
  163. cars/orchestrator/registry/saver_registry.py +363 -0
  164. cars/orchestrator/registry/unseen_registry.py +118 -0
  165. cars/orchestrator/tiles_profiler.py +279 -0
  166. cars/pipelines/__init__.py +26 -0
  167. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  168. cars/pipelines/conf_resolution/conf_first_resolution.yaml +2 -0
  169. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  170. cars/pipelines/default/__init__.py +26 -0
  171. cars/pipelines/default/default_pipeline.py +786 -0
  172. cars/pipelines/parameters/__init__.py +0 -0
  173. cars/pipelines/parameters/advanced_parameters.py +417 -0
  174. cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
  175. cars/pipelines/parameters/application_parameters.py +71 -0
  176. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  177. cars/pipelines/parameters/dsm_inputs.py +918 -0
  178. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  179. cars/pipelines/parameters/output_constants.py +52 -0
  180. cars/pipelines/parameters/output_parameters.py +454 -0
  181. cars/pipelines/parameters/sensor_inputs.py +842 -0
  182. cars/pipelines/parameters/sensor_inputs_constants.py +49 -0
  183. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  184. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  185. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  186. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  187. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  188. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  189. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  190. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  191. cars/pipelines/pipeline.py +119 -0
  192. cars/pipelines/pipeline_constants.py +31 -0
  193. cars/pipelines/pipeline_template.py +139 -0
  194. cars/pipelines/unit/__init__.py +26 -0
  195. cars/pipelines/unit/unit_pipeline.py +2850 -0
  196. cars/starter.py +167 -0
  197. cars-1.0.0rc1.dist-info/METADATA +292 -0
  198. cars-1.0.0rc1.dist-info/RECORD +202 -0
  199. cars-1.0.0rc1.dist-info/WHEEL +5 -0
  200. cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
  201. cars.libs/libgcc_s-1257a076.so.1 +0 -0
  202. cars.libs/libstdc++-0530927c.so.6.0.32 +0 -0
@@ -0,0 +1,527 @@
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 small_components point removal application class.
23
+ """
24
+
25
+
26
+ import copy
27
+
28
+ # Standard imports
29
+ import logging
30
+ import os
31
+
32
+ # Third party imports
33
+ import numpy as np
34
+ from json_checker import And, Checker, Or
35
+ from pyproj import CRS
36
+
37
+ # CARS imports
38
+ import cars.orchestrator.orchestrator as ocht
39
+ from cars.applications import application_constants
40
+ from cars.applications.point_cloud_outlier_removal import (
41
+ abstract_outlier_removal_app as pc_removal,
42
+ )
43
+ from cars.applications.point_cloud_outlier_removal import (
44
+ outlier_removal_algo,
45
+ )
46
+ from cars.applications.triangulation import pc_transform
47
+ from cars.applications.triangulation.triangulation_wrappers import (
48
+ generate_point_cloud_file_names,
49
+ )
50
+ from cars.core import constants as cst
51
+ from cars.core import projection
52
+ from cars.data_structures import cars_dataset
53
+
54
+
55
+ class SmallComponents(
56
+ pc_removal.PointCloudOutlierRemoval, short_name="small_components"
57
+ ): # pylint: disable=R0903
58
+ """
59
+ SmallComponents
60
+ """
61
+
62
+ # pylint: disable=too-many-instance-attributes
63
+
64
+ def __init__(self, scaling_coeff, conf=None):
65
+ """
66
+ Init function of SmallComponents
67
+
68
+ :param scaling_coeff: scaling factor for resolution
69
+ :type scaling_coeff: float
70
+ :param conf: configuration for points outlier removal
71
+ :return: an application_to_use object
72
+ """
73
+
74
+ super().__init__(scaling_coeff, conf=conf)
75
+
76
+ self.used_method = self.used_config["method"]
77
+
78
+ # small components
79
+ self.on_ground_margin = self.used_config["on_ground_margin"]
80
+ self.connection_distance = self.used_config["connection_distance"]
81
+ self.nb_points_threshold = self.used_config["nb_points_threshold"]
82
+ self.clusters_distance_threshold = self.used_config[
83
+ "clusters_distance_threshold"
84
+ ]
85
+ self.half_epipolar_size = self.used_config["half_epipolar_size"]
86
+
87
+ # Saving files
88
+ self.save_by_pair = self.used_config.get("save_by_pair", False)
89
+
90
+ # Init orchestrator
91
+ self.orchestrator = None
92
+
93
+ def check_conf(self, conf):
94
+ """
95
+ Check configuration
96
+
97
+ :param conf: configuration to check
98
+ :type conf: dict
99
+
100
+ :return: overloaded configuration
101
+ :rtype: dict
102
+
103
+ """
104
+
105
+ # init conf
106
+ if conf is not None:
107
+ overloaded_conf = conf.copy()
108
+ else:
109
+ conf = {}
110
+ overloaded_conf = {}
111
+
112
+ # Overload conf
113
+ overloaded_conf["method"] = conf.get("method", "small_components")
114
+ overloaded_conf[application_constants.SAVE_INTERMEDIATE_DATA] = (
115
+ conf.get(application_constants.SAVE_INTERMEDIATE_DATA, False)
116
+ )
117
+ overloaded_conf["save_by_pair"] = conf.get("save_by_pair", False)
118
+
119
+ # small components
120
+ # on_ground_margin:
121
+ # margin added to the on ground region to not filter
122
+ # points clusters
123
+ # that were incomplete because they were on the edges
124
+ overloaded_conf["on_ground_margin"] = conf.get("on_ground_margin", 11)
125
+ # pts_connection_dist:
126
+ # distance to use to consider that two points are connected
127
+ overloaded_conf["connection_distance"] = conf.get(
128
+ "connection_distance", self.scaling_coeff * 3.0
129
+ )
130
+ # nb_pts_threshold:
131
+ # points clusters that have less than this number of points
132
+ # will be filtered
133
+ overloaded_conf["nb_points_threshold"] = conf.get(
134
+ "nb_points_threshold", 50
135
+ )
136
+ # dist_between_clusters:
137
+ # distance to use to consider that two points clusters
138
+ # are far from each other or not.
139
+ # If a small points cluster is near to another one, it won't
140
+ # be filtered.
141
+ # (None = deactivated)
142
+ overloaded_conf["clusters_distance_threshold"] = conf.get(
143
+ "clusters_distance_threshold", None
144
+ )
145
+
146
+ # half_epipolar_size:
147
+ # Half size of the epipolar window used for neighobr search (depth map
148
+ # input only)
149
+ overloaded_conf["half_epipolar_size"] = conf.get(
150
+ "half_epipolar_size", 5
151
+ )
152
+
153
+ point_cloud_fusion_schema = {
154
+ "method": str,
155
+ "save_by_pair": bool,
156
+ "on_ground_margin": int,
157
+ "connection_distance": And(float, lambda x: x > 0),
158
+ "nb_points_threshold": And(int, lambda x: x > 0),
159
+ "clusters_distance_threshold": Or(None, float),
160
+ "half_epipolar_size": int,
161
+ application_constants.SAVE_INTERMEDIATE_DATA: bool,
162
+ }
163
+
164
+ # Check conf
165
+ checker = Checker(point_cloud_fusion_schema)
166
+ checker.validate(overloaded_conf)
167
+
168
+ return overloaded_conf
169
+
170
+ def get_optimal_tile_size(
171
+ self,
172
+ max_ram_per_worker,
173
+ superposing_point_clouds=1,
174
+ point_cloud_resolution=0.5,
175
+ ):
176
+ """
177
+ Get the optimal tile size to use, depending on memory available
178
+
179
+ :param max_ram_per_worker: maximum ram available
180
+ :type max_ram_per_worker: int
181
+ :param superposing_point_clouds: number of point clouds superposing
182
+ :type superposing_point_clouds: int
183
+ :param point_cloud_resolution: resolution of point cloud
184
+ :type point_cloud_resolution: float
185
+
186
+ :return: optimal tile size in meter
187
+ :rtype: float
188
+
189
+ """
190
+ tot = 10000 * superposing_point_clouds / point_cloud_resolution
191
+
192
+ import_ = 200 # MiB
193
+ tile_size = int(
194
+ np.sqrt(float(((max_ram_per_worker - import_) * 2**23)) / tot)
195
+ )
196
+
197
+ logging.info(
198
+ "Estimated optimal tile size for small"
199
+ "component removal: {} meters".format(tile_size)
200
+ )
201
+
202
+ return tile_size
203
+
204
+ def get_method(self):
205
+ """
206
+ Get margins to use during point clouds fusion
207
+
208
+ :return: algorithm method
209
+ :rtype: string
210
+
211
+ """
212
+
213
+ return self.used_method
214
+
215
+ def get_epipolar_margin(self):
216
+ """
217
+ Get epipolar margin to use
218
+
219
+ :return: margin
220
+ :rtype: int
221
+ """
222
+ margin = self.half_epipolar_size
223
+
224
+ return margin
225
+
226
+ def get_on_ground_margin(self, resolution=0.5):
227
+ """
228
+ Get margins to use during point clouds fusion
229
+
230
+ :return: margin
231
+ :rtype: float
232
+
233
+ """
234
+ on_ground_margin = self.on_ground_margin * resolution
235
+
236
+ return on_ground_margin
237
+
238
+ def run( # pylint: disable=too-many-positional-arguments
239
+ self,
240
+ merged_point_cloud,
241
+ orchestrator=None,
242
+ depth_map_dir=None,
243
+ point_cloud_dir=None,
244
+ dump_dir=None,
245
+ epsg=None,
246
+ ):
247
+ """
248
+ Run PointCloudOutlierRemoval application.
249
+
250
+ Creates a CarsDataset filled with new point cloud tiles.
251
+
252
+ :param merged_point_cloud: merged point cloud. CarsDataset contains:
253
+
254
+ - Z x W Delayed tiles. \
255
+ Each tile will be a future pandas DataFrame containing:
256
+
257
+ - data : with keys : "x", "y", "z", "corr_msk"\
258
+ optional: "clr", "msk", "data_valid","coord_epi_geom_i",\
259
+ "coord_epi_geom_j","idx_im_epi" \
260
+ - attrs with keys: "epsg"
261
+ - attributes containing "bounds", "ysize", "xsize", "epsg"
262
+
263
+ :type merged_point_cloud: CarsDataset filled with pandas.DataFrame
264
+ :param orchestrator: orchestrator used
265
+ :param depth_map_dir: output depth map directory. If None output will
266
+ be written in dump_dir if intermediate data is requested
267
+ :type depth_map_dir: str
268
+ :param point_cloud_dir: output depth map directory. If None output will
269
+ be written in dump_dir if intermediate data is requested
270
+ :type point_cloud_dir: str
271
+ :type output_dir: str
272
+ :param dump_dir: dump dir for output (except depth map) if intermediate
273
+ data is requested
274
+ :type dump_dir: str
275
+ :param epsg: cartographic reference for the point cloud (array input)
276
+ :type epsg: int
277
+
278
+
279
+ :return: filtered merged point cloud. CarsDataset contains:
280
+
281
+ - Z x W Delayed tiles.\
282
+ Each tile will be a future pandas DataFrame containing:
283
+
284
+ - data : with keys : "x", "y", "z", "corr_msk"\
285
+ optional: "clr", "msk", "data_valid","coord_epi_geom_i",\
286
+ "coord_epi_geom_j","idx_im_epi"
287
+ - attrs with keys: "epsg"
288
+ - attributes containing "bounds", "ysize", "xsize", "epsg"
289
+
290
+ :rtype: CarsDataset filled with xr.Dataset
291
+ """
292
+ # Default orchestrator
293
+ if orchestrator is None:
294
+ # Create default sequential orchestrator for current application
295
+ # be awere, no out_json will be shared between orchestrators
296
+ # No files saved
297
+ self.orchestrator = ocht.Orchestrator(
298
+ orchestrator_conf={"mode": "sequential"}
299
+ )
300
+ else:
301
+ self.orchestrator = orchestrator
302
+
303
+ if dump_dir is None:
304
+ dump_dir = self.generate_unknown_dump_dir(self.orchestrator)
305
+
306
+ if merged_point_cloud.dataset_type != "arrays":
307
+ raise RuntimeError(
308
+ "Only arrays is supported in small components removal"
309
+ )
310
+ prefix = os.path.basename(dump_dir)
311
+ # Save as depth map
312
+ filtered_point_cloud, saving_info_epipolar = (
313
+ self.__register_epipolar_dataset__(
314
+ merged_point_cloud,
315
+ depth_map_dir,
316
+ dump_dir,
317
+ app_name="small_components",
318
+ pair_key=prefix,
319
+ )
320
+ )
321
+
322
+ # Save as point cloud
323
+ (
324
+ flatten_filtered_point_cloud,
325
+ laz_pc_dir_name,
326
+ csv_pc_dir_name,
327
+ saving_info_flatten,
328
+ ) = self.__register_pc_dataset__(
329
+ merged_point_cloud,
330
+ point_cloud_dir,
331
+ dump_dir,
332
+ app_name="small_components",
333
+ )
334
+
335
+ # initialize empty index file for point cloud product if official
336
+ # product is requested
337
+ pc_index = None
338
+ if point_cloud_dir:
339
+ pc_index = {}
340
+
341
+ # Generate rasters
342
+ for col in range(filtered_point_cloud.shape[1]):
343
+ for row in range(filtered_point_cloud.shape[0]):
344
+
345
+ # update saving infos for potential replacement
346
+ full_saving_info_epipolar = ocht.update_saving_infos(
347
+ saving_info_epipolar, row=row, col=col
348
+ )
349
+ full_saving_info_flatten = None
350
+ if saving_info_flatten is not None:
351
+ full_saving_info_flatten = ocht.update_saving_infos(
352
+ saving_info_flatten, row=row, col=col
353
+ )
354
+ if merged_point_cloud[row][col] is not None:
355
+ csv_pc_file_name, laz_pc_file_name = (
356
+ generate_point_cloud_file_names(
357
+ csv_pc_dir_name,
358
+ laz_pc_dir_name,
359
+ row,
360
+ col,
361
+ pc_index,
362
+ pair_key=prefix,
363
+ )
364
+ )
365
+ window = merged_point_cloud.tiling_grid[row, col]
366
+ overlap = filtered_point_cloud.overlaps[row, col]
367
+ # Delayed call to cloud filtering
368
+ (
369
+ filtered_point_cloud[row, col],
370
+ flatten_filtered_point_cloud[row, col],
371
+ ) = self.orchestrator.cluster.create_task(
372
+ epipolar_small_component_removal_wrapper, nout=2
373
+ )(
374
+ merged_point_cloud[row, col],
375
+ self.connection_distance,
376
+ self.nb_points_threshold,
377
+ self.clusters_distance_threshold,
378
+ self.half_epipolar_size,
379
+ window,
380
+ overlap,
381
+ epsg=epsg,
382
+ point_cloud_csv_file_name=csv_pc_file_name,
383
+ point_cloud_laz_file_name=laz_pc_file_name,
384
+ saving_info_epipolar=full_saving_info_epipolar,
385
+ saving_info_flatten=full_saving_info_flatten,
386
+ )
387
+
388
+ # update point cloud index
389
+ if point_cloud_dir:
390
+ self.orchestrator.update_index(pc_index)
391
+
392
+ return filtered_point_cloud
393
+
394
+
395
+ # pylint: disable=too-many-positional-arguments
396
+ def epipolar_small_component_removal_wrapper(
397
+ cloud,
398
+ connection_distance,
399
+ nb_points_threshold,
400
+ clusters_distance_threshold,
401
+ half_epipolar_size,
402
+ window,
403
+ overlap,
404
+ epsg=None,
405
+ point_cloud_csv_file_name=None,
406
+ point_cloud_laz_file_name=None,
407
+ saving_info_epipolar=None,
408
+ saving_info_flatten=None,
409
+ ):
410
+ """
411
+ Small component outlier removal in epipolar geometry
412
+
413
+ :param epipolar_ds: epipolar dataset to filter
414
+ :type epipolar_ds: xr.Dataset
415
+ :param connection_distance: minimum distance of two connected points
416
+ :type connection_distance: float
417
+ :param nb_points_threshold: minimum valid cluster size
418
+ :type nb_points_threshold: int
419
+ :param clusters_distance_threshold: max distance between an outlier cluster
420
+ and other points
421
+ :type clusters_distance_threshold: float
422
+ :param half_epipolar_size: half size of the window used to search neighbors
423
+ :type half_epipolar_size: int
424
+ :param window: window of base tile [row min, row max, col min col max]
425
+ :type window: list
426
+ :param overlap: overlap [row min, row max, col min col max]
427
+ :type overlap: list
428
+
429
+ :return: filtered dataset
430
+ :rtype: xr.Dataset
431
+
432
+ """
433
+
434
+ # Copy input cloud
435
+ filtered_cloud = copy.copy(cloud)
436
+
437
+ # Get current epsg
438
+ cloud_epsg = filtered_cloud.attrs["epsg"]
439
+ current_epsg = cloud_epsg
440
+
441
+ # Check if can be used to filter
442
+ spatial_ref = CRS.from_epsg(cloud_epsg)
443
+ if spatial_ref.is_geographic:
444
+ logging.debug(
445
+ "The points cloud to filter is not in a cartographic system. "
446
+ "The filter's default parameters might not be adapted "
447
+ "to this referential. Please, convert the points "
448
+ "cloud to ECEF to ensure a proper point_cloud."
449
+ )
450
+ # Convert to epsg = 4978
451
+ cartographic_epsg = 4978
452
+
453
+ projection.point_cloud_conversion_dataset(
454
+ filtered_cloud, cartographic_epsg
455
+ )
456
+ current_epsg = cartographic_epsg
457
+
458
+ outlier_removal_algo.epipolar_small_components(
459
+ filtered_cloud,
460
+ min_cluster_size=nb_points_threshold,
461
+ radius=connection_distance,
462
+ half_window_size=half_epipolar_size,
463
+ clusters_distance_threshold=clusters_distance_threshold,
464
+ )
465
+
466
+ # Fill with attributes
467
+ cars_dataset.fill_dataset(
468
+ filtered_cloud,
469
+ saving_info=saving_info_epipolar,
470
+ window=cars_dataset.window_array_to_dict(window),
471
+ profile=None,
472
+ attributes=None,
473
+ overlaps=cars_dataset.overlap_array_to_dict(overlap),
474
+ )
475
+
476
+ # Flatten point cloud to save it as LAZ
477
+ flatten_filtered_cloud = None
478
+ if point_cloud_csv_file_name or point_cloud_laz_file_name:
479
+ # Convert epipolar array into point cloud
480
+ flatten_filtered_cloud, cloud_epsg = (
481
+ pc_transform.depth_map_dataset_to_dataframe(
482
+ filtered_cloud, current_epsg
483
+ )
484
+ )
485
+ # Convert to UTM
486
+ if epsg is not None and cloud_epsg != epsg:
487
+ projection.point_cloud_conversion_dataframe(
488
+ flatten_filtered_cloud, cloud_epsg, epsg
489
+ )
490
+ cloud_epsg = epsg
491
+
492
+ # Fill attributes for LAZ saving
493
+ color_type = pc_transform.get_color_type([filtered_cloud])
494
+
495
+ attributes = {
496
+ "epsg": cloud_epsg,
497
+ "color_type": color_type,
498
+ cst.CROPPED_DISPARITY_RANGE: ocht.get_disparity_range_cropped(
499
+ cloud
500
+ ),
501
+ }
502
+
503
+ cars_dataset.fill_dataframe(
504
+ flatten_filtered_cloud,
505
+ saving_info=saving_info_flatten,
506
+ attributes=attributes,
507
+ )
508
+
509
+ # Save point cloud in worker
510
+ if point_cloud_csv_file_name:
511
+ cars_dataset.run_save_points(
512
+ flatten_filtered_cloud,
513
+ point_cloud_csv_file_name,
514
+ overwrite=True,
515
+ point_cloud_format="csv",
516
+ overwrite_file_name=False,
517
+ )
518
+ if point_cloud_laz_file_name:
519
+ cars_dataset.run_save_points(
520
+ flatten_filtered_cloud,
521
+ point_cloud_laz_file_name,
522
+ overwrite=True,
523
+ point_cloud_format="laz",
524
+ overwrite_file_name=False,
525
+ )
526
+
527
+ return filtered_cloud, flatten_filtered_cloud