cars 1.0.0rc1__cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cars might be problematic. Click here for more details.

Files changed (200) hide show
  1. cars/__init__.py +74 -0
  2. cars/applications/__init__.py +37 -0
  3. cars/applications/application.py +117 -0
  4. cars/applications/application_constants.py +29 -0
  5. cars/applications/application_template.py +146 -0
  6. cars/applications/auxiliary_filling/__init__.py +29 -0
  7. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +104 -0
  8. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
  9. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -0
  10. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
  11. cars/applications/dem_generation/__init__.py +30 -0
  12. cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
  13. cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
  14. cars/applications/dem_generation/bulldozer_dem_app.py +655 -0
  15. cars/applications/dem_generation/bulldozer_memory.py +55 -0
  16. cars/applications/dem_generation/dem_generation_algo.py +107 -0
  17. cars/applications/dem_generation/dem_generation_constants.py +32 -0
  18. cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
  19. cars/applications/dense_match_filling/__init__.py +30 -0
  20. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
  21. cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
  22. cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
  23. cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
  24. cars/applications/dense_match_filling/zero_padding_app.py +302 -0
  25. cars/applications/dense_matching/__init__.py +30 -0
  26. cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
  27. cars/applications/dense_matching/census_mccnn_sgm_app.py +1460 -0
  28. cars/applications/dense_matching/cpp/__init__.py +0 -0
  29. cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-312-i386-linux-gnu.so +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  31. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  32. cars/applications/dense_matching/cpp/meson.build +9 -0
  33. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  34. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  35. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  36. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  37. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  38. cars/applications/dense_matching/disparity_grid_algo.py +588 -0
  39. cars/applications/dense_matching/loaders/__init__.py +23 -0
  40. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  46. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  47. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  48. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  49. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  50. cars/applications/dsm_filling/__init__.py +32 -0
  51. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  52. cars/applications/dsm_filling/border_interpolation_app.py +270 -0
  53. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  54. cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
  55. cars/applications/dsm_filling/exogenous_filling_app.py +333 -0
  56. cars/applications/grid_generation/__init__.py +30 -0
  57. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  58. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  59. cars/applications/grid_generation/grid_correction_app.py +496 -0
  60. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  61. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  62. cars/applications/grid_generation/transform_grid.py +88 -0
  63. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  64. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  65. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  66. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  67. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  68. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  69. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  70. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  71. cars/applications/point_cloud_outlier_removal/small_components_app.py +527 -0
  72. cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -0
  73. cars/applications/rasterization/__init__.py +30 -0
  74. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  75. cars/applications/rasterization/rasterization_algo.py +534 -0
  76. cars/applications/rasterization/rasterization_constants.py +38 -0
  77. cars/applications/rasterization/rasterization_wrappers.py +634 -0
  78. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  79. cars/applications/resampling/__init__.py +28 -0
  80. cars/applications/resampling/abstract_resampling_app.py +187 -0
  81. cars/applications/resampling/bicubic_resampling_app.py +762 -0
  82. cars/applications/resampling/resampling_algo.py +614 -0
  83. cars/applications/resampling/resampling_constants.py +36 -0
  84. cars/applications/resampling/resampling_wrappers.py +309 -0
  85. cars/applications/sparse_matching/__init__.py +30 -0
  86. cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
  87. cars/applications/sparse_matching/sift_app.py +735 -0
  88. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  89. cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
  90. cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
  91. cars/applications/triangulation/__init__.py +32 -0
  92. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  93. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  94. cars/applications/triangulation/pc_transform.py +552 -0
  95. cars/applications/triangulation/triangulation_algo.py +371 -0
  96. cars/applications/triangulation/triangulation_constants.py +38 -0
  97. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  98. cars/bundleadjustment.py +757 -0
  99. cars/cars.py +177 -0
  100. cars/conf/__init__.py +23 -0
  101. cars/conf/geoid/egm96.grd +0 -0
  102. cars/conf/geoid/egm96.grd.hdr +15 -0
  103. cars/conf/input_parameters.py +156 -0
  104. cars/conf/mask_cst.py +35 -0
  105. cars/core/__init__.py +23 -0
  106. cars/core/cars_logging.py +402 -0
  107. cars/core/constants.py +191 -0
  108. cars/core/constants_disparity.py +50 -0
  109. cars/core/datasets.py +140 -0
  110. cars/core/geometry/__init__.py +27 -0
  111. cars/core/geometry/abstract_geometry.py +1119 -0
  112. cars/core/geometry/shareloc_geometry.py +598 -0
  113. cars/core/inputs.py +568 -0
  114. cars/core/outputs.py +176 -0
  115. cars/core/preprocessing.py +722 -0
  116. cars/core/projection.py +843 -0
  117. cars/core/roi_tools.py +215 -0
  118. cars/core/tiling.py +774 -0
  119. cars/core/utils.py +164 -0
  120. cars/data_structures/__init__.py +23 -0
  121. cars/data_structures/cars_dataset.py +1541 -0
  122. cars/data_structures/cars_dict.py +74 -0
  123. cars/data_structures/corresponding_tiles_tools.py +186 -0
  124. cars/data_structures/dataframe_converter.py +185 -0
  125. cars/data_structures/format_transformation.py +297 -0
  126. cars/devibrate.py +689 -0
  127. cars/extractroi.py +264 -0
  128. cars/orchestrator/__init__.py +23 -0
  129. cars/orchestrator/achievement_tracker.py +125 -0
  130. cars/orchestrator/cluster/__init__.py +37 -0
  131. cars/orchestrator/cluster/abstract_cluster.py +244 -0
  132. cars/orchestrator/cluster/abstract_dask_cluster.py +375 -0
  133. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  134. cars/orchestrator/cluster/dask_config/README.md +94 -0
  135. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  136. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  137. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  138. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  139. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  140. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  141. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  142. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  143. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  144. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  145. cars/orchestrator/cluster/log_wrapper.py +1075 -0
  146. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  147. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  148. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  149. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  150. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  151. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +873 -0
  152. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  153. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  154. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  155. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  156. cars/orchestrator/orchestrator.py +905 -0
  157. cars/orchestrator/orchestrator_constants.py +29 -0
  158. cars/orchestrator/registry/__init__.py +23 -0
  159. cars/orchestrator/registry/abstract_registry.py +143 -0
  160. cars/orchestrator/registry/compute_registry.py +106 -0
  161. cars/orchestrator/registry/id_generator.py +116 -0
  162. cars/orchestrator/registry/replacer_registry.py +213 -0
  163. cars/orchestrator/registry/saver_registry.py +363 -0
  164. cars/orchestrator/registry/unseen_registry.py +118 -0
  165. cars/orchestrator/tiles_profiler.py +279 -0
  166. cars/pipelines/__init__.py +26 -0
  167. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  168. cars/pipelines/conf_resolution/conf_first_resolution.yaml +2 -0
  169. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  170. cars/pipelines/default/__init__.py +26 -0
  171. cars/pipelines/default/default_pipeline.py +786 -0
  172. cars/pipelines/parameters/__init__.py +0 -0
  173. cars/pipelines/parameters/advanced_parameters.py +417 -0
  174. cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
  175. cars/pipelines/parameters/application_parameters.py +71 -0
  176. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  177. cars/pipelines/parameters/dsm_inputs.py +918 -0
  178. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  179. cars/pipelines/parameters/output_constants.py +52 -0
  180. cars/pipelines/parameters/output_parameters.py +454 -0
  181. cars/pipelines/parameters/sensor_inputs.py +842 -0
  182. cars/pipelines/parameters/sensor_inputs_constants.py +49 -0
  183. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  184. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  185. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  186. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  187. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  188. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  189. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  190. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  191. cars/pipelines/pipeline.py +119 -0
  192. cars/pipelines/pipeline_constants.py +31 -0
  193. cars/pipelines/pipeline_template.py +139 -0
  194. cars/pipelines/unit/__init__.py +26 -0
  195. cars/pipelines/unit/unit_pipeline.py +2850 -0
  196. cars/starter.py +167 -0
  197. cars-1.0.0rc1.dist-info/METADATA +292 -0
  198. cars-1.0.0rc1.dist-info/RECORD +200 -0
  199. cars-1.0.0rc1.dist-info/WHEEL +6 -0
  200. cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,498 @@
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 abstract matching application class.
23
+ """
24
+ import logging
25
+ import math
26
+ import os
27
+ from abc import ABCMeta, abstractmethod
28
+ from typing import Dict
29
+
30
+ import numpy as np
31
+ import xarray as xr
32
+ from shareloc.geofunctions.rectification_grid import RectificationGrid
33
+
34
+ import cars.applications.sparse_matching.sparse_matching_constants as sm_cst
35
+ import cars.orchestrator.orchestrator as ocht
36
+ from cars.applications import application_constants
37
+ from cars.applications.application import Application
38
+ from cars.applications.application_template import ApplicationTemplate
39
+ from cars.core import constants as cst
40
+ from cars.core.utils import safe_makedirs
41
+
42
+
43
+ @Application.register("sparse_matching")
44
+ class SparseMatching(ApplicationTemplate, metaclass=ABCMeta):
45
+ """
46
+ SparseMatching
47
+ """
48
+
49
+ available_applications: Dict = {}
50
+ default_application = "sift"
51
+
52
+ def __new__(cls, conf=None): # pylint: disable=W0613
53
+ """
54
+ Return the required application
55
+ :raises:
56
+ - KeyError when the required application is not registered
57
+
58
+ :param conf: configuration for matching
59
+ :return: a application_to_use object
60
+ """
61
+
62
+ matching_method = cls.default_application
63
+ if bool(conf) is False or "method" not in conf:
64
+ logging.info(
65
+ "Sparse Matching method not specified, default "
66
+ " {} is used".format(matching_method)
67
+ )
68
+ else:
69
+ matching_method = conf.get("method", cls.default_application)
70
+
71
+ if matching_method not in cls.available_applications:
72
+ logging.error(
73
+ "No matching application named {} registered".format(
74
+ matching_method
75
+ )
76
+ )
77
+ raise KeyError(
78
+ "No matching application named {} registered".format(
79
+ matching_method
80
+ )
81
+ )
82
+
83
+ logging.info(
84
+ "The SparseMatching({}) application will be used".format(
85
+ matching_method
86
+ )
87
+ )
88
+
89
+ return super(SparseMatching, cls).__new__(
90
+ cls.available_applications[matching_method]
91
+ )
92
+
93
+ def __init_subclass__(cls, short_name, **kwargs): # pylint: disable=E0302
94
+ super().__init_subclass__(**kwargs)
95
+ for name in short_name:
96
+ cls.available_applications[name] = cls
97
+
98
+ def __init__(self, conf=None):
99
+ """
100
+ Init function of SparseMatching
101
+
102
+ :param conf: configuration
103
+ :return: an application_to_use object
104
+ """
105
+
106
+ super().__init__(conf=conf)
107
+
108
+ @abstractmethod
109
+ def get_disparity_margin(self):
110
+ """
111
+ Get disparity margin corresponding to sparse matches
112
+
113
+ :return: margin in percent
114
+
115
+ """
116
+
117
+ @abstractmethod
118
+ def get_strip_margin(self):
119
+ """
120
+ Get strip margin corresponding to sparse matches
121
+
122
+ :return: margin
123
+
124
+ """
125
+
126
+ @abstractmethod
127
+ def get_epipolar_error_upper_bound(self):
128
+ """
129
+ Get epipolar error upper bound corresponding to sparse matches
130
+
131
+ :return: margin
132
+
133
+ """
134
+
135
+ @abstractmethod
136
+ def get_epipolar_error_maximum_bias(self):
137
+ """
138
+ Get epipolar error lower bound corresponding to sparse matches
139
+
140
+ :return: margin
141
+
142
+ """
143
+
144
+ @abstractmethod
145
+ def get_match_filter_constant(self):
146
+ """
147
+ Get get_match_filter_constant :
148
+ constant in the formula to compute threshold of outliers
149
+
150
+ :return: match_filter_constant
151
+
152
+ """
153
+
154
+ @abstractmethod
155
+ def get_match_filter_mean_factor(self):
156
+ """
157
+ Get match_filter_mean_factor :
158
+ factor of mean in the formula
159
+ to compute threshold of outliers
160
+
161
+ :return: match_filter_mean_factor
162
+
163
+ """
164
+
165
+ @abstractmethod
166
+ def get_match_filter_knn(self):
167
+ """
168
+ Get match_filter_knn :
169
+ number of neighboors used to measure isolation of matches
170
+
171
+ :return: match_filter_knn
172
+
173
+ """
174
+
175
+ @abstractmethod
176
+ def get_match_filter_dev_factor(self):
177
+ """
178
+ Get match_filter_dev_factor :
179
+ factor of deviation in the formula
180
+ to compute threshold of outliers
181
+
182
+ :return: match_filter_dev_factor
183
+
184
+ """
185
+
186
+ @abstractmethod
187
+ def get_minimum_nb_matches(self):
188
+ """
189
+ Get minimum_nb_matches :
190
+ get the minimum number of matches
191
+
192
+ :return: minimum_nb_matches
193
+
194
+ """
195
+
196
+ def get_margins_fun(self, disp_min=None, disp_max=None, method="sift"):
197
+ """
198
+ Get margins function to use in resampling
199
+
200
+ :param disp_min: disp min for info
201
+ :param disp_max: disp max for info
202
+ :param method: method for the margins
203
+
204
+ :return: margins function
205
+ :rtype: function generating xr.Dataset
206
+
207
+ """
208
+
209
+ # Compute margins
210
+ corner = ["left", "up", "right", "down"]
211
+ data = np.zeros(len(corner))
212
+ col = np.arange(len(corner))
213
+ margins = xr.Dataset(
214
+ {"left_margin": (["col"], data)}, coords={"col": col}
215
+ )
216
+ margins["right_margin"] = xr.DataArray(data, dims=["col"])
217
+
218
+ left_margin = self.get_strip_margin()
219
+
220
+ if method == "sift":
221
+ right_margin = self.get_strip_margin() + int(
222
+ math.floor(
223
+ self.get_epipolar_error_upper_bound()
224
+ + self.get_epipolar_error_maximum_bias()
225
+ )
226
+ )
227
+ else:
228
+ right_margin = left_margin
229
+
230
+ # Compute margins for left region
231
+ margins["left_margin"].data = [0, left_margin, 0, left_margin]
232
+
233
+ # Compute margins for right region
234
+ margins["right_margin"].data = [0, right_margin, 0, right_margin]
235
+
236
+ # add disp range info
237
+ margins.attrs["disp_min"] = disp_min
238
+ margins.attrs["disp_max"] = disp_max
239
+
240
+ logging.info(
241
+ "Margins added to left region for matching: {}".format(
242
+ margins["left_margin"].data
243
+ )
244
+ )
245
+
246
+ logging.info(
247
+ "Margins added to right region for matching: {}".format(
248
+ margins["right_margin"].data
249
+ )
250
+ )
251
+
252
+ def margins_wrapper( # pylint: disable=unused-argument
253
+ row_min, row_max, col_min, col_max
254
+ ):
255
+ """
256
+ Generates margins Dataset used in resampling
257
+
258
+ :param row_min: row min
259
+ :param row_max: row max
260
+ :param col_min: col min
261
+ :param col_max: col max
262
+
263
+ :return: margins
264
+ :rtype: xr.Dataset
265
+ """
266
+
267
+ # Constant margins for all tiles
268
+ return margins
269
+
270
+ return margins_wrapper
271
+
272
+ def filter_matches( # pylint: disable=too-many-positional-arguments
273
+ self,
274
+ epipolar_matches_left,
275
+ grid_left,
276
+ grid_right,
277
+ geom_plugin,
278
+ orchestrator=None,
279
+ pair_key="pair_0",
280
+ pair_folder=None,
281
+ save_matches=False,
282
+ ):
283
+ """
284
+ Transform matches CarsDataset to numpy matches, and filters matches
285
+
286
+ :param cars_orchestrator: orchestrator
287
+ :param epipolar_matches_left: matches. CarsDataset contains:
288
+
289
+ - N x M Delayed tiles \
290
+ Each tile will be a future pandas DataFrame containing:
291
+
292
+ - data : (L, 4) shape matches
293
+ - attributes containing "disp_lower_bound", "disp_upper_bound", \
294
+ "elevation_delta_lower_bound","elevation_delta_upper_bound"
295
+ :type epipolar_matches_left: CarsDataset
296
+ :param grid_left: left epipolar grid dict
297
+ :type grid_left: dict
298
+ :param grid_right: right epipolar grid dict
299
+ :type grid_right: dict
300
+ :param save_matches: true is matches needs to be saved
301
+ :type save_matches: bool
302
+
303
+ :return filtered matches
304
+ :rtype: np.ndarray
305
+
306
+ """
307
+
308
+ # Default orchestrator
309
+ if orchestrator is None:
310
+ # Create default sequential orchestrator for current application
311
+ # be awere, no out_json will be shared between orchestrators
312
+ # No files saved
313
+ cars_orchestrator = ocht.Orchestrator(
314
+ orchestrator_conf={"mode": "sequential"}
315
+ )
316
+ else:
317
+ cars_orchestrator = orchestrator
318
+
319
+ if pair_folder is None:
320
+ pair_folder = os.path.join(cars_orchestrator.out_dir, "tmp")
321
+
322
+ epipolar_error_upper_bound = self.get_epipolar_error_upper_bound()
323
+ epipolar_error_maximum_bias = self.get_epipolar_error_maximum_bias()
324
+
325
+ grid_left = RectificationGrid(
326
+ grid_left["path"],
327
+ interpolator=geom_plugin.interpolator,
328
+ )
329
+ grid_right = RectificationGrid(
330
+ grid_right["path"],
331
+ interpolator=geom_plugin.interpolator,
332
+ )
333
+
334
+ # Concatenated matches
335
+ list_matches = []
336
+ for row in range(epipolar_matches_left.shape[0]):
337
+ for col in range(epipolar_matches_left.shape[1]):
338
+ # CarsDataset containing Pandas DataFrame, not Delayed anymore
339
+ if epipolar_matches_left[row, col] is not None:
340
+ epipolar_matches = epipolar_matches_left[
341
+ row, col
342
+ ].to_numpy()
343
+
344
+ sensor_matches = geom_plugin.matches_to_sensor_coords(
345
+ grid_left,
346
+ grid_right,
347
+ epipolar_matches,
348
+ cst.MATCHES_MODE,
349
+ )
350
+ sensor_matches = np.concatenate(sensor_matches, axis=1)
351
+ matches = np.concatenate(
352
+ [
353
+ epipolar_matches,
354
+ sensor_matches,
355
+ ],
356
+ axis=1,
357
+ )
358
+ list_matches.append(matches)
359
+
360
+ matches = np.concatenate(list_matches)
361
+
362
+ raw_nb_matches = matches.shape[0]
363
+
364
+ logging.info(
365
+ "Raw number of matches found: {} matches".format(raw_nb_matches)
366
+ )
367
+
368
+ # Export matches
369
+ raw_matches_array_path = None
370
+ if save_matches:
371
+ safe_makedirs(pair_folder)
372
+
373
+ logging.info("Writing raw matches file")
374
+ raw_matches_array_path = os.path.join(
375
+ pair_folder, "raw_matches.npy"
376
+ )
377
+ np.save(raw_matches_array_path, matches)
378
+
379
+ # Filter matches that are out of margin
380
+ epipolar_median_shift = np.median(matches[:, 3] - matches[:, 1])
381
+
382
+ if np.abs(epipolar_median_shift) > epipolar_error_maximum_bias:
383
+ epipolar_median_shift = epipolar_error_maximum_bias * np.sign(
384
+ epipolar_median_shift
385
+ )
386
+
387
+ matches = matches[
388
+ ((matches[:, 3] - matches[:, 1]) - epipolar_median_shift)
389
+ >= -epipolar_error_upper_bound
390
+ ]
391
+ matches = matches[
392
+ ((matches[:, 3] - matches[:, 1]) - epipolar_median_shift)
393
+ <= epipolar_error_upper_bound
394
+ ]
395
+
396
+ matches_discarded_message = (
397
+ "{} matches discarded because their epipolar error "
398
+ "is greater than --epipolar_error_upper_bound = {} pix"
399
+ ).format(raw_nb_matches - matches.shape[0], epipolar_error_upper_bound)
400
+
401
+ if epipolar_error_maximum_bias != 0:
402
+ matches_discarded_message += (
403
+ " considering a shift of {} pix".format(epipolar_median_shift)
404
+ )
405
+
406
+ logging.info(matches_discarded_message)
407
+
408
+ filtered_matches_array_path = None
409
+ if save_matches:
410
+ logging.info("Writing filtered matches file")
411
+ filtered_matches_array_path = os.path.join(
412
+ pair_folder, "filtered_matches.npy"
413
+ )
414
+ np.save(filtered_matches_array_path, matches)
415
+
416
+ # Retrieve number of matches
417
+ nb_matches = matches.shape[0]
418
+
419
+ # Check if we have enough matches
420
+ # TODO: we could also make it a warning and continue
421
+ # with uncorrected grid
422
+ # and default disparity range
423
+ if nb_matches < self.get_minimum_nb_matches():
424
+ error_message_matches = (
425
+ "Insufficient amount of matches found ({} < {}), "
426
+ "can not safely estimate epipolar error correction "
427
+ " and disparity range".format(
428
+ nb_matches, self.get_minimum_nb_matches()
429
+ )
430
+ )
431
+ logging.error(error_message_matches)
432
+ raise ValueError(error_message_matches)
433
+
434
+ logging.info(
435
+ "Number of matches kept for epipolar "
436
+ "error correction: {} matches".format(nb_matches)
437
+ )
438
+
439
+ # Compute epipolar error
440
+ epipolar_error = matches[:, 1] - matches[:, 3]
441
+ epi_error_mean = np.mean(epipolar_error)
442
+ epi_error_std = np.std(epipolar_error)
443
+ epi_error_max = np.max(np.fabs(epipolar_error))
444
+ logging.info(
445
+ "Epipolar error before correction: mean = {:.3f} pix., "
446
+ "standard deviation = {:.3f} pix., max = {:.3f} pix.".format(
447
+ epi_error_mean,
448
+ epi_error_std,
449
+ epi_error_max,
450
+ )
451
+ )
452
+
453
+ # Update orchestrator out_json
454
+ raw_matches_infos = {
455
+ application_constants.APPLICATION_TAG: {
456
+ sm_cst.MATCH_FILTERING_TAG: {
457
+ pair_key: {
458
+ sm_cst.NUMBER_MATCHES_TAG: nb_matches,
459
+ sm_cst.RAW_NUMBER_MATCHES_TAG: raw_nb_matches,
460
+ sm_cst.BEFORE_CORRECTION_EPI_ERROR_MEAN: epi_error_mean,
461
+ sm_cst.BEFORE_CORRECTION_EPI_ERROR_STD: epi_error_std,
462
+ sm_cst.BEFORE_CORRECTION_EPI_ERROR_MAX: epi_error_max,
463
+ }
464
+ }
465
+ }
466
+ }
467
+ cars_orchestrator.update_out_info(raw_matches_infos)
468
+
469
+ return matches
470
+
471
+ @abstractmethod
472
+ def get_save_matches(self):
473
+ """
474
+ Get save_matches parameter
475
+
476
+ :return: true is save_matches activated
477
+ :rtype: bool
478
+ """
479
+
480
+ @abstractmethod
481
+ def run( # pylint: disable=too-many-positional-arguments
482
+ self,
483
+ epipolar_image_left,
484
+ epipolar_image_right,
485
+ disp_to_alt_ratio,
486
+ orchestrator=None,
487
+ pair_folder=None,
488
+ pair_key="PAIR_0",
489
+ classif_bands_to_mask=None,
490
+ ):
491
+ """
492
+ Run Matching application.
493
+
494
+ Create left and right CarsDataset filled with pandas.DataFrame ,
495
+ corresponding to epipolar 2D disparities, on the same geometry
496
+ that epipolar_images_left and epipolar_images_right.
497
+
498
+ """