cars 1.0.0rc2__cp312-cp312-win_amd64.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 (225) hide show
  1. cars/__init__.py +86 -0
  2. cars/applications/__init__.py +40 -0
  3. cars/applications/application.py +117 -0
  4. cars/applications/application_constants.py +29 -0
  5. cars/applications/application_template.py +146 -0
  6. cars/applications/auxiliary_filling/__init__.py +29 -0
  7. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +105 -0
  8. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
  9. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +632 -0
  10. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
  11. cars/applications/dem_generation/__init__.py +30 -0
  12. cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
  13. cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
  14. cars/applications/dem_generation/bulldozer_dem_app.py +641 -0
  15. cars/applications/dem_generation/bulldozer_memory.py +55 -0
  16. cars/applications/dem_generation/dem_generation_algo.py +107 -0
  17. cars/applications/dem_generation/dem_generation_constants.py +32 -0
  18. cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
  19. cars/applications/dense_match_filling/__init__.py +30 -0
  20. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
  21. cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
  22. cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
  23. cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
  24. cars/applications/dense_match_filling/zero_padding_app.py +302 -0
  25. cars/applications/dense_matching/__init__.py +30 -0
  26. cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
  27. cars/applications/dense_matching/census_mccnn_sgm_app.py +1461 -0
  28. cars/applications/dense_matching/cpp/__init__.py +0 -0
  29. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.dll.a +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.pyd +0 -0
  31. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  32. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  33. cars/applications/dense_matching/cpp/meson.build +9 -0
  34. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  35. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  36. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  37. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  38. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  39. cars/applications/dense_matching/disparity_grid_algo.py +597 -0
  40. cars/applications/dense_matching/loaders/__init__.py +23 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  46. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  47. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  48. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  49. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  50. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  51. cars/applications/dsm_filling/__init__.py +32 -0
  52. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  53. cars/applications/dsm_filling/border_interpolation_app.py +278 -0
  54. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  55. cars/applications/dsm_filling/bulldozer_filling_app.py +288 -0
  56. cars/applications/dsm_filling/exogenous_filling_app.py +341 -0
  57. cars/applications/dsm_merging/__init__.py +28 -0
  58. cars/applications/dsm_merging/abstract_dsm_merging_app.py +101 -0
  59. cars/applications/dsm_merging/weighted_fusion_app.py +639 -0
  60. cars/applications/grid_correction/__init__.py +30 -0
  61. cars/applications/grid_correction/abstract_grid_correction_app.py +103 -0
  62. cars/applications/grid_correction/grid_correction_app.py +557 -0
  63. cars/applications/grid_generation/__init__.py +30 -0
  64. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  65. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  66. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  67. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  68. cars/applications/grid_generation/transform_grid.py +88 -0
  69. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  70. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  71. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  72. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  73. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  74. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  75. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  76. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  77. cars/applications/point_cloud_outlier_removal/small_components_app.py +522 -0
  78. cars/applications/point_cloud_outlier_removal/statistical_app.py +528 -0
  79. cars/applications/rasterization/__init__.py +30 -0
  80. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  81. cars/applications/rasterization/rasterization_algo.py +534 -0
  82. cars/applications/rasterization/rasterization_constants.py +38 -0
  83. cars/applications/rasterization/rasterization_wrappers.py +639 -0
  84. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  85. cars/applications/resampling/__init__.py +28 -0
  86. cars/applications/resampling/abstract_resampling_app.py +187 -0
  87. cars/applications/resampling/bicubic_resampling_app.py +760 -0
  88. cars/applications/resampling/resampling_algo.py +590 -0
  89. cars/applications/resampling/resampling_constants.py +36 -0
  90. cars/applications/resampling/resampling_wrappers.py +309 -0
  91. cars/applications/sensors_subsampling/__init__.py +32 -0
  92. cars/applications/sensors_subsampling/abstract_subsampling_app.py +109 -0
  93. cars/applications/sensors_subsampling/rasterio_subsampling_app.py +420 -0
  94. cars/applications/sensors_subsampling/subsampling_algo.py +108 -0
  95. cars/applications/sparse_matching/__init__.py +30 -0
  96. cars/applications/sparse_matching/abstract_sparse_matching_app.py +599 -0
  97. cars/applications/sparse_matching/sift_app.py +724 -0
  98. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  99. cars/applications/sparse_matching/sparse_matching_constants.py +66 -0
  100. cars/applications/sparse_matching/sparse_matching_wrappers.py +282 -0
  101. cars/applications/triangulation/__init__.py +32 -0
  102. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  103. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  104. cars/applications/triangulation/pc_transform.py +552 -0
  105. cars/applications/triangulation/triangulation_algo.py +371 -0
  106. cars/applications/triangulation/triangulation_constants.py +38 -0
  107. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  108. cars/bundleadjustment.py +750 -0
  109. cars/cars.py +179 -0
  110. cars/conf/__init__.py +23 -0
  111. cars/conf/geoid/egm96.grd +0 -0
  112. cars/conf/geoid/egm96.grd.hdr +15 -0
  113. cars/conf/input_parameters.py +156 -0
  114. cars/conf/mask_cst.py +35 -0
  115. cars/core/__init__.py +23 -0
  116. cars/core/cars_logging.py +402 -0
  117. cars/core/constants.py +191 -0
  118. cars/core/constants_disparity.py +50 -0
  119. cars/core/datasets.py +140 -0
  120. cars/core/geometry/__init__.py +27 -0
  121. cars/core/geometry/abstract_geometry.py +1119 -0
  122. cars/core/geometry/shareloc_geometry.py +598 -0
  123. cars/core/inputs.py +568 -0
  124. cars/core/outputs.py +176 -0
  125. cars/core/preprocessing.py +722 -0
  126. cars/core/projection.py +843 -0
  127. cars/core/roi_tools.py +215 -0
  128. cars/core/tiling.py +774 -0
  129. cars/core/utils.py +164 -0
  130. cars/data_structures/__init__.py +23 -0
  131. cars/data_structures/cars_dataset.py +1544 -0
  132. cars/data_structures/cars_dict.py +74 -0
  133. cars/data_structures/corresponding_tiles_tools.py +186 -0
  134. cars/data_structures/dataframe_converter.py +185 -0
  135. cars/data_structures/format_transformation.py +297 -0
  136. cars/devibrate.py +689 -0
  137. cars/extractroi.py +264 -0
  138. cars/orchestrator/__init__.py +23 -0
  139. cars/orchestrator/achievement_tracker.py +125 -0
  140. cars/orchestrator/cluster/__init__.py +37 -0
  141. cars/orchestrator/cluster/abstract_cluster.py +250 -0
  142. cars/orchestrator/cluster/abstract_dask_cluster.py +381 -0
  143. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  144. cars/orchestrator/cluster/dask_config/README.md +94 -0
  145. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  146. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  147. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  148. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  149. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  150. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  151. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  152. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  153. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  154. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  155. cars/orchestrator/cluster/log_wrapper.py +728 -0
  156. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  157. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  158. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  159. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  160. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  161. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +986 -0
  162. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  163. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  164. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  165. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  166. cars/orchestrator/memory_tools.py +47 -0
  167. cars/orchestrator/orchestrator.py +755 -0
  168. cars/orchestrator/orchestrator_constants.py +29 -0
  169. cars/orchestrator/registry/__init__.py +23 -0
  170. cars/orchestrator/registry/abstract_registry.py +143 -0
  171. cars/orchestrator/registry/compute_registry.py +106 -0
  172. cars/orchestrator/registry/id_generator.py +116 -0
  173. cars/orchestrator/registry/replacer_registry.py +213 -0
  174. cars/orchestrator/registry/saver_registry.py +363 -0
  175. cars/orchestrator/registry/unseen_registry.py +118 -0
  176. cars/orchestrator/tiles_profiler.py +279 -0
  177. cars/pipelines/__init__.py +26 -0
  178. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  179. cars/pipelines/conf_resolution/conf_first_resolution.yaml +4 -0
  180. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  181. cars/pipelines/default/__init__.py +26 -0
  182. cars/pipelines/default/default_pipeline.py +1088 -0
  183. cars/pipelines/filling/__init__.py +26 -0
  184. cars/pipelines/filling/filling.py +981 -0
  185. cars/pipelines/formatting/__init__.py +26 -0
  186. cars/pipelines/formatting/formatting.py +186 -0
  187. cars/pipelines/merging/__init__.py +26 -0
  188. cars/pipelines/merging/merging.py +439 -0
  189. cars/pipelines/parameters/__init__.py +0 -0
  190. cars/pipelines/parameters/advanced_parameters.py +256 -0
  191. cars/pipelines/parameters/advanced_parameters_constants.py +68 -0
  192. cars/pipelines/parameters/application_parameters.py +72 -0
  193. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  194. cars/pipelines/parameters/dsm_inputs.py +349 -0
  195. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  196. cars/pipelines/parameters/output_constants.py +52 -0
  197. cars/pipelines/parameters/output_parameters.py +438 -0
  198. cars/pipelines/parameters/sensor_inputs.py +859 -0
  199. cars/pipelines/parameters/sensor_inputs_constants.py +51 -0
  200. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  201. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  202. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  203. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  204. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  205. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  206. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  207. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  208. cars/pipelines/pipeline.py +119 -0
  209. cars/pipelines/pipeline_constants.py +38 -0
  210. cars/pipelines/pipeline_template.py +135 -0
  211. cars/pipelines/subsampling/__init__.py +26 -0
  212. cars/pipelines/subsampling/subsampling.py +358 -0
  213. cars/pipelines/surface_modeling/__init__.py +26 -0
  214. cars/pipelines/surface_modeling/surface_modeling.py +2098 -0
  215. cars/pipelines/tie_points/__init__.py +26 -0
  216. cars/pipelines/tie_points/tie_points.py +536 -0
  217. cars/starter.py +167 -0
  218. cars-1.0.0rc2.dist-info/DELVEWHEEL +2 -0
  219. cars-1.0.0rc2.dist-info/METADATA +289 -0
  220. cars-1.0.0rc2.dist-info/RECORD +225 -0
  221. cars-1.0.0rc2.dist-info/WHEEL +4 -0
  222. cars-1.0.0rc2.dist-info/entry_points.txt +8 -0
  223. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  224. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  225. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
@@ -0,0 +1,590 @@
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
+ Resampling module:
23
+ contains functions used for epipolar resampling
24
+ """
25
+
26
+ # Standard imports
27
+ import math
28
+
29
+ # Third party imports
30
+ import numpy as np
31
+ import rasterio as rio
32
+ import resample as cresample
33
+ from rasterio.windows import Window, bounds
34
+
35
+ from cars.conf import mask_cst as msk_cst
36
+
37
+ # CARS imports
38
+ from cars.core import constants as cst
39
+ from cars.core import datasets, inputs, tiling
40
+ from cars.core.geometry import abstract_geometry
41
+
42
+
43
+ def epipolar_rectify_images( # pylint: disable=too-many-positional-arguments
44
+ left_imgs,
45
+ right_imgs,
46
+ grid1,
47
+ grid2,
48
+ region,
49
+ margins,
50
+ epipolar_size_x,
51
+ epipolar_size_y,
52
+ interpolator_image="bicubic",
53
+ interpolator_classif="nearest",
54
+ interpolator_mask="nearest",
55
+ step=None,
56
+ mask1=None,
57
+ mask2=None,
58
+ left_classifs=None,
59
+ right_classifs=None,
60
+ nodata1=0,
61
+ nodata2=0,
62
+ add_classif=True,
63
+ ):
64
+ """
65
+ Resample left and right images
66
+ """
67
+
68
+ # Force region to be float
69
+ region = [int(x) for x in region]
70
+
71
+ # Apply margins to left image
72
+ # TODO: tiled region should be given in parameter
73
+ # TODO: keep only rectification here (keep functional unitary approach)
74
+ left_region = region.copy()
75
+ left_margins = margins["left_margin"].data
76
+ left_roi = tiling.crop(
77
+ left_region, [0, 0, epipolar_size_x, epipolar_size_y]
78
+ )
79
+ left_region = tiling.crop(
80
+ tiling.pad(left_region, left_margins),
81
+ [0, 0, epipolar_size_x, epipolar_size_y],
82
+ )
83
+
84
+ left_margins = margins["left_margin"].data
85
+ # Get actual margin taking cropping into account
86
+ left_margins[0] = left_region[0] - left_roi[0]
87
+ left_margins[1] = left_region[1] - left_roi[1]
88
+ left_margins[2] = left_region[2] - left_roi[2]
89
+ left_margins[3] = left_region[3] - left_roi[3]
90
+
91
+ # Apply margins to right image
92
+ right_region = region.copy()
93
+ right_margins = margins["right_margin"].data
94
+ right_roi = tiling.crop(
95
+ right_region, [0, 0, epipolar_size_x, epipolar_size_y]
96
+ )
97
+ right_region = tiling.crop(
98
+ tiling.pad(right_region, right_margins),
99
+ [0, 0, epipolar_size_x, epipolar_size_y],
100
+ )
101
+
102
+ # Get actual margin taking cropping into account
103
+ right_margins[0] = right_region[0] - right_roi[0]
104
+ right_margins[1] = right_region[1] - right_roi[1]
105
+ right_margins[2] = right_region[2] - right_roi[2]
106
+ right_margins[3] = right_region[3] - right_roi[3]
107
+
108
+ # Resample left images
109
+ left_img_transform = inputs.rasterio_get_transform(
110
+ next(iter(left_imgs)), convention="north"
111
+ )
112
+
113
+ left_dataset = resample_image(
114
+ left_imgs,
115
+ grid1,
116
+ [epipolar_size_x, epipolar_size_y],
117
+ step=step,
118
+ region=left_region,
119
+ nodata=nodata1,
120
+ mask=mask1,
121
+ band_coords=cst.BAND_IM,
122
+ interpolator_img=interpolator_image,
123
+ interpolator_mask=interpolator_mask,
124
+ img_transform=left_img_transform,
125
+ )
126
+
127
+ # Update attributes
128
+ left_dataset.attrs[cst.ROI] = np.array(left_roi)
129
+ left_dataset.attrs[cst.ROI_WITH_MARGINS] = np.array(left_region)
130
+ # Remove region key as it duplicates roi_with_margins key
131
+ # left_dataset.attrs.pop("region", None)
132
+ left_dataset.attrs[cst.EPI_MARGINS] = np.array(left_margins)
133
+ if "disp_min" in margins.attrs:
134
+ left_dataset.attrs[cst.EPI_DISP_MIN] = margins.attrs["disp_min"]
135
+ if "disp_max" in margins.attrs:
136
+ left_dataset.attrs[cst.EPI_DISP_MAX] = margins.attrs["disp_max"]
137
+
138
+ # Resample right image
139
+ right_img_transform = inputs.rasterio_get_transform(next(iter(right_imgs)))
140
+ right_dataset = resample_image(
141
+ right_imgs,
142
+ grid2,
143
+ [epipolar_size_x, epipolar_size_y],
144
+ step=step,
145
+ region=right_region,
146
+ nodata=nodata2,
147
+ mask=mask2,
148
+ band_coords=cst.BAND_IM,
149
+ interpolator_img=interpolator_image,
150
+ interpolator_mask=interpolator_mask,
151
+ img_transform=right_img_transform,
152
+ )
153
+
154
+ # Update attributes
155
+ right_dataset.attrs[cst.ROI] = np.array(right_roi)
156
+ right_dataset.attrs[cst.ROI_WITH_MARGINS] = np.array(right_region)
157
+ # Remove region key as it duplicates roi_with_margins key
158
+ # right_dataset.attrs.pop("region", None)
159
+ right_dataset.attrs[cst.EPI_MARGINS] = np.array(right_margins)
160
+ if "disp_min" in margins.attrs:
161
+ right_dataset.attrs[cst.EPI_DISP_MIN] = margins.attrs["disp_min"]
162
+ if "disp_max" in margins.attrs:
163
+ right_dataset.attrs[cst.EPI_DISP_MAX] = margins.attrs["disp_max"]
164
+
165
+ # Resample classifications
166
+ left_classif_dataset = None
167
+ right_classif_dataset = None
168
+ if add_classif:
169
+ if left_classifs:
170
+ left_classif_dataset = resample_image(
171
+ left_classifs,
172
+ grid1,
173
+ [epipolar_size_x, epipolar_size_y],
174
+ region=left_region,
175
+ band_coords=cst.BAND_CLASSIF,
176
+ interpolator_img=interpolator_classif,
177
+ interpolator_mask=interpolator_mask,
178
+ img_transform=left_img_transform,
179
+ )
180
+ if right_classifs:
181
+ right_classif_dataset = resample_image(
182
+ right_classifs,
183
+ grid2,
184
+ [epipolar_size_x, epipolar_size_y],
185
+ region=right_region,
186
+ band_coords=cst.BAND_CLASSIF,
187
+ interpolator_img=interpolator_classif,
188
+ interpolator_mask=interpolator_mask,
189
+ img_transform=right_img_transform,
190
+ )
191
+
192
+ return (
193
+ left_dataset,
194
+ right_dataset,
195
+ left_classif_dataset,
196
+ right_classif_dataset,
197
+ )
198
+
199
+
200
+ # pylint: disable=too-many-positional-arguments
201
+ def resample_image( # noqa: C901
202
+ imgs,
203
+ grid,
204
+ largest_size,
205
+ step=None,
206
+ region=None,
207
+ nodata=None,
208
+ mask=None,
209
+ band_coords=False,
210
+ interpolator_img="bicubic",
211
+ interpolator_mask="nearest",
212
+ img_transform=None,
213
+ ):
214
+ """
215
+ Resample image according to grid and largest size.
216
+
217
+ :param img: Path to the image to resample
218
+ :type img: string
219
+ :param grid: rectification grid dict
220
+ :type grid: dict
221
+ :param largest_size: Size of full output image
222
+ :type largest_size: list of two int
223
+ :param step: horizontal step of resampling (useful for strip resampling)
224
+ :type step: int
225
+ :param region: A subset of the output image to produce
226
+ :type region: None (full output is produced) or array of four floats
227
+ [xmin,ymin,xmax,ymax]
228
+ :param nodata: Nodata value to use (both for input and output)
229
+ :type nodata: None or float
230
+ :param mask: Mask to resample as well
231
+ :type mask: None or path to mask image
232
+ :param band_coords: Force bands coordinate in output dataset
233
+ :type band_coords: boolean
234
+ :param interpolator: interpolator type (bicubic (default) or nearest)
235
+ :type interpolator: str ("nearest" "linear" "bco")
236
+ :rtype: xarray.Dataset with resampled image and mask
237
+ """
238
+ img_sample = next(iter(imgs))
239
+ # Handle region is None
240
+ if region is None:
241
+ region = [0, 0, largest_size[0], largest_size[1]]
242
+ else:
243
+ region = [
244
+ int(math.floor(region[0])),
245
+ int(math.floor(region[1])),
246
+ int(math.ceil(region[2])),
247
+ int(math.ceil(region[3])),
248
+ ]
249
+
250
+ if img_transform is None:
251
+ img_transform = inputs.rasterio_get_transform(
252
+ img_sample, convention="north"
253
+ )
254
+
255
+ # Convert largest_size to int if needed
256
+ largest_size = [int(x) for x in largest_size]
257
+
258
+ # Localize blocks of the tile to resample
259
+ if step is None:
260
+ step = region[2] - region[0]
261
+
262
+ xmin_of_blocks = np.arange(region[0], region[2], step)
263
+ xmax_of_blocks = np.append(
264
+ np.arange(region[0] + step, region[2], step), region[2]
265
+ )
266
+
267
+ ymin_of_blocks = np.arange(region[1], region[3], step)
268
+ ymax_of_blocks = np.append(
269
+ np.arange(region[1] + step, region[3], step), region[3]
270
+ )
271
+
272
+ resampled_images_list = []
273
+ resampled_masks_list = []
274
+ band_names = []
275
+ data_types = []
276
+ nodata_msk = msk_cst.NO_DATA_IN_EPIPOLAR_RECTIFICATION
277
+ for img in imgs:
278
+ bands = imgs[img]
279
+ if "band_id" in bands:
280
+ nb_bands = len(bands["band_id"])
281
+ elif "values" in bands:
282
+ nb_bands = len(bands["values"])
283
+ else:
284
+ raise ValueError(
285
+ "File {} not recognised as an image or classif file".format(
286
+ bands
287
+ )
288
+ )
289
+ # Initialize outputs of the entire tile
290
+ resamp = np.empty(
291
+ (nb_bands, region[3] - region[1], region[2] - region[0]),
292
+ dtype=np.float32,
293
+ )
294
+ msk = np.empty(
295
+ (nb_bands, region[3] - region[1], region[2] - region[0]),
296
+ dtype=np.float32,
297
+ )
298
+
299
+ ystart = 0
300
+ with rio.open(grid["path"]) as grid_reader, rio.open(img) as img_reader:
301
+ for ymin, ymax in zip(ymin_of_blocks, ymax_of_blocks): # noqa: B905
302
+ ysize = ymax - ymin
303
+ xstart = 0
304
+ for xmin, xmax in zip( # noqa: B905
305
+ xmin_of_blocks, xmax_of_blocks
306
+ ):
307
+ block_region = [xmin, ymin, xmax, ymax]
308
+ xsize = xmax - xmin
309
+ resamp, msk = oversampling_func(
310
+ grid_reader,
311
+ img_reader,
312
+ img_transform,
313
+ block_region,
314
+ interpolator_img,
315
+ band_coords,
316
+ nb_bands,
317
+ bands,
318
+ resamp,
319
+ nodata,
320
+ msk,
321
+ mask,
322
+ nodata_msk,
323
+ interpolator_mask,
324
+ ysize,
325
+ xsize,
326
+ ystart,
327
+ xstart,
328
+ )
329
+ xstart += xsize
330
+
331
+ ystart += ysize
332
+ if "band_id" in bands:
333
+ band_names += bands["band_name"]
334
+ elif "values" in bands:
335
+ band_names += list(map(str, bands["values"]))
336
+ else:
337
+ raise ValueError(
338
+ "File {} not recognised as an image or classif file".format(
339
+ bands
340
+ )
341
+ )
342
+ data_types += [inputs.rasterio_get_image_type(img)] * nb_bands
343
+ resampled_images_list.append(resamp)
344
+ resampled_masks_list.append(msk)
345
+
346
+ resamp_final = np.concatenate(resampled_images_list, axis=0)
347
+ msk_final = np.concatenate(resampled_masks_list, axis=0)
348
+ dataset = datasets.create_im_dataset(
349
+ resamp_final,
350
+ region,
351
+ largest_size,
352
+ img_sample,
353
+ band_coords,
354
+ band_names,
355
+ data_types,
356
+ msk_final,
357
+ )
358
+
359
+ return dataset
360
+
361
+
362
+ def oversampling_func( # pylint: disable=too-many-positional-arguments
363
+ grid_reader,
364
+ img_reader,
365
+ img_transform,
366
+ block_region,
367
+ interpolator_img,
368
+ band_coords,
369
+ nb_bands,
370
+ bands,
371
+ resamp,
372
+ nodata,
373
+ msk,
374
+ mask,
375
+ nodata_msk,
376
+ interpolator_mask,
377
+ ysize,
378
+ xsize,
379
+ ystart,
380
+ xstart,
381
+ ):
382
+ """
383
+ Do the resampling calculus
384
+ """
385
+
386
+ xmin = block_region[0]
387
+ ymin = block_region[1]
388
+ xmax = block_region[2]
389
+ ymax = block_region[3]
390
+
391
+ # Build rectification pipelines for images
392
+ res_x, res_y = grid_reader.res
393
+ assert res_x == res_y
394
+ oversampling = int(res_x)
395
+ assert res_x == oversampling
396
+
397
+ grid_origin_x = grid_reader.transform[2]
398
+ grid_origin_y = grid_reader.transform[5]
399
+ assert grid_origin_x == grid_origin_y
400
+ grid_margin = int(-grid_origin_x / oversampling - 0.5)
401
+
402
+ grid_margin = int(grid_margin)
403
+
404
+ # Convert resampled region to grid region with oversampling
405
+ grid_region = np.array(
406
+ [
407
+ math.floor(xmin / oversampling),
408
+ math.floor(ymin / oversampling),
409
+ math.ceil(xmax / oversampling),
410
+ math.ceil(ymax / oversampling),
411
+ ]
412
+ )
413
+
414
+ # Out region of epipolar image
415
+ out_region = oversampling * grid_region
416
+ # Grid region
417
+ grid_region += grid_margin
418
+
419
+ grid_window = Window.from_slices(
420
+ (grid_region[1], grid_region[3] + 1),
421
+ (grid_region[0], grid_region[2] + 1),
422
+ )
423
+ grid_as_array = grid_reader.read(window=grid_window)
424
+ grid_as_array = grid_as_array.astype(np.float32)
425
+ grid_as_array = grid_as_array.astype(np.float64)
426
+
427
+ # get needed source bounding box
428
+ left = math.floor(np.amin(grid_as_array[0, ...]))
429
+ right = math.ceil(np.amax(grid_as_array[0, ...]))
430
+ top = math.floor(np.amin(grid_as_array[1, ...]))
431
+ bottom = math.ceil(np.amax(grid_as_array[1, ...]))
432
+
433
+ transform = rio.Affine(*np.abs(img_transform))
434
+ # transform xmin and xmax positions to index
435
+ (top, bottom, left, right) = abstract_geometry.min_max_to_index_min_max(
436
+ left, right, top, bottom, transform
437
+ )
438
+
439
+ # filter margin for bicubic = 2
440
+ filter_margin = 2
441
+ top -= filter_margin
442
+ bottom += filter_margin
443
+ left -= filter_margin
444
+ right += filter_margin
445
+
446
+ left, right = list(np.clip([left, right], 0, img_reader.shape[0]))
447
+ top, bottom = list(np.clip([top, bottom], 0, img_reader.shape[1]))
448
+
449
+ img_window = Window.from_slices([left, right], [top, bottom])
450
+
451
+ in_sensor = True
452
+ if right - left == 0 or bottom - top == 0:
453
+ in_sensor = False
454
+
455
+ # round window
456
+ img_window = img_window.round_offsets()
457
+ img_window = img_window.round_lengths()
458
+
459
+ # compute offset
460
+ res_x = float(abs(transform[0]))
461
+ res_y = float(abs(transform[4]))
462
+ tile_bounds = list(bounds(img_window, transform))
463
+
464
+ x_offset = min(tile_bounds[0], tile_bounds[2])
465
+ y_offset = min(tile_bounds[1], tile_bounds[3])
466
+
467
+ if in_sensor:
468
+ # get sensor data
469
+ if "band_id" in bands:
470
+ # image
471
+ img_as_array = img_reader.read(bands["band_id"], window=img_window)
472
+ elif "values" in bands:
473
+ # classification
474
+ img_as_array = img_reader.read([1], window=img_window)
475
+ else:
476
+ raise ValueError(
477
+ "File {} not recognised as an image or classif file".format(
478
+ bands
479
+ )
480
+ )
481
+ # get the nodata mask before blurring
482
+ img_nan_mask = img_as_array == nodata
483
+
484
+ # set the nodata values back
485
+ if nodata is not None:
486
+ img_as_array[img_nan_mask] = nodata
487
+
488
+ # shift grid regarding the img extraction
489
+ grid_as_array[0, ...] -= x_offset
490
+ grid_as_array[1, ...] -= y_offset
491
+
492
+ # apply input resolution
493
+ grid_as_array[0, ...] /= res_x
494
+ grid_as_array[1, ...] /= res_y
495
+
496
+ block_resamp = cresample.grid(
497
+ img_as_array,
498
+ grid_as_array,
499
+ oversampling,
500
+ interpolator=interpolator_img,
501
+ nodata=0,
502
+ ).astype(np.float32)
503
+
504
+ if interpolator_img == "bicubic" and band_coords == cst.BAND_CLASSIF:
505
+ block_resamp = np.where(
506
+ block_resamp >= 0.5,
507
+ 1,
508
+ np.where(block_resamp < 0.5, 0, block_resamp),
509
+ ).astype(int)
510
+
511
+ # extract exact region
512
+ ext_region = block_region - out_region
513
+ block_resamp = block_resamp[
514
+ ...,
515
+ ext_region[1] : ext_region[3] - 1,
516
+ ext_region[0] : ext_region[2] - 1,
517
+ ]
518
+
519
+ if "values" in bands:
520
+ # Extract binary bands from mono-band classification
521
+ multiband_block_resamp = np.zeros(
522
+ (
523
+ nb_bands,
524
+ block_region[3] - block_region[1],
525
+ block_region[2] - block_region[0],
526
+ )
527
+ )
528
+ for band_id, value in enumerate(bands["values"]):
529
+ multiband_block_resamp[band_id] = block_resamp == value
530
+ block_resamp = multiband_block_resamp
531
+
532
+ else:
533
+ block_resamp = np.zeros(
534
+ (
535
+ nb_bands,
536
+ block_region[3] - block_region[1],
537
+ block_region[2] - block_region[0],
538
+ )
539
+ )
540
+
541
+ resamp[:, ystart : ystart + ysize, xstart : xstart + xsize] = block_resamp
542
+
543
+ # create msk
544
+ if in_sensor:
545
+ # get mask in source geometry
546
+ if mask is not None:
547
+ with rio.open(mask) as msk_reader:
548
+ msk_as_array = msk_reader.read(1, window=img_window)
549
+ msk_as_array = np.array([msk_as_array] * img_as_array.shape[0])
550
+ else:
551
+ msk_as_array = np.zeros(img_as_array.shape)
552
+
553
+ if nodata is not None:
554
+ nodata_index = img_as_array == nodata
555
+ msk_as_array[nodata_index] = nodata_msk
556
+
557
+ # resample mask
558
+ block_msk = cresample.grid(
559
+ msk_as_array,
560
+ grid_as_array,
561
+ oversampling,
562
+ interpolator=interpolator_mask,
563
+ nodata=nodata_msk,
564
+ )
565
+
566
+ if interpolator_mask == "bicubic":
567
+ block_msk = np.where(
568
+ block_msk >= 0.5,
569
+ 1,
570
+ np.where(block_msk < 0.5, 0, block_msk),
571
+ ).astype(int)
572
+
573
+ block_msk = block_msk[
574
+ ...,
575
+ ext_region[1] : ext_region[3] - 1,
576
+ ext_region[0] : ext_region[2] - 1,
577
+ ]
578
+ else:
579
+ block_msk = np.full(
580
+ (
581
+ nb_bands,
582
+ block_region[3] - block_region[1],
583
+ block_region[2] - block_region[0],
584
+ ),
585
+ fill_value=nodata_msk,
586
+ )
587
+
588
+ msk[:, ystart : ystart + ysize, xstart : xstart + xsize] = block_msk
589
+
590
+ return resamp, msk
@@ -0,0 +1,36 @@
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 constants of resampling.
23
+ """
24
+
25
+
26
+ # USED VARIABLES
27
+
28
+
29
+ RESAMPLING_RUN_TAG = "resampling"
30
+
31
+
32
+ # PARAMS
33
+ METHOD = "method"
34
+ EPI_TILE_SIZE = "epi_tile_size"
35
+
36
+ # INFOS