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