cars 1.0.0a2__cp311-cp311-win_amd64.whl → 1.0.0a3__cp311-cp311-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 (53) hide show
  1. cars/applications/application.py +14 -6
  2. cars/applications/application_template.py +22 -0
  3. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +15 -10
  4. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  5. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  6. cars/applications/dem_generation/dem_generation_wrappers.py +46 -27
  7. cars/applications/dem_generation/dichotomic_generation_app.py +6 -3
  8. cars/applications/dem_generation/rasterization_app.py +15 -5
  9. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.dll.a +0 -0
  10. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.pyd +0 -0
  11. cars/applications/dense_matching/census_mccnn_sgm_app.py +11 -22
  12. cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.dll.a +0 -0
  13. cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.pyd +0 -0
  14. cars/applications/dense_matching/disparity_grid_algo.py +26 -32
  15. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  16. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  17. cars/applications/dense_matching/loaders/pandora_loader.py +78 -1
  18. cars/applications/dsm_filling/border_interpolation_app.py +10 -5
  19. cars/applications/dsm_filling/bulldozer_filling_app.py +14 -7
  20. cars/applications/dsm_filling/exogenous_filling_app.py +10 -5
  21. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +9 -5
  22. cars/applications/point_cloud_outlier_removal/small_components_app.py +5 -3
  23. cars/applications/point_cloud_outlier_removal/statistical_app.py +4 -2
  24. cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -0
  25. cars/applications/rasterization/simple_gaussian_app.py +28 -3
  26. cars/applications/resampling/resampling_algo.py +44 -49
  27. cars/applications/sparse_matching/sift_app.py +2 -22
  28. cars/core/geometry/abstract_geometry.py +113 -2
  29. cars/core/geometry/shareloc_geometry.py +2 -0
  30. cars/core/inputs.py +15 -0
  31. cars/core/projection.py +117 -0
  32. cars/data_structures/cars_dataset.py +7 -5
  33. cars/orchestrator/cluster/log_wrapper.py +1 -1
  34. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +1 -1
  35. cars/orchestrator/orchestrator.py +1 -1
  36. cars/pipelines/default/default_pipeline.py +46 -26
  37. cars/pipelines/parameters/advanced_parameters.py +17 -0
  38. cars/pipelines/parameters/advanced_parameters_constants.py +4 -0
  39. cars/pipelines/parameters/output_parameters.py +44 -8
  40. cars/pipelines/parameters/sensor_inputs.py +97 -3
  41. cars/pipelines/unit/unit_pipeline.py +194 -99
  42. cars-1.0.0a3.dist-info/DELVEWHEEL +2 -0
  43. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/METADATA +1 -1
  44. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/RECORD +49 -47
  45. cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
  46. cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
  47. cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
  48. cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
  49. cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
  50. cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
  51. cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
  52. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/WHEEL +0 -0
  53. {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/entry_points.txt +0 -0
@@ -31,6 +31,7 @@ from typing import Dict
31
31
 
32
32
  import numpy as np
33
33
  import pandora
34
+ import rasterio
34
35
  from json_checker import Checker, Or
35
36
  from pandora.check_configuration import (
36
37
  check_pipeline_section,
@@ -40,6 +41,10 @@ from pandora.check_configuration import (
40
41
  )
41
42
  from pandora.img_tools import get_metadata
42
43
  from pandora.state_machine import PandoraMachine
44
+ from rasterio.mask import mask
45
+ from shapely.geometry import mapping
46
+
47
+ from cars.core.projection import polygon_projection
43
48
 
44
49
 
45
50
  class PandoraLoader:
@@ -135,7 +140,7 @@ class PandoraLoader:
135
140
  # read conf
136
141
  with open(conf_file_path, "r", encoding="utf8") as fstream:
137
142
  conf = json.load(fstream)
138
- elif method_name == "census_sgm_default":
143
+ elif method_name in ("census_sgm_default", "auto"):
139
144
  # Use census sgm conf
140
145
  conf_file_path = os.path.join(
141
146
  package_path, "config_census_sgm_default.json"
@@ -300,6 +305,78 @@ class PandoraLoader:
300
305
 
301
306
  return self.pandora_config
302
307
 
308
+ def find_auto_conf(
309
+ self, intersection_poly, land_cover_map, classif_to_config_mapping, epsg
310
+ ):
311
+ """
312
+ Find the configuration that suits the most on the
313
+ land cover map based on the roi
314
+ """
315
+ package_path = os.path.dirname(__file__)
316
+
317
+ # construct the path to the land_cover_map
318
+ if os.path.dirname(land_cover_map) == "":
319
+ land_cover_map_path = os.path.join(package_path, land_cover_map)
320
+ else:
321
+ land_cover_map_path = land_cover_map
322
+
323
+ with rasterio.open(land_cover_map_path) as src:
324
+ # Project the polygon to the right epsg
325
+ if src.crs != epsg:
326
+ poly = polygon_projection(
327
+ intersection_poly, epsg, src.crs.to_epsg()
328
+ )
329
+ else:
330
+ poly = intersection_poly
331
+
332
+ # Use a buffer because the land_cover_map resolution is coarse
333
+ data_land_cover, _ = mask(
334
+ src, [mapping(poly)], crop=True, all_touched=True
335
+ )
336
+
337
+ # Find the most common class in the roi
338
+ data_squeeze = data_land_cover.squeeze()
339
+ valid_data = data_squeeze[data_squeeze != src.nodata]
340
+
341
+ most_common_class = None
342
+ if valid_data.size > 0:
343
+ classes, counts = np.unique(valid_data, return_counts=True)
344
+ max_index = np.argmax(counts)
345
+ most_common_class = classes[max_index]
346
+
347
+ # Construct the path to the classification to configuration mapping
348
+ if os.path.dirname(classif_to_config_mapping) == "":
349
+ conf_file_path = os.path.join(
350
+ package_path, classif_to_config_mapping
351
+ )
352
+ else:
353
+ conf_file_path = classif_to_config_mapping
354
+
355
+ # read conf
356
+ with open(conf_file_path, "r", encoding="utf8") as fstream:
357
+ conf_mapping = json.load(fstream)
358
+
359
+ # Find the configuration that corresponds to the most common class
360
+ corresponding_conf_name = conf_mapping.get(str(most_common_class), None)
361
+
362
+ # If no equivalence has been found, we use the default configuration
363
+ if corresponding_conf_name is None:
364
+ corresponding_conf_name = "census_sgm_default"
365
+
366
+ logging.info(
367
+ "The conf that has been chosen regarding the "
368
+ "world classification map is {}".format(corresponding_conf_name)
369
+ )
370
+
371
+ # We return the corresponding configuration
372
+ json_conf_name = os.path.join(
373
+ package_path, "config_" + corresponding_conf_name + ".json"
374
+ )
375
+ with open(json_conf_name, "r", encoding="utf8") as fstream:
376
+ conf = json.load(fstream)
377
+
378
+ return conf
379
+
303
380
  def check_conf(
304
381
  self,
305
382
  user_cfg,
@@ -31,6 +31,7 @@ import rasterio as rio
31
31
  import scipy
32
32
  import skimage
33
33
  from json_checker import Checker, Or
34
+ from pyproj import CRS
34
35
  from shapely import Polygon
35
36
 
36
37
  from cars.core import inputs, projection
@@ -74,7 +75,11 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
74
75
  # Overload conf
75
76
  overloaded_conf["method"] = conf.get("method", "bulldozer")
76
77
  overloaded_conf["activated"] = conf.get("activated", False)
77
- overloaded_conf["classification"] = conf.get("classification", None)
78
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
79
+ if isinstance(overloaded_conf["classification"], str):
80
+ overloaded_conf["classification"] = [
81
+ overloaded_conf["classification"]
82
+ ]
78
83
  overloaded_conf["component_min_size"] = conf.get(
79
84
  "component_min_size", 5
80
85
  )
@@ -151,8 +156,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
151
156
  roi_polys_outepsg = []
152
157
  for poly in roi_polys:
153
158
  if isinstance(poly, Polygon):
154
- roi_poly_outepsg = projection.polygon_projection(
155
- poly, roi_epsg, dsm_crs.to_epsg()
159
+ roi_poly_outepsg = projection.polygon_projection_crs(
160
+ poly, CRS(roi_epsg), dsm_crs
156
161
  )
157
162
  roi_polys_outepsg.append(roi_poly_outepsg)
158
163
 
@@ -160,8 +165,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
160
165
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
161
166
  )
162
167
  elif isinstance(roi_polys, Polygon):
163
- roi_poly_outepsg = projection.polygon_projection(
164
- roi_polys, roi_epsg, dsm_crs.to_epsg()
168
+ roi_poly_outepsg = projection.polygon_projection_crs(
169
+ roi_polys, CRS(roi_epsg), dsm_crs
165
170
  )
166
171
  roi_raster = rio.features.rasterize(
167
172
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -32,6 +32,7 @@ import rasterio as rio
32
32
  import yaml
33
33
  from bulldozer.pipeline.bulldozer_pipeline import dsm_to_dtm
34
34
  from json_checker import Checker, Or
35
+ from pyproj import CRS
35
36
  from shapely import Polygon
36
37
 
37
38
  from cars.core import inputs, projection
@@ -72,7 +73,13 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
72
73
  # Overload conf
73
74
  overloaded_conf["method"] = conf.get("method", "bulldozer")
74
75
  overloaded_conf["activated"] = conf.get("activated", False)
75
- overloaded_conf["classification"] = conf.get("classification", None)
76
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
77
+
78
+ if isinstance(overloaded_conf["classification"], str):
79
+ overloaded_conf["classification"] = [
80
+ overloaded_conf["classification"]
81
+ ]
82
+
76
83
  overloaded_conf["save_intermediate_data"] = conf.get(
77
84
  "save_intermediate_data", False
78
85
  )
@@ -162,8 +169,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
162
169
  roi_polys_outepsg = []
163
170
  for poly in roi_polys:
164
171
  if isinstance(poly, Polygon):
165
- roi_poly_outepsg = projection.polygon_projection(
166
- poly, roi_epsg, dsm_crs.to_epsg()
172
+ roi_poly_outepsg = projection.polygon_projection_crs(
173
+ poly, CRS(roi_epsg), dsm_crs
167
174
  )
168
175
  roi_polys_outepsg.append(roi_poly_outepsg)
169
176
 
@@ -171,8 +178,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
171
178
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
172
179
  )
173
180
  elif isinstance(roi_polys, Polygon):
174
- roi_poly_outepsg = projection.polygon_projection(
175
- roi_polys, roi_epsg, dsm_crs.to_epsg()
181
+ roi_poly_outepsg = projection.polygon_projection_crs(
182
+ roi_polys, CRS(roi_epsg), dsm_crs
176
183
  )
177
184
  roi_raster = rio.features.rasterize(
178
185
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -211,7 +218,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
211
218
  with rio.open(old_dsm_path, "w", **dsm_meta) as out_dsm:
212
219
  out_dsm.write(dsm, 1)
213
220
 
214
- if classif_file is not None:
221
+ if classif_file is not None and os.path.exists(classif_file):
215
222
  classif_descriptions = inputs.get_descriptions_bands(classif_file)
216
223
  else:
217
224
  classif_descriptions = []
@@ -225,7 +232,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
225
232
  classif[classif_msk == 0] = 0
226
233
  filling_mask = np.logical_and(classif, roi_raster > 0)
227
234
  elif label == "nodata":
228
- if classif_file is not None:
235
+ if classif_file is not None and os.path.exists(classif_file):
229
236
  with rio.open(classif_file) as in_classif:
230
237
  classif_msk = in_classif.read_masks(1)
231
238
  classif = ~classif_msk
@@ -29,6 +29,7 @@ import shutil
29
29
  import numpy as np
30
30
  import rasterio as rio
31
31
  from json_checker import Checker, Or
32
+ from pyproj import CRS
32
33
  from rasterio.enums import Resampling
33
34
  from rasterio.warp import reproject
34
35
  from shapely import Polygon
@@ -73,7 +74,11 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
73
74
  # Overload conf
74
75
  overloaded_conf["method"] = conf.get("method", "bulldozer")
75
76
  overloaded_conf["activated"] = conf.get("activated", False)
76
- overloaded_conf["classification"] = conf.get("classification", None)
77
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
78
+ if isinstance(overloaded_conf["classification"], str):
79
+ overloaded_conf["classification"] = [
80
+ overloaded_conf["classification"]
81
+ ]
77
82
  overloaded_conf["fill_with_geoid"] = conf.get("fill_with_geoid", None)
78
83
  overloaded_conf["interpolation_method"] = conf.get(
79
84
  "interpolation_method", "bilinear"
@@ -170,8 +175,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
170
175
  roi_polys_outepsg = []
171
176
  for poly in roi_polys:
172
177
  if isinstance(poly, Polygon):
173
- roi_poly_outepsg = projection.polygon_projection(
174
- poly, roi_epsg, dsm_crs.to_epsg()
178
+ roi_poly_outepsg = projection.polygon_projection_crs(
179
+ poly, CRS(roi_epsg), dsm_crs
175
180
  )
176
181
  roi_polys_outepsg.append(roi_poly_outepsg)
177
182
 
@@ -179,8 +184,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
179
184
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
180
185
  )
181
186
  elif isinstance(roi_polys, Polygon):
182
- roi_poly_outepsg = projection.polygon_projection(
183
- roi_polys, roi_epsg, dsm_crs.to_epsg()
187
+ roi_poly_outepsg = projection.polygon_projection_crs(
188
+ roi_polys, CRS(roi_epsg), dsm_crs
184
189
  )
185
190
  roi_raster = rio.features.rasterize(
186
191
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -31,7 +31,7 @@ import numpy as np
31
31
 
32
32
  from cars.applications import application_constants
33
33
  from cars.applications.application import Application
34
- from cars.applications.application_template import ApplicationTemplate
34
+ from cars.applications.application_template import ScalingApplicationTemplate
35
35
  from cars.applications.point_cloud_outlier_removal import (
36
36
  outlier_removal_constants as pr_cst,
37
37
  )
@@ -41,7 +41,7 @@ from cars.data_structures import cars_dataset
41
41
 
42
42
 
43
43
  @Application.register("point_cloud_outlier_removal")
44
- class PointCloudOutlierRemoval(ApplicationTemplate, metaclass=ABCMeta):
44
+ class PointCloudOutlierRemoval(ScalingApplicationTemplate, metaclass=ABCMeta):
45
45
  """
46
46
  PointCloudOutlierRemoval
47
47
  """
@@ -49,12 +49,14 @@ class PointCloudOutlierRemoval(ApplicationTemplate, metaclass=ABCMeta):
49
49
  available_applications: Dict = {}
50
50
  default_application = "statistical"
51
51
 
52
- def __new__(cls, conf=None): # pylint: disable=W0613
52
+ def __new__(cls, scaling_coeff, conf=None): # pylint: disable=W0613
53
53
  """
54
54
  Return the required application
55
55
  :raises:
56
56
  - KeyError when the required application is not registered
57
57
 
58
+ :param scaling_coeff: scaling factor for resolution
59
+ :type scaling_coeff: float
58
60
  :param conf: configuration for points removal
59
61
  :return: a application_to_use object
60
62
  """
@@ -95,15 +97,17 @@ class PointCloudOutlierRemoval(ApplicationTemplate, metaclass=ABCMeta):
95
97
  cls.orchestrator = None
96
98
  cls.available_applications[short_name] = cls
97
99
 
98
- def __init__(self, conf=None):
100
+ def __init__(self, scaling_coeff, conf=None):
99
101
  """
100
102
  Init function of PointCloudOutlierRemoval
101
103
 
104
+ :param scaling_coeff: scaling factor for resolution
105
+ :type scaling_coeff: float
102
106
  :param conf: configuration
103
107
  :return: an application_to_use object
104
108
  """
105
109
 
106
- super().__init__(conf=conf)
110
+ super().__init__(scaling_coeff, conf=conf)
107
111
 
108
112
  @abstractmethod
109
113
  def get_on_ground_margin(self, resolution=0.5):
@@ -64,15 +64,17 @@ class SmallComponents(
64
64
 
65
65
  # pylint: disable=too-many-instance-attributes
66
66
 
67
- def __init__(self, conf=None):
67
+ def __init__(self, scaling_coeff, conf=None):
68
68
  """
69
69
  Init function of SmallComponents
70
70
 
71
+ :param scaling_coeff: scaling factor for resolution
72
+ :type scaling_coeff: float
71
73
  :param conf: configuration for points outlier removal
72
74
  :return: an application_to_use object
73
75
  """
74
76
 
75
- super().__init__(conf=conf)
77
+ super().__init__(scaling_coeff, conf=conf)
76
78
 
77
79
  self.used_method = self.used_config["method"]
78
80
 
@@ -131,7 +133,7 @@ class SmallComponents(
131
133
  # pts_connection_dist:
132
134
  # distance to use to consider that two points are connected
133
135
  overloaded_conf["connection_distance"] = conf.get(
134
- "connection_distance", 3.0
136
+ "connection_distance", self.scaling_coeff * 3.0
135
137
  )
136
138
  # nb_pts_threshold:
137
139
  # points clusters that have less than this number of points
@@ -68,15 +68,17 @@ class Statistical(
68
68
 
69
69
  # pylint: disable=too-many-instance-attributes
70
70
 
71
- def __init__(self, conf=None):
71
+ def __init__(self, scaling_coeff, conf=None):
72
72
  """
73
73
  Init function of Statistical
74
74
 
75
+ :param scaling_coeff: scaling factor for resolution
76
+ :type scaling_coeff: float
75
77
  :param conf: configuration for points outlier removal
76
78
  :return: a application_to_use object
77
79
  """
78
80
 
79
- super().__init__(conf=conf)
81
+ super().__init__(scaling_coeff, conf=conf)
80
82
 
81
83
  self.used_method = self.used_config["method"]
82
84
 
@@ -131,6 +131,7 @@ class PointCloudRasterization(ApplicationTemplate, metaclass=ABCMeta):
131
131
  self,
132
132
  point_clouds,
133
133
  epsg,
134
+ output_crs,
134
135
  resolution,
135
136
  orchestrator=None,
136
137
  dsm_file_name=None,
@@ -208,6 +208,7 @@ class SimpleGaussian(
208
208
  self,
209
209
  point_clouds,
210
210
  epsg,
211
+ output_crs,
211
212
  resolution,
212
213
  orchestrator=None,
213
214
  dsm_file_name=None,
@@ -256,6 +257,8 @@ class SimpleGaussian(
256
257
  :type point_clouds: CarsDataset filled with pandas.DataFrame
257
258
  :param epsg: epsg of raster data
258
259
  :type epsg: str
260
+ :param output_crs: output_crs of raster data
261
+ :type output_crs: str
259
262
  :param resolution: resolution of raster data (in target CRS unit)
260
263
  :type resolution: float
261
264
  :param orchestrator: orchestrator used
@@ -267,7 +270,7 @@ class SimpleGaussian(
267
270
  :type color_file_name: str
268
271
  :param mask_file_name: path of color
269
272
  :type mask_file_name: str
270
- :param classif_file_name: path of color
273
+ :param classif_file_name: path of classification
271
274
  :type classif_file_name: str
272
275
  :param performance_map_file_name: path of performance map file
273
276
  :type performance_map_file_name: str
@@ -317,6 +320,27 @@ class SimpleGaussian(
317
320
  # Get if color, mask and stats are saved
318
321
  save_intermediate_data = self.used_config["save_intermediate_data"]
319
322
 
323
+ keep_dir = (
324
+ len(
325
+ list(
326
+ filter(
327
+ lambda x: x is not None,
328
+ [
329
+ weights_file_name,
330
+ color_file_name,
331
+ mask_file_name,
332
+ classif_file_name,
333
+ performance_map_file_name,
334
+ ambiguity_file_name,
335
+ contributing_pair_file_name,
336
+ filling_file_name,
337
+ ],
338
+ )
339
+ )
340
+ )
341
+ > 0
342
+ )
343
+
320
344
  if not self.color_dtype:
321
345
  self.color_dtype = color_dtype
322
346
 
@@ -333,7 +357,7 @@ class SimpleGaussian(
333
357
  if dump_dir is not None:
334
358
  out_dump_dir = dump_dir
335
359
  safe_makedirs(dump_dir)
336
- if not save_intermediate_data:
360
+ if not save_intermediate_data and not keep_dir:
337
361
  self.orchestrator.add_to_clean(dump_dir)
338
362
  else:
339
363
  out_dump_dir = self.orchestrator.out_dir
@@ -512,6 +536,7 @@ class SimpleGaussian(
512
536
  out_classif_file_name = os.path.join(
513
537
  out_dump_dir, "classification.tif"
514
538
  )
539
+
515
540
  if out_classif_file_name is not None:
516
541
  list_computed_layers += ["classif"]
517
542
  self.orchestrator.add_to_save_lists(
@@ -817,7 +842,7 @@ class SimpleGaussian(
817
842
  "driver": "GTiff",
818
843
  "dtype": "float32",
819
844
  "transform": transform,
820
- "crs": "EPSG:{}".format(epsg),
845
+ "crs": output_crs.to_wkt(),
821
846
  "tiled": True,
822
847
  }
823
848
  )
@@ -284,14 +284,10 @@ def resample_image( # noqa: C901
284
284
  (nb_bands, region[3] - region[1], region[2] - region[0]),
285
285
  dtype=np.float32,
286
286
  )
287
- nodata = 0
288
- if nodata is not None or mask is not None:
289
- msk = np.empty(
290
- (nb_bands, region[3] - region[1], region[2] - region[0]),
291
- dtype=np.float32,
292
- )
293
- else:
294
- msk = None
287
+ msk = np.empty(
288
+ (nb_bands, region[3] - region[1], region[2] - region[0]),
289
+ dtype=np.float32,
290
+ )
295
291
 
296
292
  ystart = 0
297
293
  with rio.open(grid["path"]) as grid_reader, rio.open(img) as img_reader:
@@ -513,51 +509,50 @@ def oversampling_func(
513
509
  resamp[:, ystart : ystart + ysize, xstart : xstart + xsize] = block_resamp
514
510
 
515
511
  # create msk
516
- if nodata is not None or mask is not None:
517
- if in_sensor:
518
- # get mask in source geometry
519
- nodata_index = img_as_array == nodata
520
-
521
- if mask is not None:
522
- with rio.open(mask) as msk_reader:
523
- msk_as_array = msk_reader.read(1, window=img_window)
524
- msk_as_array = np.array([msk_as_array] * img_as_array.shape[0])
525
- else:
526
- msk_as_array = np.zeros(img_as_array.shape)
512
+ if in_sensor:
513
+ # get mask in source geometry
514
+ if mask is not None:
515
+ with rio.open(mask) as msk_reader:
516
+ msk_as_array = msk_reader.read(1, window=img_window)
517
+ msk_as_array = np.array([msk_as_array] * img_as_array.shape[0])
518
+ else:
519
+ msk_as_array = np.zeros(img_as_array.shape)
527
520
 
521
+ if nodata is not None:
522
+ nodata_index = img_as_array == nodata
528
523
  msk_as_array[nodata_index] = nodata_msk
529
524
 
530
- # resample mask
531
- block_msk = cresample.grid(
532
- msk_as_array,
533
- grid_as_array,
534
- oversampling,
535
- interpolator=interpolator_mask,
536
- nodata=nodata_msk,
537
- )
525
+ # resample mask
526
+ block_msk = cresample.grid(
527
+ msk_as_array,
528
+ grid_as_array,
529
+ oversampling,
530
+ interpolator=interpolator_mask,
531
+ nodata=nodata_msk,
532
+ )
538
533
 
539
- if interpolator_mask == "bicubic":
540
- block_msk = np.where(
541
- block_msk >= 0.5,
542
- 1,
543
- np.where(block_msk < 0.5, 0, block_msk),
544
- ).astype(int)
545
-
546
- block_msk = block_msk[
547
- ...,
548
- ext_region[1] : ext_region[3] - 1,
549
- ext_region[0] : ext_region[2] - 1,
550
- ]
551
- else:
552
- block_msk = np.full(
553
- (
554
- nb_bands,
555
- block_region[3] - block_region[1],
556
- block_region[2] - block_region[0],
557
- ),
558
- fill_value=nodata_msk,
559
- )
534
+ if interpolator_mask == "bicubic":
535
+ block_msk = np.where(
536
+ block_msk >= 0.5,
537
+ 1,
538
+ np.where(block_msk < 0.5, 0, block_msk),
539
+ ).astype(int)
540
+
541
+ block_msk = block_msk[
542
+ ...,
543
+ ext_region[1] : ext_region[3] - 1,
544
+ ext_region[0] : ext_region[2] - 1,
545
+ ]
546
+ else:
547
+ block_msk = np.full(
548
+ (
549
+ nb_bands,
550
+ block_region[3] - block_region[1],
551
+ block_region[2] - block_region[0],
552
+ ),
553
+ fill_value=nodata_msk,
554
+ )
560
555
 
561
- msk[:, ystart : ystart + ysize, xstart : xstart + xsize] = block_msk
556
+ msk[:, ystart : ystart + ysize, xstart : xstart + xsize] = block_msk
562
557
 
563
558
  return resamp, msk
@@ -224,7 +224,7 @@ class Sift(SparseMatching, short_name=["sift"]):
224
224
  "sift_matching_threshold": And(float, lambda x: x > 0),
225
225
  "sift_n_octave": And(int, lambda x: x > 0),
226
226
  "sift_n_scale_per_octave": And(int, lambda x: x > 0),
227
- "sift_peak_threshold": Or(float, None),
227
+ "sift_peak_threshold": Or(float, int),
228
228
  "sift_edge_threshold": float,
229
229
  "sift_magnification": And(float, lambda x: x > 0),
230
230
  "sift_window_size": And(int, lambda x: x > 0),
@@ -514,26 +514,6 @@ class Sift(SparseMatching, short_name=["sift"]):
514
514
  epipolar_disparity_map_left.attributes.update(
515
515
  epipolar_image_left.attributes
516
516
  )
517
- # check sift_peak_threshold with image type
518
- # only if sift_peak_threshold is None
519
- tmp_sift_peak_threshold = self.sift_peak_threshold
520
- if not self.sift_peak_threshold:
521
- logging.info("The sift_peak_threshold is set to auto-mode.")
522
- # sift_peak_threshold is None or not specified
523
- # check input type
524
- if np.issubdtype(
525
- epipolar_disparity_map_left.attributes["image_type"],
526
- np.uint8,
527
- ):
528
- tmp_sift_peak_threshold = 1
529
- else:
530
- tmp_sift_peak_threshold = 20
531
- logging.info(
532
- "The sift_peak_threshold will be set to {}.".format(
533
- tmp_sift_peak_threshold
534
- )
535
- )
536
- self.sift_peak_threshold = tmp_sift_peak_threshold
537
517
 
538
518
  # Save disparity maps
539
519
  if self.save_intermediate_data:
@@ -628,7 +608,7 @@ class Sift(SparseMatching, short_name=["sift"]):
628
608
  matching_threshold=self.sift_matching_threshold,
629
609
  n_octave=self.sift_n_octave,
630
610
  n_scale_per_octave=self.sift_n_scale_per_octave,
631
- peak_threshold=tmp_sift_peak_threshold,
611
+ peak_threshold=self.sift_peak_threshold,
632
612
  edge_threshold=self.sift_edge_threshold,
633
613
  magnification=self.sift_magnification,
634
614
  window_size=self.sift_window_size,