cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a3__cp313-cp313-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.
- cars/applications/application.py +14 -6
- cars/applications/application_template.py +22 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +15 -10
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
- cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
- cars/applications/dem_generation/dem_generation_wrappers.py +46 -27
- cars/applications/dem_generation/dichotomic_generation_app.py +6 -3
- cars/applications/dem_generation/rasterization_app.py +15 -5
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_matching/census_mccnn_sgm_app.py +11 -22
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.pyd +0 -0
- cars/applications/dense_matching/disparity_grid_algo.py +26 -32
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +78 -1
- cars/applications/dsm_filling/border_interpolation_app.py +10 -5
- cars/applications/dsm_filling/bulldozer_filling_app.py +14 -7
- cars/applications/dsm_filling/exogenous_filling_app.py +10 -5
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +9 -5
- cars/applications/point_cloud_outlier_removal/small_components_app.py +5 -3
- cars/applications/point_cloud_outlier_removal/statistical_app.py +4 -2
- cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -0
- cars/applications/rasterization/simple_gaussian_app.py +28 -3
- cars/applications/resampling/resampling_algo.py +44 -49
- cars/applications/sparse_matching/sift_app.py +2 -22
- cars/core/geometry/abstract_geometry.py +113 -2
- cars/core/geometry/shareloc_geometry.py +2 -0
- cars/core/inputs.py +15 -0
- cars/core/projection.py +117 -0
- cars/data_structures/cars_dataset.py +7 -5
- cars/orchestrator/cluster/log_wrapper.py +1 -1
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +1 -1
- cars/pipelines/default/default_pipeline.py +46 -26
- cars/pipelines/parameters/advanced_parameters.py +17 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +4 -0
- cars/pipelines/parameters/output_parameters.py +44 -8
- cars/pipelines/parameters/sensor_inputs.py +97 -3
- cars/pipelines/unit/unit_pipeline.py +194 -99
- cars-1.0.0a3.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/METADATA +1 -1
- {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/RECORD +49 -47
- cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
- cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
- cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
- cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
- cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
- cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
- cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
- {cars-1.0.0a2.dist-info → cars-1.0.0a3.dist-info}/WHEEL +0 -0
- {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
|
|
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",
|
|
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.
|
|
155
|
-
poly, roi_epsg, dsm_crs
|
|
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.
|
|
164
|
-
roi_polys, roi_epsg, dsm_crs
|
|
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",
|
|
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.
|
|
166
|
-
poly, roi_epsg, dsm_crs
|
|
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.
|
|
175
|
-
roi_polys, roi_epsg, dsm_crs
|
|
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",
|
|
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.
|
|
174
|
-
poly, roi_epsg, dsm_crs
|
|
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.
|
|
183
|
-
roi_polys, roi_epsg, dsm_crs
|
|
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
|
|
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(
|
|
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
|
|
|
@@ -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
|
|
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":
|
|
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
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
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
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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
|
-
|
|
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,
|
|
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=
|
|
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,
|