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,74 @@
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
+ cars_dict module:
23
+
24
+ """
25
+
26
+
27
+ class CarsDict:
28
+ """
29
+ CarsDict.
30
+
31
+ Internal CARS structure for dict representation
32
+ """
33
+
34
+ def __init__(self, dict_data, attributes=None):
35
+ """
36
+ Init function of CarsDict.
37
+ If a path is provided, restore CarsDataset saved on disk.
38
+
39
+ :param dict_data: dictrionary to store
40
+ :type dict_data: dict
41
+ :param attributes: attributes
42
+ :type attributes: dict
43
+
44
+ """
45
+
46
+ self.data = dict_data
47
+ self.attrs = attributes
48
+ if self.attrs is None:
49
+ self.attrs = {}
50
+
51
+ def __repr__(self):
52
+ """
53
+ Repr function
54
+ :return: printable self CarsDataset
55
+ """
56
+ return self.custom_print()
57
+
58
+ def __str__(self):
59
+ """
60
+ Str function
61
+ :return: printable self CarsDataset
62
+ """
63
+ return self.custom_print()
64
+
65
+ def custom_print(self):
66
+ """
67
+ Return string of self
68
+ :return: printable self
69
+ """
70
+
71
+ res = str(self.__class__) + ": \n" "data: " + str(
72
+ self.data
73
+ ) + "\n" + "attrs: " + str(self.attrs)
74
+ return res
@@ -0,0 +1,186 @@
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
+ Contains functions for array reconstructions and crop for multiple tiles
23
+ """
24
+
25
+
26
+ # Third party imports
27
+ import numpy as np
28
+ import xarray as xr
29
+
30
+
31
+ def reconstruct_data(tiles, window, overlap): # noqa: C901
32
+ """
33
+ Combine list of tiles (window, overlap, xr.Dataset) as
34
+ one full dataset
35
+
36
+ :param tiles: list of tiles
37
+ :type tiles: list(tuple)
38
+ :param window: window of base tile [row min, row max, col min col max]
39
+ :type window: list
40
+ :param overlap: overlap of base tile [row min, row max, col min col max]
41
+ :type overlap: list
42
+
43
+ :return: full dataset, row min of combined, col min of combined
44
+ :rtype: xr.Dataset, int, int
45
+
46
+ """
47
+
48
+ first_valid_tile = next(
49
+ (tile for tile in tiles if tile[2] is not None), None
50
+ )
51
+
52
+ if first_valid_tile is None:
53
+ return None, None, None
54
+
55
+ list_tags = list(first_valid_tile[2].keys())
56
+
57
+ row_min, row_max, col_min, col_max = window
58
+ ol_row_min, ol_row_max, ol_col_min, ol_col_max = overlap
59
+
60
+ # find whole window and new overlaps
61
+ for tile_window, tile_overlap, _ in tiles:
62
+ if tile_window[0] < row_min:
63
+ row_min, ol_row_min = tile_window[0], tile_overlap[0]
64
+ if tile_window[1] > row_max:
65
+ row_max, ol_row_max = tile_window[1], tile_overlap[1]
66
+ if tile_window[2] < col_min:
67
+ col_min, ol_col_min = tile_window[2], tile_overlap[2]
68
+ if tile_window[3] > col_max:
69
+ col_max, ol_col_max = tile_window[3], tile_overlap[3]
70
+
71
+ # Generate new arr
72
+
73
+ # Compute full shape
74
+ nb_rows = int(row_max + ol_row_max - (row_min - ol_row_min))
75
+ nb_cols = int(col_max + ol_col_max - (col_min - ol_col_min))
76
+
77
+ new_coords = {}
78
+ for key in first_valid_tile[2].coords.keys():
79
+ if key == "row":
80
+ new_coords["row"] = range(
81
+ int(row_min - ol_row_min), int(row_max + ol_row_max)
82
+ )
83
+ elif key == "col":
84
+ new_coords["col"] = range(
85
+ int(col_min - ol_col_min), int(col_max + ol_col_max)
86
+ )
87
+ elif key == "y":
88
+ # Doesnt contain coordinates, but pixels position
89
+ # after reconstruction, only used in notebooks
90
+ new_coords["y"] = range(
91
+ int(row_min - ol_row_min), int(row_max + ol_row_max)
92
+ )
93
+ elif key == "x":
94
+ # Doesnt contain coordinates, but pixels position
95
+ # after reconstruction, only used in notebooks
96
+ new_coords["x"] = range(
97
+ int(col_min - ol_col_min), int(col_max + ol_col_max)
98
+ )
99
+ else:
100
+ new_coords[key] = first_valid_tile[2].coords[key]
101
+
102
+ new_dataset = xr.Dataset(data_vars={}, coords=new_coords)
103
+
104
+ for tag in list_tags:
105
+ # reconstruct data
106
+ data_type = first_valid_tile[2][tag].dtype
107
+ data_shape = (nb_rows, nb_cols)
108
+ dims = first_valid_tile[2][tag].dims
109
+ if len(dims) == 3:
110
+ nb_bands = first_valid_tile[2][tag].values.shape[0]
111
+ data_shape = (nb_bands, nb_rows, nb_cols)
112
+ data = np.nan * np.zeros(data_shape)
113
+
114
+ for tile_window, tile_overlap, tile_ds in tiles:
115
+ # only use overlaps when on the border of full image
116
+ # row min
117
+ if row_min == tile_window[0]:
118
+ # is on border -> use overlap
119
+ real_row_min = int(tile_window[0])
120
+ getter_offset_row_min = int(0)
121
+ else:
122
+ real_row_min = int(tile_window[0] + ol_row_min)
123
+ getter_offset_row_min = int(tile_overlap[0])
124
+
125
+ # row max
126
+ if row_max == tile_window[1]:
127
+ # is on border -> use overlap
128
+ real_row_max = int(tile_window[1] + ol_row_max + ol_row_min)
129
+ getter_offset_row_max = int(0)
130
+ else:
131
+ real_row_max = int(tile_window[1] + ol_row_min)
132
+ getter_offset_row_max = int(tile_overlap[1])
133
+
134
+ # col min
135
+ if col_min == tile_window[2]:
136
+ # is on border -> use overlap
137
+ real_col_min = int(tile_window[2])
138
+ getter_offset_col_min = int(0)
139
+ else:
140
+ real_col_min = int(tile_window[2] + ol_col_min)
141
+ getter_offset_col_min = int(tile_overlap[2])
142
+
143
+ # col max
144
+ if col_max == tile_window[3]:
145
+ # is on border -> use overlap
146
+ real_col_max = int(tile_window[3] + ol_col_max + ol_col_min)
147
+ getter_offset_col_max = int(0)
148
+ else:
149
+ real_col_max = int(tile_window[3] + ol_col_min)
150
+ getter_offset_col_max = int(tile_overlap[3])
151
+
152
+ real_row_min = int(real_row_min - row_min)
153
+ real_row_max = int(real_row_max - row_min)
154
+ real_col_min = int(real_col_min - col_min)
155
+ real_col_max = int(real_col_max - col_min)
156
+
157
+ # Fill data
158
+ if tile_ds is not None:
159
+ tile_data = tile_ds[tag].values
160
+
161
+ if len(tile_data.shape) == 2:
162
+ data[
163
+ real_row_min:real_row_max, real_col_min:real_col_max
164
+ ] = tile_data[
165
+ getter_offset_row_min : tile_data.shape[0]
166
+ - getter_offset_row_max,
167
+ getter_offset_col_min : tile_data.shape[1]
168
+ - getter_offset_col_max,
169
+ ]
170
+ else:
171
+ data[
172
+ :, real_row_min:real_row_max, real_col_min:real_col_max
173
+ ] = tile_data[
174
+ :,
175
+ getter_offset_row_min : tile_data.shape[1]
176
+ - getter_offset_row_max,
177
+ getter_offset_col_min : tile_data.shape[2]
178
+ - getter_offset_col_max,
179
+ ]
180
+
181
+ # add arrays to data
182
+ new_dataset[tag] = xr.DataArray(
183
+ data,
184
+ dims=dims,
185
+ ).astype(data_type)
186
+ return new_dataset, row_min - ol_row_min, col_min - ol_col_min
@@ -0,0 +1,185 @@
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
+ Contains function to convert the point cloud dataframe to laz format:
23
+ """
24
+ import logging
25
+ import warnings
26
+
27
+ import laspy
28
+ import laspy.file
29
+ import laspy.header
30
+ import numpy as np
31
+ from pyproj import CRS
32
+
33
+ import cars.core.constants as cst
34
+
35
+
36
+ def convert_pcl_to_laz(point_clouds, output_filename: str):
37
+ """
38
+ Convert 3d point cloud to laz format
39
+ :param point_clouds: point_clouds dataframe
40
+ :param output_filename: output laz filename (with naming convention)
41
+ :return: the list of point cloud save in las format
42
+ """
43
+
44
+ # get all layer : X, Y, Z and color
45
+ coordinates = ["X", "Y", "Z"]
46
+ las_color = ["red", "green", "blue"]
47
+ color_type = point_clouds.attrs["attributes"]["color_type"]
48
+ epsg = point_clouds.attrs["attributes"]["epsg"]
49
+ input_color = get_input_color(point_clouds)
50
+ laz_file_name = output_filename
51
+ arrays_pcl, arrays_color = extract_point_cloud(
52
+ point_clouds, coordinates, input_color, color_type
53
+ )
54
+ # generate laz
55
+ generate_laz(
56
+ laz_file_name, coordinates, las_color, arrays_pcl, arrays_color
57
+ )
58
+ # dump prj file
59
+ generate_prj_file(laz_file_name, epsg)
60
+
61
+
62
+ def get_input_color(point_clouds):
63
+ """
64
+ Retrieve color index from point cloud
65
+ :param point_clouds: point clouds data
66
+ :return: input color list
67
+ """
68
+
69
+ input_color = ["color_R", "color_G", "color_B"]
70
+ color_names = [
71
+ name
72
+ for name in point_clouds.columns
73
+ if cst.POINT_CLOUD_CLR_KEY_ROOT in name
74
+ ]
75
+ nb_color = len(color_names)
76
+ if nb_color == 1:
77
+ logging.warning("No color available for point cloud")
78
+ input_color = color_names
79
+ elif sorted(color_names[:3]) != sorted(input_color):
80
+ logging.warning(
81
+ "Descriptions of color bands {} does not conform to names "
82
+ "'R', 'G', 'B'".format(color_names[:3])
83
+ )
84
+ input_color = color_names[:3]
85
+
86
+ return input_color
87
+
88
+
89
+ def extract_point_cloud(point_clouds, coordinates, input_color, color_type):
90
+ """
91
+ Extract point cloud positions (x,y,z) and color layers
92
+ :param point_clouds: point cloud dataframe
93
+ :param coordinate: target coordinates key index
94
+ :param input_color: color key index according to input
95
+ :param color_type: type of color data
96
+ :param nb
97
+ :return: point cloud array location and color
98
+ """
99
+
100
+ nb_color = len(input_color)
101
+ arrays_pcl = None
102
+ arrays_color = None
103
+ for name in point_clouds.columns:
104
+ # get coordinates bands
105
+ if name in ["x", "y", "z"]:
106
+ array = point_clouds[name].to_numpy()
107
+ # first step : define np.ndarray to contains the arrays X,Y,Z
108
+ if arrays_pcl is None:
109
+ arrays_pcl = np.ndarray((3, array.reshape(-1).T.shape[0]))
110
+ # get only valid pixels
111
+ array = array.reshape(-1).T
112
+ # get layer into np.ndarray (laspy accept only XYZ in upper case)
113
+ arrays_pcl[coordinates.index(name.upper())] = array
114
+ elif name in input_color:
115
+ array = point_clouds[name].to_numpy()
116
+ if arrays_color is None:
117
+ arrays_color = np.ndarray((3, array.reshape(-1).T.shape[0]))
118
+ array = array.reshape(-1).T
119
+ maxi = 65535
120
+ if color_type:
121
+ if np.issubdtype(np.dtype(color_type), np.integer):
122
+ maxi = np.min([maxi, np.iinfo(np.dtype(color_type)).max])
123
+ array[array >= maxi] = maxi
124
+ array[array <= 0] = 0
125
+
126
+ arrays_color[input_color.index(name)] = array
127
+ if nb_color == 1:
128
+ arrays_color[1] = array
129
+ arrays_color[2] = array
130
+ return arrays_pcl, arrays_color
131
+
132
+
133
+ def generate_prj_file(output_filename, epsg):
134
+ """
135
+ Generate prj file associated to the laz file if projection is UTM or WGS84
136
+ :param output_filename: name of laz file
137
+ :param epsg: code of output epsg
138
+ """
139
+ with warnings.catch_warnings():
140
+ # Ignore some crs warning
141
+ warnings.filterwarnings(
142
+ "ignore",
143
+ category=UserWarning,
144
+ message=".*You will likely lose important projection"
145
+ " information when converting to a PROJ string from "
146
+ "another format.*",
147
+ )
148
+ crs = CRS.from_epsg(epsg)
149
+ proj = crs.to_proj4()
150
+ if crs.is_geographic:
151
+ logging.warning(
152
+ "Coordinate system of point cloud is geographic: "
153
+ "Display of LAZ file may not work"
154
+ )
155
+ with open(output_filename + ".prj", "w", encoding="utf8") as file_prj:
156
+ file_prj.write(proj)
157
+
158
+
159
+ def generate_laz(
160
+ output_filename, coordinates, las_color, arrays_pcl, arrays_color
161
+ ):
162
+ """
163
+ Generate laz file from location and color arrays
164
+ """
165
+ # Create laz image
166
+ header = laspy.LasHeader(point_format=2)
167
+ scale_factor = 0.01
168
+ header.scales = [scale_factor, scale_factor, scale_factor]
169
+ laz = laspy.LasData(header)
170
+ # fill X,Y,Z into laspy structure, convert to cm
171
+ scale_multiplicator = 1 / scale_factor
172
+ for layer_index in range(arrays_pcl.shape[0]):
173
+ setattr(
174
+ laz,
175
+ [k for i, k in enumerate(coordinates) if i == layer_index][0],
176
+ scale_multiplicator * arrays_pcl[layer_index],
177
+ )
178
+ if arrays_color is not None:
179
+ for color_index in range(arrays_color.shape[0]):
180
+ setattr(
181
+ laz,
182
+ [k for i, k in enumerate(las_color) if i == color_index][0],
183
+ arrays_color[color_index],
184
+ )
185
+ laz.write(output_filename)