cars 1.0.0rc1__cp312-cp312-manylinux_2_17_i686.manylinux2014_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 (200) 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-312-i386-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 +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 +200 -0
  199. cars-1.0.0rc1.dist-info/WHEEL +6 -0
  200. cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,552 @@
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
+ # pylint: disable=too-many-lines
22
+ """
23
+ This module is responsible for the transition between triangulation and
24
+ rasterization steps
25
+ """
26
+ # pylint: disable=C0302
27
+
28
+ # Standard imports
29
+ import logging
30
+ from typing import List, Tuple, Union
31
+
32
+ # Third party imports
33
+ import numpy as np
34
+ import pandas as pd
35
+ import xarray as xr
36
+
37
+ from cars.applications.dense_matching import dense_matching_wrappers
38
+
39
+ # CARS imports
40
+ from cars.core import constants as cst
41
+ from cars.core import projection
42
+
43
+
44
+ def filter_cloud_with_mask(crop_cloud, crop_terrain_tile_data_msk):
45
+ """
46
+ Delete masked points with terrain tile mask
47
+
48
+ :param crop_cloud: the point cloud
49
+ :param crop_terrain_tile_data_msk: terrain tile mask
50
+ """
51
+ crop_terrain_tile_data_msk = np.ravel(crop_terrain_tile_data_msk)
52
+
53
+ crop_terrain_tile_data_msk_pos = np.nonzero(~crop_terrain_tile_data_msk)
54
+
55
+ crop_cloud = np.delete(crop_cloud, crop_terrain_tile_data_msk_pos[0], 0)
56
+
57
+ return crop_cloud
58
+
59
+
60
+ # pylint: disable=too-many-positional-arguments
61
+ def compute_terrain_msk(
62
+ dsm_epsg,
63
+ xmin,
64
+ xmax,
65
+ ymin,
66
+ ymax,
67
+ margin,
68
+ epsg,
69
+ point_cloud,
70
+ full_x,
71
+ full_y,
72
+ ):
73
+ """
74
+ Compute terrain tile msk bounds
75
+
76
+ If the point clouds are not in the same referential as the roi,
77
+ it is converted using the dsm_epsg
78
+
79
+ :param dsm_epsg: epsg code for the CRS of the final output raster
80
+ :param xmin: xmin of the rasterization grid
81
+ (if None, the whole clouds are combined)
82
+ :param xmax: xmax of the rasterization grid
83
+ (if None, the whole clouds are combined)
84
+ :param ymin: ymin of the rasterization grid
85
+ (if None, the whole clouds are combined)
86
+ :param ymax: ymax of the rasterization grid
87
+ (if None, the whole clouds are combined)
88
+ :param margin: Margin added for each tile, in meter or degree.
89
+ (default value: 0)
90
+ :param epsg: epsg code of the input cloud
91
+ :param point_cloud: the point cloud
92
+ :param full_x: point_cloud[X]
93
+ :param full_y: point_cloud[Y]
94
+ """
95
+ if epsg != dsm_epsg:
96
+ (
97
+ full_x,
98
+ full_y,
99
+ ) = projection.get_converted_xy_np_arrays_from_dataset(
100
+ point_cloud, dsm_epsg
101
+ )
102
+ msk_xmin = np.where(full_x > xmin - margin, True, False)
103
+ msk_xmax = np.where(full_x < xmax + margin, True, False)
104
+ msk_ymin = np.where(full_y > ymin - margin, True, False)
105
+ msk_ymax = np.where(full_y < ymax + margin, True, False)
106
+ terrain_tile_data_msk = np.logical_and(
107
+ msk_xmin,
108
+ np.logical_and(msk_xmax, np.logical_and(msk_ymin, msk_ymax)),
109
+ )
110
+ terrain_tile_data_msk_pos = terrain_tile_data_msk.astype(np.int8).nonzero()
111
+
112
+ return terrain_tile_data_msk, terrain_tile_data_msk_pos
113
+
114
+
115
+ def create_point_cloud_index(cloud_sample):
116
+ """
117
+ Create point cloud index from cloud list keys and color inputs
118
+ """
119
+ cloud_indexes_with_types = {
120
+ cst.X: "float64",
121
+ cst.Y: "float64",
122
+ cst.Z: "float64",
123
+ }
124
+
125
+ # Add Z_inf Z_sup, and performance maps if computed
126
+ for key in list(cloud_sample.keys()):
127
+ if (
128
+ cst.POINT_CLOUD_LAYER_INF in key
129
+ or cst.POINT_CLOUD_LAYER_SUP in key
130
+ or cst.POINT_CLOUD_PERFORMANCE_MAP_ROOT in key
131
+ ):
132
+ cloud_indexes_with_types[key] = "float32"
133
+
134
+ # Add mask index
135
+ if cst.EPI_MSK in cloud_sample:
136
+ cloud_indexes_with_types[cst.POINT_CLOUD_MSK] = "uint8"
137
+
138
+ # Add color indexes
139
+ if cst.EPI_TEXTURE in cloud_sample:
140
+ band_color = list(cloud_sample.coords[cst.BAND_IM].to_numpy())
141
+ color_type = "float32"
142
+ if "color_type" in cloud_sample.attrs:
143
+ color_type = cloud_sample.attrs["color_type"]
144
+ for band in band_color:
145
+ band_index = "{}_{}".format(cst.POINT_CLOUD_CLR_KEY_ROOT, band)
146
+ cloud_indexes_with_types[band_index] = color_type
147
+
148
+ # Add classif indexes
149
+ if cst.EPI_CLASSIFICATION in cloud_sample:
150
+ band_classif = list(cloud_sample.coords[cst.BAND_CLASSIF].to_numpy())
151
+ for band in band_classif:
152
+ band_index = "{}_{}".format(cst.POINT_CLOUD_CLASSIF_KEY_ROOT, band)
153
+ cloud_indexes_with_types[band_index] = "boolean"
154
+
155
+ # Add filling information indexes
156
+ if cst.EPI_FILLING in cloud_sample:
157
+ band_filling = list(cloud_sample.coords[cst.BAND_FILLING].to_numpy())
158
+ for band in band_filling:
159
+ band_index = "{}_{}".format(cst.POINT_CLOUD_FILLING_KEY_ROOT, band)
160
+ cloud_indexes_with_types[band_index] = "uint8"
161
+
162
+ # Add ambiguity information index
163
+ if cst.EPI_AMBIGUITY in cloud_sample:
164
+ cloud_indexes_with_types[cst.EPI_AMBIGUITY] = "float32"
165
+
166
+ return cloud_indexes_with_types
167
+
168
+
169
+ # pylint: disable=too-many-positional-arguments
170
+ def add_information_to_cloud(
171
+ input_cloud, cloud_indexes, bbox, target_cloud, input_array, output_column
172
+ ):
173
+ """
174
+ Add color information for a current cloud_list item
175
+
176
+ :param cloud: source point cloud dataset
177
+ :type cloud: xr.Dataset
178
+ :param cloud_indexes: list of band data to extract
179
+ :type cloud_indexes: list[str]
180
+ :param bbox: bbox of interest
181
+ :type bbox: list[int]
182
+ :param crop_cloud: target flatten point cloud
183
+ :type crop_cloud: np.array[columns, points]
184
+ :param input_array: index of input to extract from cloud
185
+ :type input_array: str
186
+ :param output_column: index of crop_cloud to fill
187
+ :type input_array: str
188
+ """
189
+ if input_array in input_cloud:
190
+ full_array = input_cloud[input_array]
191
+ if len(full_array.shape) == 3:
192
+ # Array with multiple bands
193
+ array = full_array[:, bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
194
+ for column_name in cloud_indexes:
195
+ if output_column in column_name:
196
+ band_name = column_name.replace(output_column + "_", "")
197
+ band = array.loc[band_name]
198
+ index = cloud_indexes.index(column_name)
199
+ target_cloud[index, :] = np.ravel(band.values)
200
+ elif len(full_array.shape) == 2:
201
+ # Array with single band
202
+ array = full_array[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
203
+ index = cloud_indexes.index(output_column)
204
+ target_cloud[index, :] = np.ravel(array.values)
205
+
206
+
207
+ def get_color_type(clouds):
208
+ """
209
+ Get color type of the tiles and if the same type.
210
+
211
+ :param cloud_list: list of clouds
212
+ :type cloud_list: xarray Dataset
213
+
214
+ :return: color type of the tiles list
215
+ :rtype: str
216
+
217
+ """
218
+ color_types = []
219
+ for cloud_id, cloud_item in enumerate(clouds):
220
+ if cst.EPI_TEXTURE in clouds[cloud_id]:
221
+ if "color_type" in cloud_item.attrs:
222
+ color_types.append(cloud_item.attrs["color_type"])
223
+ if color_types:
224
+ color_type_set = set(color_types)
225
+ if len(color_type_set) > 1:
226
+ logging.warning("The tiles colors don't have the same type.")
227
+ return color_types[0]
228
+
229
+ return None
230
+
231
+
232
+ def filter_cloud(
233
+ cloud: pd.DataFrame,
234
+ index_elt_to_remove: List[int],
235
+ filtered_elt_pos: bool = False,
236
+ ) -> Tuple[pd.DataFrame, Union[None, pd.DataFrame]]:
237
+ """
238
+ Filter all points of the cloud DataFrame
239
+ which index is in the index_elt_to_remove list.
240
+
241
+ If filtered_elt_pos is set to True, the information of the removed elements
242
+ positions in their original epipolar images are returned.
243
+
244
+ To do so the cloud DataFrame has to be build
245
+ with the 'with_coords' option activated.
246
+
247
+ :param cloud: combined cloud
248
+ as returned by the create_combined_cloud function
249
+ :param index_elt_to_remove: indexes of lines
250
+ to filter in the cloud DataFrame
251
+ :param filtered_elt_pos: if filtered_elt_pos is set to True,
252
+ the removed points positions in their original epipolar images are
253
+ returned, otherwise it is set to None
254
+ :return: Tuple composed of the filtered cloud DataFrame and
255
+ the filtered elements epipolar position information
256
+ (or None for the latter if filtered_elt_pos is set to False
257
+ or if the cloud Dataframe has not been build with with_coords option)
258
+ """
259
+ if filtered_elt_pos and not (
260
+ cst.POINT_CLOUD_COORD_EPI_GEOM_I in cloud.columns
261
+ and cst.POINT_CLOUD_COORD_EPI_GEOM_J in cloud.columns
262
+ and cst.POINT_CLOUD_ID_IM_EPI in cloud.columns
263
+ ):
264
+ logging.warning(
265
+ "In filter_cloud: the filtered_elt_pos has been activated but "
266
+ "the cloud Datafram has not been build with option with_coords. "
267
+ "The positions cannot be retrieved."
268
+ )
269
+ filtered_elt_pos = False
270
+
271
+ # retrieve removed points position in their original epipolar images
272
+ if filtered_elt_pos:
273
+ labels = [
274
+ cst.POINT_CLOUD_COORD_EPI_GEOM_I,
275
+ cst.POINT_CLOUD_COORD_EPI_GEOM_J,
276
+ cst.POINT_CLOUD_ID_IM_EPI,
277
+ ]
278
+
279
+ removed_elt_pos_infos = cloud.loc[
280
+ cloud.index.values[index_elt_to_remove], labels
281
+ ].values
282
+
283
+ removed_elt_pos_infos = pd.DataFrame(
284
+ removed_elt_pos_infos, columns=labels
285
+ )
286
+ else:
287
+ removed_elt_pos_infos = None
288
+
289
+ # remove points from the cloud
290
+ cloud = cloud.drop(index=cloud.index.values[index_elt_to_remove])
291
+
292
+ return cloud, removed_elt_pos_infos
293
+
294
+
295
+ # pylint: disable=too-many-positional-arguments
296
+ def depth_map_dataset_to_dataframe( # noqa: C901
297
+ cloud_dataset: xr.Dataset,
298
+ dsm_epsg: int,
299
+ xmin: float = None,
300
+ xmax: float = None,
301
+ ymin: int = None,
302
+ ymax: int = None,
303
+ margin: float = 0,
304
+ with_coords: bool = False,
305
+ ) -> Tuple[pd.DataFrame, int]:
306
+ """
307
+ Combine a list of clouds (and their colors) into a pandas dataframe
308
+ structured with the following labels:
309
+
310
+ - if no colors in input and no mask data present in cloud_list datasets:
311
+ labels=[cst.X, cst.Y, cst.Z] \
312
+ The combined cloud has x, y, z columns
313
+
314
+ - if no colors in input and mask data present in cloud_list datasets:
315
+ labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK]\
316
+ The mask values are added to the dataframe.
317
+
318
+ - if colors are set in input and mask data are present \
319
+ in the cloud_list datasets:
320
+ labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK,\
321
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"0",\
322
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"1",\
323
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"2"]\
324
+ Color channels information are added to the dataframe.
325
+
326
+ - if colors in input, mask data present in the cloud_list datasets and\
327
+ the with_coords option is activated:
328
+ labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK,\
329
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"0",\
330
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"1",\
331
+ cst.POINT_CLOUD_CLR_KEY_ROOT+"2"\
332
+ cst.POINT_CLOUD_COORD_EPI_GEOM_I,\
333
+ cst.POINT_CLOUD_COORD_EPI_GEOM_J,\
334
+ cst.POINT_CLOUD_ID_IM_EPI]\
335
+ The pixel position of the xyz point in the original epipolar\
336
+ image (coord_epi_geom_i, coord_epi_geom_j) are added\
337
+ to the dataframe along with the index of its original cloud\
338
+ in the cloud_list input.
339
+ - if confidence intervals on Z in input, then\
340
+ [cst.Z_INF, cst.Z_SUP] are also added to the labels
341
+
342
+
343
+ :param dsm_epsg: epsg code for the CRS of the final output raster
344
+ :param xmin: xmin of the rasterization grid
345
+ (if None, the whole clouds are combined)
346
+ :param xmax: xmax of the rasterization grid
347
+ (if None, the whole clouds are combined)
348
+ :param ymin: ymin of the rasterization grid
349
+ (if None, the whole clouds are combined)
350
+ :param ymax: ymax of the rasterization grid
351
+ (if None, the whole clouds are combined)
352
+ :param margin: Margin added for each tile, in meter or degree.
353
+ (default value: 0)
354
+ :param with_coords: Option enabling the adding to the combined cloud
355
+ of information of each point to retrieve their positions
356
+ in the original epipolar images
357
+ :return: Tuple formed with the combined clouds and color
358
+ in a single pandas dataframe and the epsg code
359
+ """
360
+ epsg = int(cloud_dataset.attrs[cst.EPSG])
361
+
362
+ # Compute margin/roi and final number of data to add to the combined cloud
363
+ roi = (
364
+ xmin is not None
365
+ and xmax is not None
366
+ and ymin is not None
367
+ and ymax is not None
368
+ )
369
+
370
+ # Create point cloud index
371
+ cloud_indexes_with_types = create_point_cloud_index(cloud_dataset)
372
+
373
+ # Add coords
374
+ if with_coords:
375
+ cloud_indexes_with_types.update(
376
+ {
377
+ cst.POINT_CLOUD_COORD_EPI_GEOM_I: "uint16",
378
+ cst.POINT_CLOUD_COORD_EPI_GEOM_J: "uint16",
379
+ }
380
+ )
381
+
382
+ cloud_indexes = list(cloud_indexes_with_types.keys())
383
+
384
+ # crop point cloud if is not created from tif depth maps
385
+ if (
386
+ cst.EPI_MARGINS in cloud_dataset.attrs
387
+ and cst.ROI in cloud_dataset.attrs
388
+ ):
389
+ ref_roi, _, _ = dense_matching_wrappers.compute_cropped_roi(
390
+ cloud_dataset.attrs[cst.EPI_MARGINS],
391
+ 0,
392
+ cloud_dataset.attrs[cst.ROI],
393
+ cloud_dataset.sizes[cst.ROW],
394
+ cloud_dataset.sizes[cst.COL],
395
+ )
396
+ cloud_dataset = cloud_dataset.isel(
397
+ row=slice(ref_roi[1], ref_roi[3]),
398
+ col=slice(ref_roi[0], ref_roi[2]),
399
+ )
400
+
401
+ full_x = cloud_dataset[cst.X].values
402
+ full_y = cloud_dataset[cst.Y].values
403
+ full_z = cloud_dataset[cst.Z].values
404
+
405
+ # get mask of points inside the roi (plus margins)
406
+ if roi:
407
+ # Compute terrain tile bounds
408
+ # if the point clouds are not in the same referential as the roi,
409
+ # it is converted using the dsm_epsg
410
+ (
411
+ terrain_tile_data_msk,
412
+ terrain_tile_data_msk_pos,
413
+ ) = compute_terrain_msk(
414
+ dsm_epsg,
415
+ xmin,
416
+ xmax,
417
+ ymin,
418
+ ymax,
419
+ margin,
420
+ epsg,
421
+ cloud_dataset,
422
+ full_x,
423
+ full_y,
424
+ )
425
+
426
+ # if the point clouds are not in the same referential as the roi,
427
+ # retrieve the initial values
428
+ if epsg != dsm_epsg:
429
+ full_x = cloud_dataset[cst.X].values
430
+ full_y = cloud_dataset[cst.Y].values
431
+
432
+ # if no point is found, return Empty cloud
433
+ if terrain_tile_data_msk_pos[0].shape[0] == 0:
434
+ logging.error("No points found to transform")
435
+ return pd.DataFrame(columns=cloud_indexes), epsg
436
+
437
+ # get useful data bounding box
438
+ bbox = [
439
+ np.min(terrain_tile_data_msk_pos[0]),
440
+ np.min(terrain_tile_data_msk_pos[1]),
441
+ np.max(terrain_tile_data_msk_pos[0]),
442
+ np.max(terrain_tile_data_msk_pos[1]),
443
+ ]
444
+ else:
445
+ bbox = [0, 0, full_y.shape[0] - 1, full_y.shape[1] - 1]
446
+
447
+ # add (x, y, z) information to the current cloud
448
+ crop_x = full_x[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
449
+ crop_y = full_y[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
450
+ crop_z = full_z[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
451
+
452
+ flatten_cloud = np.zeros(
453
+ (
454
+ len(cloud_indexes),
455
+ (bbox[2] - bbox[0] + 1) * (bbox[3] - bbox[1] + 1),
456
+ )
457
+ )
458
+ flatten_cloud[cloud_indexes.index(cst.X), :] = np.ravel(crop_x)
459
+ flatten_cloud[cloud_indexes.index(cst.Y), :] = np.ravel(crop_y)
460
+ flatten_cloud[cloud_indexes.index(cst.Z), :] = np.ravel(crop_z)
461
+
462
+ # add additional information to point cloud
463
+ arrays_to_add_to_point_cloud = [
464
+ (cst.EPI_TEXTURE, cst.POINT_CLOUD_CLR_KEY_ROOT),
465
+ (cst.EPI_MSK, cst.POINT_CLOUD_MSK),
466
+ (cst.EPI_CLASSIFICATION, cst.POINT_CLOUD_CLASSIF_KEY_ROOT),
467
+ (cst.EPI_FILLING, cst.POINT_CLOUD_FILLING_KEY_ROOT),
468
+ ]
469
+
470
+ # Add layer inf and sup
471
+ for array_name in cloud_dataset:
472
+ if cst.POINT_CLOUD_LAYER_SUP_OR_INF_ROOT in array_name:
473
+ arrays_to_add_to_point_cloud.append((array_name, array_name))
474
+
475
+ # add performance map
476
+ for array_name in cloud_dataset:
477
+ if cst.POINT_CLOUD_PERFORMANCE_MAP_ROOT in array_name:
478
+ arrays_to_add_to_point_cloud.append((array_name, array_name))
479
+
480
+ # add ambiguity layer, drop confidence_* layers
481
+ for array_name in cloud_dataset:
482
+ if (
483
+ cst.EPI_AMBIGUITY in array_name
484
+ and cst.EPI_CONFIDENCE_KEY_ROOT not in array_name
485
+ ):
486
+ arrays_to_add_to_point_cloud.append((array_name, array_name))
487
+
488
+ # add denoising info layers
489
+ for array_name in cloud_dataset:
490
+ if cst.EPI_DENOISING_INFO_KEY_ROOT in array_name:
491
+ arrays_to_add_to_point_cloud.append((array_name, array_name))
492
+
493
+ for input_band, output_column in arrays_to_add_to_point_cloud:
494
+ add_information_to_cloud(
495
+ cloud_dataset,
496
+ cloud_indexes,
497
+ bbox,
498
+ flatten_cloud,
499
+ input_band,
500
+ output_column,
501
+ )
502
+
503
+ # add the original image coordinates information to the current cloud
504
+ if with_coords:
505
+ coords_line = np.linspace(bbox[0], bbox[2], bbox[2] - bbox[0] + 1)
506
+ coords_col = np.linspace(bbox[1], bbox[3], bbox[3] - bbox[1] + 1)
507
+ coords_col, coords_line = np.meshgrid(coords_col, coords_line)
508
+
509
+ flatten_cloud[
510
+ cloud_indexes.index(cst.POINT_CLOUD_COORD_EPI_GEOM_I), :
511
+ ] = np.ravel(coords_line)
512
+ flatten_cloud[
513
+ cloud_indexes.index(cst.POINT_CLOUD_COORD_EPI_GEOM_J), :
514
+ ] = np.ravel(coords_col)
515
+
516
+ # Transpose point cloud
517
+ flatten_cloud = flatten_cloud.transpose()
518
+
519
+ # remove masked data (pandora + out of the terrain tile points)
520
+ crop_terrain_tile_data_msk = (
521
+ cloud_dataset[cst.POINT_CLOUD_CORR_MSK].values[
522
+ bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1
523
+ ]
524
+ == 255
525
+ )
526
+
527
+ if roi:
528
+ crop_terrain_tile_data_msk = np.logical_and(
529
+ crop_terrain_tile_data_msk,
530
+ terrain_tile_data_msk[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1],
531
+ )
532
+
533
+ flatten_cloud = filter_cloud_with_mask(
534
+ flatten_cloud, crop_terrain_tile_data_msk
535
+ )
536
+
537
+ # Remove points with nan values on X, Y or Z
538
+ xyz_indexes = np.array(
539
+ [
540
+ cloud_indexes.index(cst.X),
541
+ cloud_indexes.index(cst.Y),
542
+ cloud_indexes.index(cst.Z),
543
+ ]
544
+ )
545
+ flatten_cloud = flatten_cloud[
546
+ ~np.any(np.isnan(flatten_cloud[:, xyz_indexes]), axis=1)
547
+ ]
548
+
549
+ pd_cloud = pd.DataFrame(flatten_cloud, columns=cloud_indexes)
550
+ pd_cloud = pd_cloud.astype(cloud_indexes_with_types)
551
+
552
+ return pd_cloud, epsg