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,588 @@
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 wrapper used in disparity grid computation.
23
+ """
24
+
25
+ # Standard imports
26
+ import itertools
27
+ import logging
28
+
29
+ # Third party imports
30
+ import numpy as np
31
+ import rasterio
32
+ import xarray as xr
33
+ from scipy.ndimage import maximum_filter, minimum_filter
34
+ from shareloc.proj_utils import transform_physical_point_to_index
35
+
36
+ # CARS imports
37
+ import cars.applications.dense_matching.dense_matching_constants as dm_cst
38
+ import cars.orchestrator.orchestrator as ocht
39
+ from cars.applications.dense_matching.dense_matching_algo import (
40
+ LinearInterpNearestExtrap,
41
+ )
42
+ from cars.core import inputs, projection
43
+ from cars.core.projection import point_cloud_conversion
44
+ from cars.data_structures import cars_dataset, cars_dict
45
+
46
+
47
+ # pylint: disable=too-many-positional-arguments
48
+ def generate_disp_grids_dataset(
49
+ grid_min,
50
+ grid_max,
51
+ saving_info,
52
+ raster_profile,
53
+ window=None,
54
+ row_coords=None,
55
+ col_coords=None,
56
+ ):
57
+ """
58
+ Generate disparity grids xarray dataset
59
+
60
+ :param grid_min: disp grid min
61
+ :type grid_min: np.ndarray
62
+ :param grid_max: disp grid max
63
+ :type grid_max: np.ndarray
64
+ :param saving_info: saving infos
65
+ :type saving_info: dict
66
+ :param raster_profile: raster_profile
67
+ :type raster_profile: dict
68
+ :param row_coords: row cooordinates
69
+ :type row_coords: np.ndarray, optional
70
+ :param col_coords: col coordinates
71
+ :type col_coords: np.ndarray, optional
72
+
73
+ :return: disp range dataset
74
+ :rtype: xarray.Dataset
75
+ """
76
+
77
+ if row_coords is None:
78
+ row_coords = np.arange(0, grid_min.shape[0])
79
+
80
+ if col_coords is None:
81
+ col_coords = np.arange(0, grid_min.shape[1])
82
+
83
+ disp_range_tile = xr.Dataset(
84
+ data_vars={
85
+ dm_cst.DISP_MIN_GRID: (["row", "col"], grid_min),
86
+ dm_cst.DISP_MAX_GRID: (["row", "col"], grid_max),
87
+ },
88
+ coords={
89
+ "row": row_coords,
90
+ "col": col_coords,
91
+ },
92
+ )
93
+
94
+ cars_dataset.fill_dataset(
95
+ disp_range_tile,
96
+ saving_info=saving_info,
97
+ window=window,
98
+ profile=raster_profile,
99
+ attributes=None,
100
+ overlaps=None,
101
+ )
102
+
103
+ return disp_range_tile
104
+
105
+
106
+ # pylint: disable=too-many-positional-arguments
107
+ def generate_disp_range_const_tile_wrapper(
108
+ row_range,
109
+ col_range,
110
+ dmin,
111
+ dmax,
112
+ raster_profile,
113
+ saving_info,
114
+ saving_info_global_infos,
115
+ ):
116
+ """
117
+ Generate disparity range dataset from constant dmin and dmax
118
+
119
+ :param row_range: Row range
120
+ :type row_range: list
121
+ :param col_range: Column range.
122
+ :type col_range: list
123
+ :param dmin: disparity minimum.
124
+ :type dmin: float
125
+ :param dmax: disparity maximum.
126
+ :type dmax: float
127
+ :param raster_profile: The raster profile.
128
+ :type raster_profile: dict
129
+ :param saving_info: The disp range grid saving information.
130
+ :type saving_info: dict
131
+ :param saving_info_global_infos: Global info saving infos.
132
+ :type saving_info_global_infos: dict
133
+
134
+ :return: Disparity range grid
135
+ :rtype: dict
136
+ """
137
+ grid_min = np.empty((len(row_range), len(col_range)))
138
+ grid_max = np.empty((len(row_range), len(col_range)))
139
+ grid_min[:, :] = dmin
140
+ grid_max[:, :] = dmax
141
+
142
+ mono_tile_saving_info = ocht.update_saving_infos(saving_info, row=0, col=0)
143
+ disp_range = generate_disp_grids_dataset(
144
+ grid_min, grid_max, mono_tile_saving_info, raster_profile, window=None
145
+ )
146
+
147
+ # Generate infos on global min and max
148
+ global_infos = cars_dict.CarsDict(
149
+ {"global_min": np.nanmin(dmin), "global_max": np.nanmin(dmax)}
150
+ )
151
+ cars_dataset.fill_dict(global_infos, saving_info=saving_info_global_infos)
152
+
153
+ return disp_range, global_infos
154
+
155
+
156
+ # pylint: disable=too-many-positional-arguments
157
+ def generate_disp_range_from_dem_wrapper(
158
+ epipolar_grid_array_window,
159
+ full_epi_row_range,
160
+ full_epi_col_range,
161
+ sensor_image_right,
162
+ grid_right,
163
+ geom_plugin_with_dem_and_geoid,
164
+ dem_median,
165
+ dem_min,
166
+ dem_max,
167
+ raster_profile,
168
+ saving_info,
169
+ saving_info_global_infos,
170
+ filter_overlap,
171
+ disp_to_alt_ratio,
172
+ disp_min_threshold=None,
173
+ disp_max_threshold=None,
174
+ ):
175
+ """
176
+ Generate disparity range dataset from dems
177
+
178
+ :param epipolar_grid_array_window: The window of the epipolar grid array.
179
+ :type epipolar_grid_array_window: dict
180
+ :param full_epi_row_range: The full range of rows in the epipolar grid.
181
+ :type full_epi_row_range: list
182
+ :param full_epi_col_range: The full range of columns in the epipolar grid.
183
+ :type full_epi_col_range: list
184
+ :param sensor_image_right: The right sensor image.
185
+ :type sensor_image_right: dict
186
+ :param grid_right: The right epipolar grid.
187
+ :type grid_right: dict
188
+ :param geom_plugin_with_dem_and_geoid: The geometry plugin with DEM.
189
+ :type geom_plugin_with_dem_and_geoid: object
190
+ :param dem_median: Path of dem median.
191
+ :type dem_median: str
192
+ :param dem_min: Path of dem min.
193
+ :type dem_min: str
194
+ :param dem_max: Path of dem max.
195
+ :type dem_max: srt
196
+ :param raster_profile: The raster profile.
197
+ :type raster_profile: dict
198
+ :param saving_info: The disp range grid saving information.
199
+ :type saving_info: dict
200
+ :param saving_info_global_infos: Global info saving infos.
201
+ :type saving_info_global_infos: dict
202
+ :param filter_overlap: The overlap to use for filtering.
203
+ :type filter_overlap: int
204
+ :param disp_to_alt_ratio: disparity to altitude ratio
205
+ :type disp_to_alt_ratio: float
206
+ :param disp_min_threshold: The minimum disparity threshold.
207
+ :type disp_min_threshold: float, optional
208
+ :param disp_max_threshold: The maximum disparity threshold.
209
+ :type disp_max_threshold: float, optional
210
+
211
+ :return: Disparity range grid
212
+ :rtype: dict
213
+ """
214
+
215
+ # compute reverse matrix
216
+ transform_sensor = inputs.rasterio_get_transform(
217
+ sensor_image_right["image"]["bands"]["b0"]["path"], convention="north"
218
+ )
219
+
220
+ trans_inv_sensor = ~transform_sensor
221
+
222
+ # Geometry plugin
223
+ geo_plugin = geom_plugin_with_dem_and_geoid
224
+
225
+ # get epsg
226
+ terrain_epsg = inputs.rasterio_get_epsg(dem_median)
227
+
228
+ # Get epipolar position of all dem mean
229
+ transform_dem_median = inputs.rasterio_get_transform(dem_median)
230
+
231
+ # use local disparity
232
+
233
+ # Get associated alti mean / min / max values
234
+ dem_median_shape = inputs.rasterio_get_size(dem_median)
235
+ dem_median_width, dem_median_height = dem_median_shape
236
+
237
+ # get corresponding window from epipolar_array_window
238
+ epi_grid_margin = filter_overlap + 1
239
+ epi_grid_row_min = epipolar_grid_array_window["row_min"]
240
+ epi_grid_row_max = epipolar_grid_array_window["row_max"]
241
+ epi_grid_col_min = epipolar_grid_array_window["col_min"]
242
+ epi_grid_col_max = epipolar_grid_array_window["col_max"]
243
+
244
+ def clip(value, min_value, max_value):
245
+ """
246
+ Clip a value inside bounds
247
+ """
248
+ return int(max(min_value, min(value, max_value)))
249
+
250
+ # Epi grid tile coordinate to use, with and without margins
251
+ epi_grid_row_min_with_margin = clip(
252
+ epi_grid_row_min - epi_grid_margin, 0, len(full_epi_row_range)
253
+ )
254
+ epi_grid_row_max_with_margin = clip(
255
+ epi_grid_row_max + epi_grid_margin, 0, len(full_epi_row_range)
256
+ )
257
+ epi_grid_col_min_with_margin = clip(
258
+ epi_grid_col_min - epi_grid_margin, 0, len(full_epi_col_range)
259
+ )
260
+ epi_grid_col_max_with_margin = clip(
261
+ epi_grid_col_max + epi_grid_margin, 0, len(full_epi_col_range)
262
+ )
263
+
264
+ # range to use for epipolar interpolation
265
+ row_range_with_margin = full_epi_row_range[
266
+ epi_grid_row_min_with_margin:epi_grid_row_max_with_margin
267
+ ]
268
+ row_range_no_margin = full_epi_row_range[epi_grid_row_min:epi_grid_row_max]
269
+ col_range_with_margin = full_epi_col_range[
270
+ epi_grid_col_min_with_margin:epi_grid_col_max_with_margin
271
+ ]
272
+ col_range_no_margin = full_epi_col_range[epi_grid_col_min:epi_grid_col_max]
273
+
274
+ # Loc on dem median
275
+ epi_bbox = [
276
+ (np.min(col_range_with_margin), np.min(row_range_with_margin)),
277
+ (np.min(col_range_with_margin), np.max(row_range_with_margin)),
278
+ (np.max(col_range_with_margin), np.min(row_range_with_margin)),
279
+ (np.max(col_range_with_margin), np.max(row_range_with_margin)),
280
+ ]
281
+ sensor_bbox = geo_plugin.sensor_position_from_grid(
282
+ grid_right, epi_bbox, interpolation_method="linear"
283
+ )
284
+ row_sensor_bbox, col_sensor_bbox = transform_physical_point_to_index(
285
+ trans_inv_sensor, sensor_bbox[:, 1], sensor_bbox[:, 0]
286
+ )
287
+
288
+ terrain_bbox = geo_plugin.safe_direct_loc(
289
+ sensor_image_right["image"]["bands"]["b0"]["path"],
290
+ sensor_image_right["geomodel"],
291
+ col_sensor_bbox,
292
+ row_sensor_bbox,
293
+ )
294
+
295
+ # reshape terrain bbox
296
+ terrain_bbox = terrain_bbox[0:2].T
297
+ terrain_bbox[:, [1, 0]] = terrain_bbox[:, [0, 1]]
298
+
299
+ # get pixel location on dem median
300
+ pixel_roi_dem_mean = inputs.rasterio_get_pixel_points(
301
+ dem_median, terrain_bbox
302
+ )
303
+
304
+ # Add margins (for interpolation) and clip
305
+ dem_margin = 10 # arbitrary
306
+ roi_lower_row = np.floor(np.min(pixel_roi_dem_mean[:, 0])) - dem_margin
307
+ roi_upper_row = np.ceil(np.max(pixel_roi_dem_mean[:, 0])) + dem_margin
308
+ roi_lower_col = np.floor(np.min(pixel_roi_dem_mean[:, 1])) - dem_margin
309
+ roi_upper_col = np.ceil(np.max(pixel_roi_dem_mean[:, 1])) + dem_margin
310
+
311
+ min_row = clip(roi_lower_row, 0, dem_median_height)
312
+ max_row = clip(roi_upper_row, 0, dem_median_height)
313
+ min_col = clip(roi_lower_col, 0, dem_median_width)
314
+ max_col = clip(roi_upper_col, 0, dem_median_width)
315
+
316
+ # compute terrain positions to use (all dem min and max)
317
+ row_indexes = range(min_row, max_row)
318
+ col_indexes = range(min_col, max_col)
319
+ transformer = rasterio.transform.AffineTransformer(transform_dem_median)
320
+
321
+ indexes = np.array(list(itertools.product(row_indexes, col_indexes)))
322
+
323
+ row = indexes[:, 0]
324
+ col = indexes[:, 1]
325
+ x_mean, y_mean = transformer.xy(row, col)
326
+ terrain_positions = np.transpose(np.array([x_mean, y_mean]))
327
+
328
+ # dem mean in terrain_epsg
329
+ x_mean = terrain_positions[:, 0]
330
+ y_mean = terrain_positions[:, 1]
331
+
332
+ dem_median_list = inputs.rasterio_get_values(
333
+ dem_median, x_mean, y_mean, point_cloud_conversion
334
+ )
335
+
336
+ nan_mask = ~np.isnan(dem_median_list)
337
+
338
+ # transform to lon lat
339
+ terrain_position_lon_lat = projection.point_cloud_conversion(
340
+ terrain_positions, terrain_epsg, 4326
341
+ )
342
+ lon_mean = terrain_position_lon_lat[:, 0]
343
+ lat_mean = terrain_position_lon_lat[:, 1]
344
+
345
+ # dem min and max are in 4326
346
+ dem_min_list = inputs.rasterio_get_values(
347
+ dem_min, lon_mean, lat_mean, point_cloud_conversion
348
+ )
349
+ dem_max_list = inputs.rasterio_get_values(
350
+ dem_max, lon_mean, lat_mean, point_cloud_conversion
351
+ )
352
+ if dem_min_list is None or dem_max_list is None:
353
+ logging.warning("DEM min and DEM max does not cover this tile")
354
+ disp_range, global_infos = empty_disparity_grids(
355
+ row_range_no_margin,
356
+ col_range_no_margin,
357
+ epipolar_grid_array_window,
358
+ raster_profile,
359
+ saving_info,
360
+ saving_info_global_infos,
361
+ )
362
+ return disp_range, global_infos
363
+
364
+ nan_mask = nan_mask & ~np.isnan(dem_min_list) & ~np.isnan(dem_max_list)
365
+
366
+ # filter nan value from input points
367
+ lon_mean = lon_mean[nan_mask]
368
+ lat_mean = lat_mean[nan_mask]
369
+ dem_median_list = dem_median_list[nan_mask]
370
+ dem_min_list = dem_min_list[nan_mask]
371
+ dem_max_list = dem_max_list[nan_mask]
372
+
373
+ # sensors physical positions
374
+ (
375
+ ind_cols_sensor,
376
+ ind_rows_sensor,
377
+ _,
378
+ ) = geom_plugin_with_dem_and_geoid.safe_inverse_loc(
379
+ sensor_image_right["image"]["bands"]["b0"]["path"],
380
+ sensor_image_right["geomodel"],
381
+ lat_mean,
382
+ lon_mean,
383
+ z_coord=dem_median_list,
384
+ )
385
+
386
+ # Generate epipolar disp grids
387
+ # Get epipolar positions
388
+ (epipolar_positions_row, epipolar_positions_col) = np.meshgrid(
389
+ col_range_with_margin,
390
+ row_range_with_margin,
391
+ )
392
+ epipolar_positions = np.stack(
393
+ [epipolar_positions_row, epipolar_positions_col], axis=2
394
+ )
395
+
396
+ # Get sensor position
397
+ sensors_positions = (
398
+ geom_plugin_with_dem_and_geoid.sensor_position_from_grid(
399
+ grid_right,
400
+ np.reshape(
401
+ epipolar_positions,
402
+ (
403
+ epipolar_positions.shape[0] * epipolar_positions.shape[1],
404
+ 2,
405
+ ),
406
+ ),
407
+ interpolation_method="linear",
408
+ )
409
+ )
410
+
411
+ # Transform physical position to index
412
+ ind_rows_sensor_grid, ind_cols_sensor_grid = (
413
+ transform_physical_point_to_index(
414
+ trans_inv_sensor, sensors_positions[:, 1], sensors_positions[:, 0]
415
+ )
416
+ )
417
+
418
+ if len(ind_rows_sensor) < 5:
419
+ # QH6214 needs at least 4 points for interpolation
420
+ disp_range, global_infos = empty_disparity_grids(
421
+ row_range_no_margin,
422
+ col_range_no_margin,
423
+ epipolar_grid_array_window,
424
+ raster_profile,
425
+ saving_info,
426
+ saving_info_global_infos,
427
+ )
428
+ return disp_range, global_infos
429
+
430
+ # Interpolate disparity
431
+ disp_min_points = -(dem_max_list - dem_median_list) / disp_to_alt_ratio
432
+ disp_max_points = -(dem_min_list - dem_median_list) / disp_to_alt_ratio
433
+
434
+ interp_min_linear = LinearInterpNearestExtrap(
435
+ list(zip(ind_rows_sensor, ind_cols_sensor)), # noqa: B905
436
+ disp_min_points,
437
+ )
438
+ interp_max_linear = LinearInterpNearestExtrap(
439
+ list(zip(ind_rows_sensor, ind_cols_sensor)), # noqa: B905
440
+ disp_max_points,
441
+ )
442
+
443
+ grid_min = np.reshape(
444
+ interp_min_linear(ind_rows_sensor_grid, ind_cols_sensor_grid),
445
+ (
446
+ epipolar_positions.shape[0],
447
+ epipolar_positions.shape[1],
448
+ ),
449
+ )
450
+
451
+ grid_max = np.reshape(
452
+ interp_max_linear(ind_rows_sensor_grid, ind_cols_sensor_grid),
453
+ (
454
+ epipolar_positions.shape[0],
455
+ epipolar_positions.shape[1],
456
+ ),
457
+ )
458
+
459
+ # Add margin
460
+ diff = grid_max - grid_min
461
+ logging.info("Max grid max - grid min : {} disp ".format(np.max(diff)))
462
+
463
+ if disp_min_threshold is not None:
464
+ if np.any(grid_min < disp_min_threshold):
465
+ logging.warning(
466
+ "Override disp_min with disp_min_threshold {}".format(
467
+ disp_min_threshold
468
+ )
469
+ )
470
+ grid_min[grid_min < disp_min_threshold] = disp_min_threshold
471
+ if disp_max_threshold is not None:
472
+ if np.any(grid_max > disp_max_threshold):
473
+ logging.warning(
474
+ "Override disp_max with disp_max_threshold {}".format(
475
+ disp_max_threshold
476
+ )
477
+ )
478
+ grid_max[grid_max > disp_max_threshold] = disp_max_threshold
479
+
480
+ # generate footprint
481
+ footprint_mask = create_circular_mask(filter_overlap, filter_overlap)
482
+ grid_min = minimum_filter(
483
+ grid_min, footprint=footprint_mask, mode="nearest"
484
+ )
485
+ grid_max = maximum_filter(
486
+ grid_max, footprint=footprint_mask, mode="nearest"
487
+ )
488
+
489
+ # Create xarray dataset
490
+ disp_range = generate_disp_grids_dataset(
491
+ grid_min,
492
+ grid_max,
493
+ saving_info,
494
+ raster_profile,
495
+ window=epipolar_grid_array_window,
496
+ row_coords=row_range_with_margin,
497
+ col_coords=col_range_with_margin,
498
+ )
499
+
500
+ # crop epipolar grid from margin added for propagation filter
501
+ disp_range = disp_range.sel(
502
+ row=list(row_range_no_margin), col=list(col_range_no_margin)
503
+ )
504
+
505
+ # Generate infos on global min and max
506
+ global_infos = cars_dict.CarsDict(
507
+ {
508
+ "global_min": np.floor(np.nanmin(grid_min)),
509
+ "global_max": np.ceil(np.nanmax(grid_max)),
510
+ }
511
+ )
512
+ cars_dataset.fill_dict(global_infos, saving_info=saving_info_global_infos)
513
+
514
+ return disp_range, global_infos
515
+
516
+
517
+ def empty_disparity_grids( # pylint: disable=too-many-positional-arguments
518
+ row_range_no_margin,
519
+ col_range_no_margin,
520
+ epipolar_grid_array_window,
521
+ raster_profile,
522
+ saving_info,
523
+ saving_info_global_infos,
524
+ ):
525
+ """
526
+ Return empty disparity grids
527
+ :param row_range_no_margin: Rows id in grid
528
+ :type row_range_no_margin: int
529
+ :param col_range_no_margin: Cols id in grid
530
+ :type col_range_no_margin: int
531
+ :param epipolar_grid_array_window: ROI of grid
532
+ :type epipolar_grid_array_window: dict
533
+ :param raster_profile: The raster profile.
534
+ :type raster_profile: dict
535
+ :param saving_info: The disp range grid saving information.
536
+ :type saving_info: dict
537
+ :param saving_info_global_infos: Global info saving infos.
538
+ :type saving_info_global_infos: dict
539
+ """
540
+ grid_min = np.empty((len(row_range_no_margin), len(col_range_no_margin)))
541
+ grid_max = np.empty((len(row_range_no_margin), len(col_range_no_margin)))
542
+ grid_min[:, :] = 0
543
+ grid_max[:, :] = 0
544
+
545
+ disp_range = generate_disp_grids_dataset(
546
+ grid_min,
547
+ grid_max,
548
+ saving_info,
549
+ raster_profile,
550
+ window=epipolar_grid_array_window,
551
+ row_coords=row_range_no_margin,
552
+ col_coords=col_range_no_margin,
553
+ )
554
+
555
+ # Generate infos on global min and max
556
+ global_infos = cars_dict.CarsDict(
557
+ {
558
+ "global_min": 0,
559
+ "global_max": 0,
560
+ }
561
+ )
562
+ cars_dataset.fill_dict(global_infos, saving_info=saving_info_global_infos)
563
+
564
+ return disp_range, global_infos
565
+
566
+
567
+ def create_circular_mask(height, width):
568
+ """
569
+ Create a circular mask for footprint around pixel
570
+
571
+ :param height: height of footprint
572
+ :type height: int
573
+ :param width: width of footprint
574
+ :type width: int
575
+
576
+ :return: mask representing circular footprint
577
+ :rtype: np.ndarray
578
+ """
579
+ center = (int(width / 2), int(height / 2))
580
+ radius = min(center[0], center[1], width - center[0], height - center[1])
581
+
582
+ y_grid, x_grid = np.ogrid[:height, :width]
583
+ dist_from_center = np.sqrt(
584
+ (x_grid - center[0]) ** 2 + (y_grid - center[1]) ** 2
585
+ )
586
+
587
+ mask = dist_from_center <= radius
588
+ return mask.astype(bool)
@@ -0,0 +1,23 @@
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 core dense matching module init file
23
+ """
@@ -0,0 +1,31 @@
1
+ {
2
+ "input": {},
3
+ "pipeline": {
4
+ "matching_cost": {
5
+ "matching_cost_method": "census",
6
+ "window_size": 5,
7
+ "subpix": 1
8
+ },
9
+ "optimization": {
10
+ "optimization_method": "sgm",
11
+ "overcounting": false,
12
+ "penalty": {
13
+ "P1": 8,
14
+ "P2": 32,
15
+ "p2_method": "constant",
16
+ "penalty_method": "sgm_penalty"
17
+ }
18
+ },
19
+ "disparity": {
20
+ "disparity_method": "wta",
21
+ "invalid_disparity": "NaN"
22
+ },
23
+ "refinement": {
24
+ "refinement_method": "vfit"
25
+ },
26
+ "filter": {
27
+ "filter_method": "median",
28
+ "filter_size": 3
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "input": {},
3
+ "pipeline": {
4
+ "matching_cost": {
5
+ "matching_cost_method": "census",
6
+ "window_size": 11,
7
+ "subpix": 1
8
+ },
9
+ "optimization": {
10
+ "optimization_method": "sgm",
11
+ "overcounting": true,
12
+ "penalty": {
13
+ "P1": 72,
14
+ "P2": 309,
15
+ "penalty_method": "sgm_penalty"
16
+ }
17
+ },
18
+ "disparity": {
19
+ "disparity_method": "wta",
20
+ "invalid_disparity": "NaN"
21
+ },
22
+ "refinement": {
23
+ "refinement_method": "vfit"
24
+ },
25
+ "filter": {
26
+ "filter_method": "median",
27
+ "filter_size": 3
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "input": {},
3
+ "pipeline": {
4
+ "matching_cost": {
5
+ "matching_cost_method": "census",
6
+ "window_size": 11,
7
+ "subpix": 1
8
+ },
9
+ "optimization": {
10
+ "optimization_method": "sgm",
11
+ "overcounting": true,
12
+ "penalty": {
13
+ "P1": 38,
14
+ "P2": 464,
15
+ "penalty_method": "sgm_penalty"
16
+ }
17
+ },
18
+ "disparity": {
19
+ "disparity_method": "wta",
20
+ "invalid_disparity": "NaN"
21
+ },
22
+ "refinement": {
23
+ "refinement_method": "vfit"
24
+ },
25
+ "filter": {
26
+ "filter_method": "median",
27
+ "filter_size": 3
28
+ }
29
+ }
30
+ }