cars 1.0.0a2__cp312-cp312-win_amd64.whl → 1.0.0a3__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.
- 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.cp312-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp312-win_amd64.pyd +0 -0
- cars/applications/dense_matching/census_mccnn_sgm_app.py +11 -22
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-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
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
# See the License for the specific language governing permissions and
|
|
19
19
|
# limitations under the License.
|
|
20
20
|
#
|
|
21
|
+
|
|
22
|
+
# pylint: disable=C0302
|
|
23
|
+
|
|
21
24
|
"""
|
|
22
25
|
this module contains the abstract geometry class to use in the
|
|
23
26
|
geometry plugins
|
|
@@ -50,7 +53,7 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
50
53
|
|
|
51
54
|
available_plugins: Dict = {}
|
|
52
55
|
|
|
53
|
-
def __new__(cls, geometry_plugin_conf=None, **kwargs):
|
|
56
|
+
def __new__(cls, geometry_plugin_conf=None, scaling_coeff=1, **kwargs):
|
|
54
57
|
"""
|
|
55
58
|
Return the required plugin
|
|
56
59
|
:raises:
|
|
@@ -59,6 +62,8 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
59
62
|
:param geometry_plugin_conf: plugin name or plugin configuration
|
|
60
63
|
to instantiate
|
|
61
64
|
:type geometry_plugin_conf: str or dict
|
|
65
|
+
:param scaling_coeff: scaling factor for resolution
|
|
66
|
+
:type scaling_coeff: float
|
|
62
67
|
:return: a geometry_plugin object
|
|
63
68
|
"""
|
|
64
69
|
if geometry_plugin_conf is not None:
|
|
@@ -100,9 +105,12 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
100
105
|
dem=None,
|
|
101
106
|
geoid=None,
|
|
102
107
|
default_alt=None,
|
|
108
|
+
scaling_coeff=1,
|
|
103
109
|
**kwargs,
|
|
104
110
|
):
|
|
105
111
|
|
|
112
|
+
self.scaling_coeff = scaling_coeff
|
|
113
|
+
|
|
106
114
|
config = self.check_conf(geometry_plugin_conf)
|
|
107
115
|
|
|
108
116
|
self.plugin_name = config["plugin_name"]
|
|
@@ -160,7 +168,9 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
160
168
|
"plugin_name", "SharelocGeometry"
|
|
161
169
|
)
|
|
162
170
|
overloaded_conf["interpolator"] = conf.get("interpolator", "cubic")
|
|
163
|
-
overloaded_conf["dem_roi_margin"] = conf.get(
|
|
171
|
+
overloaded_conf["dem_roi_margin"] = conf.get(
|
|
172
|
+
"dem_roi_margin", float(self.scaling_coeff * 0.012)
|
|
173
|
+
)
|
|
164
174
|
|
|
165
175
|
geometry_schema = {
|
|
166
176
|
"plugin_name": str,
|
|
@@ -617,6 +627,55 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
617
627
|
:return: Latitude, Longitude, Altitude coordinates list as a numpy array
|
|
618
628
|
"""
|
|
619
629
|
|
|
630
|
+
def safe_direct_loc(
|
|
631
|
+
self,
|
|
632
|
+
sensor,
|
|
633
|
+
geomodel,
|
|
634
|
+
x_coord: np.array,
|
|
635
|
+
y_coord: np.array,
|
|
636
|
+
z_coord: np.array = None,
|
|
637
|
+
) -> np.ndarray:
|
|
638
|
+
"""
|
|
639
|
+
For a given image points list, compute the latitudes,
|
|
640
|
+
longitudes, altitudes
|
|
641
|
+
|
|
642
|
+
Advice: to be sure, use x,y,z list inputs only
|
|
643
|
+
|
|
644
|
+
:param sensor: path to sensor image
|
|
645
|
+
:param geomodel: path and attributes for geomodel
|
|
646
|
+
:param x_coord: X Coordinates list in input image sensor
|
|
647
|
+
:param y_coord: Y Coordinate list in input image sensor
|
|
648
|
+
:param z_coord: Z Altitude list coordinate to take the image
|
|
649
|
+
:return: Latitude, Longitude, Altitude coordinates list as a numpy array
|
|
650
|
+
"""
|
|
651
|
+
if len(x_coord) > 0:
|
|
652
|
+
ground_points = self.direct_loc(
|
|
653
|
+
sensor,
|
|
654
|
+
geomodel,
|
|
655
|
+
x_coord,
|
|
656
|
+
y_coord,
|
|
657
|
+
z_coord,
|
|
658
|
+
)
|
|
659
|
+
else:
|
|
660
|
+
logging.warning("Direct loc function launched on empty list")
|
|
661
|
+
return []
|
|
662
|
+
if z_coord is None:
|
|
663
|
+
status = np.any(np.isnan(ground_points), axis=0)
|
|
664
|
+
if sum(status) > 0:
|
|
665
|
+
logging.warning(
|
|
666
|
+
"{} errors have been detected on direct "
|
|
667
|
+
"loc and will be re-launched".format(sum(status))
|
|
668
|
+
)
|
|
669
|
+
ground_points_retry = self.direct_loc(
|
|
670
|
+
sensor,
|
|
671
|
+
geomodel,
|
|
672
|
+
x_coord[status],
|
|
673
|
+
y_coord[status],
|
|
674
|
+
np.array([0]),
|
|
675
|
+
)
|
|
676
|
+
ground_points[:, status] = ground_points_retry
|
|
677
|
+
return ground_points
|
|
678
|
+
|
|
620
679
|
@abstractmethod
|
|
621
680
|
def inverse_loc(
|
|
622
681
|
self,
|
|
@@ -640,6 +699,58 @@ class AbstractGeometry(metaclass=ABCMeta):
|
|
|
640
699
|
:return: X / Y / Z Coordinates list in input image as a numpy array
|
|
641
700
|
"""
|
|
642
701
|
|
|
702
|
+
def safe_inverse_loc(
|
|
703
|
+
self,
|
|
704
|
+
sensor,
|
|
705
|
+
geomodel,
|
|
706
|
+
lat_coord: np.array,
|
|
707
|
+
lon_coord: np.array,
|
|
708
|
+
z_coord: np.array = None,
|
|
709
|
+
) -> np.ndarray:
|
|
710
|
+
"""
|
|
711
|
+
For a given image points list, compute the latitudes,
|
|
712
|
+
longitudes, altitudes
|
|
713
|
+
|
|
714
|
+
Advice: to be sure, use x,y,z list inputs only
|
|
715
|
+
|
|
716
|
+
:param sensor: path to sensor image
|
|
717
|
+
:param geomodel: path and attributes for geomodel
|
|
718
|
+
:param lat_coord: latitute Coordinate list
|
|
719
|
+
:param lon_coord: longitude Coordinates list
|
|
720
|
+
:param z_coord: Z Altitude list
|
|
721
|
+
:return: X / Y / Z Coordinates list in input image as a numpy array
|
|
722
|
+
"""
|
|
723
|
+
if len(lat_coord) > 0:
|
|
724
|
+
image_points = self.inverse_loc(
|
|
725
|
+
sensor,
|
|
726
|
+
geomodel,
|
|
727
|
+
lat_coord,
|
|
728
|
+
lon_coord,
|
|
729
|
+
z_coord,
|
|
730
|
+
)
|
|
731
|
+
image_points = np.array(image_points)
|
|
732
|
+
else:
|
|
733
|
+
logging.warning("Inverse loc function launched on empty list")
|
|
734
|
+
return [], [], []
|
|
735
|
+
if z_coord is None:
|
|
736
|
+
image_points = np.array(image_points)
|
|
737
|
+
status = np.any(np.isnan(image_points), axis=0)
|
|
738
|
+
if sum(status) > 0:
|
|
739
|
+
logging.warning(
|
|
740
|
+
"{} errors have been detected on inverse "
|
|
741
|
+
"loc and will be re-launched".format(sum(status))
|
|
742
|
+
)
|
|
743
|
+
image_points_retry = self.inverse_loc(
|
|
744
|
+
sensor,
|
|
745
|
+
geomodel,
|
|
746
|
+
lat_coord[status],
|
|
747
|
+
lon_coord[status],
|
|
748
|
+
np.array([self.default_alt]),
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
image_points[:, status] = image_points_retry
|
|
752
|
+
return image_points[0], image_points[1], image_points[2]
|
|
753
|
+
|
|
643
754
|
def image_envelope(
|
|
644
755
|
self,
|
|
645
756
|
sensor,
|
|
@@ -63,6 +63,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
63
63
|
geoid=None,
|
|
64
64
|
default_alt=None,
|
|
65
65
|
pairs_for_roi=None,
|
|
66
|
+
scaling_coeff=1,
|
|
66
67
|
):
|
|
67
68
|
|
|
68
69
|
super().__init__(
|
|
@@ -71,6 +72,7 @@ class SharelocGeometry(AbstractGeometry):
|
|
|
71
72
|
geoid=geoid,
|
|
72
73
|
default_alt=default_alt,
|
|
73
74
|
pairs_for_roi=pairs_for_roi,
|
|
75
|
+
scaling_coeff=scaling_coeff,
|
|
74
76
|
)
|
|
75
77
|
|
|
76
78
|
self.dem_roi = None
|
cars/core/inputs.py
CHANGED
|
@@ -36,6 +36,7 @@ import numpy as np
|
|
|
36
36
|
import rasterio as rio
|
|
37
37
|
import xarray as xr
|
|
38
38
|
from json_checker import Checker
|
|
39
|
+
from pyproj import CRS
|
|
39
40
|
from rasterio.warp import Resampling, calculate_default_transform, reproject
|
|
40
41
|
from rasterio.windows import Window
|
|
41
42
|
from shapely.geometry import shape
|
|
@@ -378,6 +379,20 @@ def rasterio_get_epsg(raster_file: str) -> int:
|
|
|
378
379
|
return epsg
|
|
379
380
|
|
|
380
381
|
|
|
382
|
+
def rasterio_get_crs(raster_file: str) -> CRS:
|
|
383
|
+
"""
|
|
384
|
+
Get the crs of an image file
|
|
385
|
+
|
|
386
|
+
:param raster_file: Image file
|
|
387
|
+
:return: The crs of the given image
|
|
388
|
+
"""
|
|
389
|
+
crs = None
|
|
390
|
+
with rio.open(raster_file, "r") as descriptor:
|
|
391
|
+
crs = descriptor.crs
|
|
392
|
+
|
|
393
|
+
return crs
|
|
394
|
+
|
|
395
|
+
|
|
381
396
|
def rasterio_transform_epsg(file_name, new_epsg):
|
|
382
397
|
"""
|
|
383
398
|
Modify epsg of raster file
|
cars/core/projection.py
CHANGED
|
@@ -182,6 +182,22 @@ def polygon_projection(poly: Polygon, epsg_in: int, epsg_out: int) -> Polygon:
|
|
|
182
182
|
return poly
|
|
183
183
|
|
|
184
184
|
|
|
185
|
+
def polygon_projection_crs(poly: Polygon, crs_in: CRS, crs_out: CRS) -> Polygon:
|
|
186
|
+
"""
|
|
187
|
+
Projects a polygon from an initial crs to another
|
|
188
|
+
|
|
189
|
+
:param poly: poly to project
|
|
190
|
+
:param crs_in: initial crs
|
|
191
|
+
:param crs_out: final crs
|
|
192
|
+
:return: The polygon in the final projection
|
|
193
|
+
"""
|
|
194
|
+
# Project polygon between CRS (keep always_xy for compatibility)
|
|
195
|
+
project = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
|
|
196
|
+
poly = transform(project.transform, poly)
|
|
197
|
+
|
|
198
|
+
return poly
|
|
199
|
+
|
|
200
|
+
|
|
185
201
|
def geo_to_ecef(
|
|
186
202
|
lat: np.ndarray, lon: np.ndarray, alt: np.ndarray
|
|
187
203
|
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
@@ -351,6 +367,27 @@ def point_cloud_conversion(
|
|
|
351
367
|
return cloud_in
|
|
352
368
|
|
|
353
369
|
|
|
370
|
+
def point_cloud_conversion_crs(
|
|
371
|
+
cloud_in: np.ndarray, crs_in: int, crs_out: int
|
|
372
|
+
) -> np.ndarray:
|
|
373
|
+
"""
|
|
374
|
+
Convert a point cloud from a SRS to another one.
|
|
375
|
+
|
|
376
|
+
:param cloud_in: cloud to project
|
|
377
|
+
:param crs_in: crs of the input SRS
|
|
378
|
+
:param crs_out: crs of the output SRS
|
|
379
|
+
:return: Projected point cloud
|
|
380
|
+
"""
|
|
381
|
+
# Project point cloud between CRS (keep always_xy for compatibility)
|
|
382
|
+
cloud_in = np.array(cloud_in).T
|
|
383
|
+
transformer = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
|
|
384
|
+
|
|
385
|
+
cloud_in = transformer.transform(*cloud_in)
|
|
386
|
+
cloud_in = np.array(cloud_in).T
|
|
387
|
+
|
|
388
|
+
return cloud_in
|
|
389
|
+
|
|
390
|
+
|
|
354
391
|
def get_xyz_np_array_from_dataset(
|
|
355
392
|
cloud_in: xr.Dataset,
|
|
356
393
|
) -> Tuple[np.array, List[int]]:
|
|
@@ -721,3 +758,83 @@ def get_ground_angles(
|
|
|
721
758
|
convergence_angle = np.degrees(utils.angle_vectors(enu1, enu2))
|
|
722
759
|
|
|
723
760
|
return az1, elev_angle1, az2, elev_angle2, convergence_angle
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def get_output_crs(epsg, out_conf):
|
|
764
|
+
"""
|
|
765
|
+
Détermine le CRS de sortie en fonction de la config.
|
|
766
|
+
"""
|
|
767
|
+
geoid = out_conf.get("geoid")
|
|
768
|
+
crs_epsg = CRS(f"EPSG:{epsg}")
|
|
769
|
+
|
|
770
|
+
if len(crs_epsg.axis_info) != 2:
|
|
771
|
+
return crs_epsg # the user himself set a 3D CRS
|
|
772
|
+
|
|
773
|
+
geoid_is_path = isinstance(geoid, str)
|
|
774
|
+
|
|
775
|
+
if geoid_is_path: # user given geoid
|
|
776
|
+
vepsg = guess_vcrs_from_file_name(geoid)
|
|
777
|
+
if vepsg is None:
|
|
778
|
+
custom_wkt = (
|
|
779
|
+
'VERTCRS["Custom geoid height",'
|
|
780
|
+
+ f' VDATUM["Custom geoid model (file: {geoid})"],'
|
|
781
|
+
+ " CS[vertical,1],"
|
|
782
|
+
+ ' AXIS["gravity-related height (h)", up],'
|
|
783
|
+
+ ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
|
|
784
|
+
"]"
|
|
785
|
+
)
|
|
786
|
+
logging.warning(
|
|
787
|
+
"Could not create a known VCRS from the geoid file."
|
|
788
|
+
)
|
|
789
|
+
return CRS.from_wkt(
|
|
790
|
+
f'COMPOUNDCRS["EPSG:{epsg} + Custom geoid height",'
|
|
791
|
+
f" {crs_epsg.to_wkt()},"
|
|
792
|
+
f" {custom_wkt}]"
|
|
793
|
+
)
|
|
794
|
+
# a vepsg was found using the geoid file
|
|
795
|
+
return CRS(f"EPSG:{epsg}+{vepsg}")
|
|
796
|
+
|
|
797
|
+
if geoid: # geoid == True
|
|
798
|
+
return CRS(f"EPSG:{epsg}+5773")
|
|
799
|
+
|
|
800
|
+
# geoid == False
|
|
801
|
+
wgs84_wkt = (
|
|
802
|
+
'VERTCRS["WGS 84 ellipsoidal height",'
|
|
803
|
+
+ ' VDATUM["WGS 84"],'
|
|
804
|
+
+ " CS[vertical,1],"
|
|
805
|
+
+ ' AXIS["ellipsoidal height (h)", up],'
|
|
806
|
+
+ ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
|
|
807
|
+
"]"
|
|
808
|
+
)
|
|
809
|
+
logging.warning("The output VCRS is WGS84.")
|
|
810
|
+
|
|
811
|
+
return CRS.from_wkt(
|
|
812
|
+
f'COMPOUNDCRS["EPSG:{epsg} + WGS84 ellipsoidal height",'
|
|
813
|
+
f" {crs_epsg.to_wkt()},"
|
|
814
|
+
f" {wgs84_wkt}]"
|
|
815
|
+
)
|
|
816
|
+
|
|
817
|
+
|
|
818
|
+
def guess_vcrs_from_file_name(filepath):
|
|
819
|
+
"""
|
|
820
|
+
Tries to detect the geoid's EPSG from the file name
|
|
821
|
+
"""
|
|
822
|
+
filename = os.path.basename(filepath).lower()
|
|
823
|
+
|
|
824
|
+
known_models = {
|
|
825
|
+
"egm96": 5773, # EGM96 height
|
|
826
|
+
"egm_96": 5773, # alias
|
|
827
|
+
"egm 96": 5773, # alias
|
|
828
|
+
"egm1996": 5773, # alias
|
|
829
|
+
"egm08": 3855, # EGM2008 height
|
|
830
|
+
"egm_08": 3855, # alias
|
|
831
|
+
"egm 08": 3855, # alias
|
|
832
|
+
"egm2008": 3855, # alias
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
for key, vepsg in known_models.items():
|
|
836
|
+
if key in filename:
|
|
837
|
+
return vepsg
|
|
838
|
+
|
|
839
|
+
# aucun match connu
|
|
840
|
+
return None
|
|
@@ -38,6 +38,7 @@ from typing import Dict
|
|
|
38
38
|
# Third party imports
|
|
39
39
|
import numpy as np
|
|
40
40
|
import pandas
|
|
41
|
+
import pyproj
|
|
41
42
|
import rasterio as rio
|
|
42
43
|
import xarray as xr
|
|
43
44
|
from rasterio.profiles import DefaultGTiffProfile
|
|
@@ -1327,12 +1328,13 @@ def dict_profile_to_rio_profile(dict_profile: Dict) -> Dict:
|
|
|
1327
1328
|
crs = None
|
|
1328
1329
|
if "crs" in dict_profile:
|
|
1329
1330
|
if dict_profile["crs"] is not None:
|
|
1330
|
-
if
|
|
1331
|
-
crs
|
|
1332
|
-
|
|
1333
|
-
|
|
1331
|
+
if (
|
|
1332
|
+
isinstance(dict_profile["crs"], str)
|
|
1333
|
+
and "EPSG:" in dict_profile["crs"]
|
|
1334
|
+
):
|
|
1335
|
+
crs = pyproj.CRS(dict_profile["crs"].replace("EPSG:", ""))
|
|
1334
1336
|
else:
|
|
1335
|
-
crs =
|
|
1337
|
+
crs = pyproj.CRS(dict_profile["crs"])
|
|
1336
1338
|
|
|
1337
1339
|
rio_profile["crs"] = crs
|
|
1338
1340
|
rio_profile["transform"] = transform
|
|
@@ -120,9 +120,6 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
120
120
|
# Check conf inputs
|
|
121
121
|
inputs = self.check_inputs(conf[INPUTS], config_dir=config_dir)
|
|
122
122
|
|
|
123
|
-
# Check conf output
|
|
124
|
-
output = self.check_output(conf[OUTPUT])
|
|
125
|
-
|
|
126
123
|
# Check advanced parameters
|
|
127
124
|
# TODO static method in the base class
|
|
128
125
|
(
|
|
@@ -132,10 +129,19 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
132
129
|
self.geom_plugin_without_dem_and_geoid,
|
|
133
130
|
self.geom_plugin_with_dem_and_geoid,
|
|
134
131
|
_,
|
|
132
|
+
self.scaling_coeff,
|
|
133
|
+
_,
|
|
134
|
+
_,
|
|
135
135
|
) = advanced_parameters.check_advanced_parameters(
|
|
136
136
|
inputs, conf.get(ADVANCED, {}), check_epipolar_a_priori=True
|
|
137
137
|
)
|
|
138
138
|
|
|
139
|
+
# Check conf output
|
|
140
|
+
(
|
|
141
|
+
output,
|
|
142
|
+
self.scaling_coeff,
|
|
143
|
+
) = self.check_output(conf[OUTPUT], self.scaling_coeff)
|
|
144
|
+
|
|
139
145
|
resolutions = advanced["epipolar_resolutions"]
|
|
140
146
|
if isinstance(resolutions, int):
|
|
141
147
|
resolutions = [resolutions]
|
|
@@ -254,20 +260,6 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
254
260
|
# (except the last one)
|
|
255
261
|
self.used_conf[key][OUTPUT][out_cst.PRODUCT_LEVEL] = "dsm"
|
|
256
262
|
|
|
257
|
-
# The idea is to calculate the less possible things
|
|
258
|
-
# So we override those parameters
|
|
259
|
-
self.used_conf[key][ADVANCED][adv_cst.MERGING] = False
|
|
260
|
-
self.used_conf[key][ADVANCED][adv_cst.PHASING] = None
|
|
261
|
-
self.used_conf[key][OUTPUT][out_cst.SAVE_BY_PAIR] = False
|
|
262
|
-
|
|
263
|
-
aux_items = self.used_conf[key][OUTPUT][
|
|
264
|
-
out_cst.AUXILIARY
|
|
265
|
-
].items()
|
|
266
|
-
for aux_key, _ in aux_items:
|
|
267
|
-
if aux_key not in ("dem_min", "dem_max", "dem_median"):
|
|
268
|
-
self.used_conf[key][OUTPUT][out_cst.AUXILIARY][
|
|
269
|
-
aux_key
|
|
270
|
-
] = False
|
|
271
263
|
else:
|
|
272
264
|
# If save_intermediate_data is true,
|
|
273
265
|
# we save the depth_maps also to debug
|
|
@@ -563,17 +555,19 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
563
555
|
return output_config
|
|
564
556
|
|
|
565
557
|
@staticmethod
|
|
566
|
-
def check_output(conf):
|
|
558
|
+
def check_output(conf, scaling_coeff):
|
|
567
559
|
"""
|
|
568
560
|
Check the output given
|
|
569
561
|
|
|
570
562
|
:param conf: configuration of output
|
|
571
563
|
:type conf: dict
|
|
564
|
+
:param scaling_coeff: scaling factor for resolution
|
|
565
|
+
:type scaling_coeff: float
|
|
572
566
|
|
|
573
567
|
:return overloader output
|
|
574
568
|
:rtype : dict
|
|
575
569
|
"""
|
|
576
|
-
return output_parameters.check_output_parameters(conf)
|
|
570
|
+
return output_parameters.check_output_parameters(conf, scaling_coeff)
|
|
577
571
|
|
|
578
572
|
def merge_resolution_conf(self, config1, config2):
|
|
579
573
|
"""
|
|
@@ -629,6 +623,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
629
623
|
:param conf: configuration of applications
|
|
630
624
|
:type conf: dict
|
|
631
625
|
"""
|
|
626
|
+
scaling_coeff = self.scaling_coeff
|
|
632
627
|
|
|
633
628
|
# Check if all specified applications are used
|
|
634
629
|
# Application in terrain_application are note used in
|
|
@@ -727,7 +722,9 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
727
722
|
if self.sensors_in_inputs:
|
|
728
723
|
# Epipolar grid generation
|
|
729
724
|
self.epipolar_grid_generation_application = Application(
|
|
730
|
-
"grid_generation",
|
|
725
|
+
"grid_generation",
|
|
726
|
+
cfg=used_conf.get("grid_generation", {}),
|
|
727
|
+
scaling_coeff=scaling_coeff,
|
|
731
728
|
)
|
|
732
729
|
used_conf["grid_generation"] = (
|
|
733
730
|
self.epipolar_grid_generation_application.get_conf()
|
|
@@ -736,7 +733,9 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
736
733
|
# image resampling
|
|
737
734
|
|
|
738
735
|
self.resampling_application = Application(
|
|
739
|
-
"resampling",
|
|
736
|
+
"resampling",
|
|
737
|
+
cfg=used_conf.get("resampling", {}),
|
|
738
|
+
scaling_coeff=scaling_coeff,
|
|
740
739
|
)
|
|
741
740
|
used_conf["resampling"] = self.resampling_application.get_conf()
|
|
742
741
|
|
|
@@ -758,10 +757,13 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
758
757
|
self.ground_truth_reprojection = Application(
|
|
759
758
|
"ground_truth_reprojection",
|
|
760
759
|
cfg=used_conf.get("ground_truth_reprojection", {}),
|
|
760
|
+
scaling_coeff=scaling_coeff,
|
|
761
761
|
)
|
|
762
762
|
# holes detection
|
|
763
763
|
self.hole_detection_app = Application(
|
|
764
|
-
"hole_detection",
|
|
764
|
+
"hole_detection",
|
|
765
|
+
cfg=used_conf.get("hole_detection", {}),
|
|
766
|
+
scaling_coeff=scaling_coeff,
|
|
765
767
|
)
|
|
766
768
|
used_conf["hole_detection"] = self.hole_detection_app.get_conf()
|
|
767
769
|
|
|
@@ -772,6 +774,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
772
774
|
"dense_match_filling.1",
|
|
773
775
|
{"method": "plane"},
|
|
774
776
|
),
|
|
777
|
+
scaling_coeff=scaling_coeff,
|
|
775
778
|
)
|
|
776
779
|
used_conf["dense_match_filling.1"] = (
|
|
777
780
|
self.dense_match_filling_1.get_conf()
|
|
@@ -784,6 +787,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
784
787
|
"dense_match_filling.2",
|
|
785
788
|
{"method": "zero_padding"},
|
|
786
789
|
),
|
|
790
|
+
scaling_coeff=scaling_coeff,
|
|
787
791
|
)
|
|
788
792
|
used_conf["dense_match_filling.2"] = (
|
|
789
793
|
self.dense_match_filling_2.get_conf()
|
|
@@ -793,6 +797,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
793
797
|
self.sparse_mtch_sift_app = Application(
|
|
794
798
|
"sparse_matching",
|
|
795
799
|
cfg=used_conf.get("sparse_matching.sift", {"method": "sift"}),
|
|
800
|
+
scaling_coeff=scaling_coeff,
|
|
796
801
|
)
|
|
797
802
|
used_conf["sparse_matching.sift"] = (
|
|
798
803
|
self.sparse_mtch_sift_app.get_conf()
|
|
@@ -820,7 +825,9 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
820
825
|
):
|
|
821
826
|
dense_matching_config["performance_map_method"] = "risk"
|
|
822
827
|
self.dense_matching_app = Application(
|
|
823
|
-
"dense_matching",
|
|
828
|
+
"dense_matching",
|
|
829
|
+
cfg=dense_matching_config,
|
|
830
|
+
scaling_coeff=scaling_coeff,
|
|
824
831
|
)
|
|
825
832
|
used_conf["dense_matching"] = self.dense_matching_app.get_conf()
|
|
826
833
|
|
|
@@ -832,7 +839,9 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
832
839
|
|
|
833
840
|
# Triangulation
|
|
834
841
|
self.triangulation_application = Application(
|
|
835
|
-
"triangulation",
|
|
842
|
+
"triangulation",
|
|
843
|
+
cfg=used_conf.get("triangulation", {}),
|
|
844
|
+
scaling_coeff=scaling_coeff,
|
|
836
845
|
)
|
|
837
846
|
used_conf["triangulation"] = (
|
|
838
847
|
self.triangulation_application.get_conf()
|
|
@@ -840,7 +849,9 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
840
849
|
|
|
841
850
|
# MNT generation
|
|
842
851
|
self.dem_generation_application = Application(
|
|
843
|
-
"dem_generation",
|
|
852
|
+
"dem_generation",
|
|
853
|
+
cfg=used_conf.get("dem_generation", {}),
|
|
854
|
+
scaling_coeff=scaling_coeff,
|
|
844
855
|
)
|
|
845
856
|
|
|
846
857
|
height_margin = None
|
|
@@ -867,6 +878,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
867
878
|
"point_cloud_outlier_removal.1",
|
|
868
879
|
{"method": "small_components"},
|
|
869
880
|
),
|
|
881
|
+
scaling_coeff=scaling_coeff,
|
|
870
882
|
)
|
|
871
883
|
|
|
872
884
|
connection_val = None
|
|
@@ -894,6 +906,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
894
906
|
"point_cloud_outlier_removal.2",
|
|
895
907
|
{"method": "statistical"},
|
|
896
908
|
),
|
|
909
|
+
scaling_coeff=scaling_coeff,
|
|
897
910
|
)
|
|
898
911
|
used_conf["point_cloud_outlier_removal.2"] = (
|
|
899
912
|
self.pc_outlier_removal_2_app.get_conf()
|
|
@@ -905,6 +918,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
905
918
|
self.pc_denoising_application = Application(
|
|
906
919
|
"pc_denoising",
|
|
907
920
|
cfg=used_conf.get("pc_denoising", {"method": "none"}),
|
|
921
|
+
scaling_coeff=scaling_coeff,
|
|
908
922
|
)
|
|
909
923
|
used_conf["pc_denoising"] = self.pc_denoising_application.get_conf()
|
|
910
924
|
|
|
@@ -914,6 +928,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
914
928
|
self.rasterization_application = Application(
|
|
915
929
|
"point_cloud_rasterization",
|
|
916
930
|
cfg=used_conf.get("point_cloud_rasterization", {}),
|
|
931
|
+
scaling_coeff=scaling_coeff,
|
|
917
932
|
)
|
|
918
933
|
used_conf["point_cloud_rasterization"] = (
|
|
919
934
|
self.rasterization_application.get_conf()
|
|
@@ -925,6 +940,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
925
940
|
"dsm_filling.1",
|
|
926
941
|
{"method": "exogenous_filling"},
|
|
927
942
|
),
|
|
943
|
+
scaling_coeff=scaling_coeff,
|
|
928
944
|
)
|
|
929
945
|
used_conf["dsm_filling.1"] = (
|
|
930
946
|
self.dsm_filling_1_application.get_conf()
|
|
@@ -947,13 +963,16 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
947
963
|
"dsm_filling.3",
|
|
948
964
|
{"method": "border_interpolation"},
|
|
949
965
|
),
|
|
966
|
+
scaling_coeff=scaling_coeff,
|
|
950
967
|
)
|
|
951
968
|
used_conf["dsm_filling.3"] = (
|
|
952
969
|
self.dsm_filling_3_application.get_conf()
|
|
953
970
|
)
|
|
954
971
|
# Auxiliary filling
|
|
955
972
|
self.auxiliary_filling_application = Application(
|
|
956
|
-
"auxiliary_filling",
|
|
973
|
+
"auxiliary_filling",
|
|
974
|
+
cfg=conf.get("auxiliary_filling", {}),
|
|
975
|
+
scaling_coeff=scaling_coeff,
|
|
957
976
|
)
|
|
958
977
|
used_conf["auxiliary_filling"] = (
|
|
959
978
|
self.auxiliary_filling_application.get_conf()
|
|
@@ -965,6 +984,7 @@ class DefaultPipeline(PipelineTemplate):
|
|
|
965
984
|
self.pc_fusion_application = Application(
|
|
966
985
|
"point_cloud_fusion",
|
|
967
986
|
cfg=used_conf.get("point_cloud_fusion", {}),
|
|
987
|
+
scaling_coeff=scaling_coeff,
|
|
968
988
|
)
|
|
969
989
|
used_conf["point_cloud_fusion"] = (
|
|
970
990
|
self.pc_fusion_application.get_conf()
|