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.
- cars/__init__.py +74 -0
- cars/applications/__init__.py +37 -0
- cars/applications/application.py +117 -0
- cars/applications/application_constants.py +29 -0
- cars/applications/application_template.py +146 -0
- cars/applications/auxiliary_filling/__init__.py +29 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +104 -0
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -0
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
- cars/applications/dem_generation/__init__.py +30 -0
- cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
- cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
- cars/applications/dem_generation/bulldozer_dem_app.py +655 -0
- cars/applications/dem_generation/bulldozer_memory.py +55 -0
- cars/applications/dem_generation/dem_generation_algo.py +107 -0
- cars/applications/dem_generation/dem_generation_constants.py +32 -0
- cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
- cars/applications/dense_match_filling/__init__.py +30 -0
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
- cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
- cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
- cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
- cars/applications/dense_match_filling/zero_padding_app.py +302 -0
- cars/applications/dense_matching/__init__.py +30 -0
- cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
- cars/applications/dense_matching/census_mccnn_sgm_app.py +1460 -0
- cars/applications/dense_matching/cpp/__init__.py +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-312-i386-linux-gnu.so +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
- cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
- cars/applications/dense_matching/cpp/meson.build +9 -0
- cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
- cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
- cars/applications/dense_matching/dense_matching_algo.py +401 -0
- cars/applications/dense_matching/dense_matching_constants.py +89 -0
- cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
- cars/applications/dense_matching/disparity_grid_algo.py +588 -0
- cars/applications/dense_matching/loaders/__init__.py +23 -0
- cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
- cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
- cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
- cars/applications/dsm_filling/__init__.py +32 -0
- cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
- cars/applications/dsm_filling/border_interpolation_app.py +270 -0
- cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
- cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
- cars/applications/dsm_filling/exogenous_filling_app.py +333 -0
- cars/applications/grid_generation/__init__.py +30 -0
- cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
- cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
- cars/applications/grid_generation/grid_correction_app.py +496 -0
- cars/applications/grid_generation/grid_generation_algo.py +388 -0
- cars/applications/grid_generation/grid_generation_constants.py +46 -0
- cars/applications/grid_generation/transform_grid.py +88 -0
- cars/applications/ground_truth_reprojection/__init__.py +30 -0
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
- cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
- cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
- cars/applications/point_cloud_outlier_removal/small_components_app.py +527 -0
- cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -0
- cars/applications/rasterization/__init__.py +30 -0
- cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
- cars/applications/rasterization/rasterization_algo.py +534 -0
- cars/applications/rasterization/rasterization_constants.py +38 -0
- cars/applications/rasterization/rasterization_wrappers.py +634 -0
- cars/applications/rasterization/simple_gaussian_app.py +1152 -0
- cars/applications/resampling/__init__.py +28 -0
- cars/applications/resampling/abstract_resampling_app.py +187 -0
- cars/applications/resampling/bicubic_resampling_app.py +762 -0
- cars/applications/resampling/resampling_algo.py +614 -0
- cars/applications/resampling/resampling_constants.py +36 -0
- cars/applications/resampling/resampling_wrappers.py +309 -0
- cars/applications/sparse_matching/__init__.py +30 -0
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
- cars/applications/sparse_matching/sift_app.py +735 -0
- cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
- cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
- cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
- cars/applications/triangulation/__init__.py +32 -0
- cars/applications/triangulation/abstract_triangulation_app.py +227 -0
- cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +371 -0
- cars/applications/triangulation/triangulation_constants.py +38 -0
- cars/applications/triangulation/triangulation_wrappers.py +259 -0
- cars/bundleadjustment.py +757 -0
- cars/cars.py +177 -0
- cars/conf/__init__.py +23 -0
- cars/conf/geoid/egm96.grd +0 -0
- cars/conf/geoid/egm96.grd.hdr +15 -0
- cars/conf/input_parameters.py +156 -0
- cars/conf/mask_cst.py +35 -0
- cars/core/__init__.py +23 -0
- cars/core/cars_logging.py +402 -0
- cars/core/constants.py +191 -0
- cars/core/constants_disparity.py +50 -0
- cars/core/datasets.py +140 -0
- cars/core/geometry/__init__.py +27 -0
- cars/core/geometry/abstract_geometry.py +1119 -0
- cars/core/geometry/shareloc_geometry.py +598 -0
- cars/core/inputs.py +568 -0
- cars/core/outputs.py +176 -0
- cars/core/preprocessing.py +722 -0
- cars/core/projection.py +843 -0
- cars/core/roi_tools.py +215 -0
- cars/core/tiling.py +774 -0
- cars/core/utils.py +164 -0
- cars/data_structures/__init__.py +23 -0
- cars/data_structures/cars_dataset.py +1541 -0
- cars/data_structures/cars_dict.py +74 -0
- cars/data_structures/corresponding_tiles_tools.py +186 -0
- cars/data_structures/dataframe_converter.py +185 -0
- cars/data_structures/format_transformation.py +297 -0
- cars/devibrate.py +689 -0
- cars/extractroi.py +264 -0
- cars/orchestrator/__init__.py +23 -0
- cars/orchestrator/achievement_tracker.py +125 -0
- cars/orchestrator/cluster/__init__.py +37 -0
- cars/orchestrator/cluster/abstract_cluster.py +244 -0
- cars/orchestrator/cluster/abstract_dask_cluster.py +375 -0
- cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
- cars/orchestrator/cluster/dask_config/README.md +94 -0
- cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
- cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
- cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
- cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
- cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
- cars/orchestrator/cluster/local_dask_cluster.py +116 -0
- cars/orchestrator/cluster/log_wrapper.py +1075 -0
- cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
- cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
- cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
- cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
- cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +873 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
- cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
- cars/orchestrator/cluster/sequential_cluster.py +139 -0
- cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
- cars/orchestrator/orchestrator.py +905 -0
- cars/orchestrator/orchestrator_constants.py +29 -0
- cars/orchestrator/registry/__init__.py +23 -0
- cars/orchestrator/registry/abstract_registry.py +143 -0
- cars/orchestrator/registry/compute_registry.py +106 -0
- cars/orchestrator/registry/id_generator.py +116 -0
- cars/orchestrator/registry/replacer_registry.py +213 -0
- cars/orchestrator/registry/saver_registry.py +363 -0
- cars/orchestrator/registry/unseen_registry.py +118 -0
- cars/orchestrator/tiles_profiler.py +279 -0
- cars/pipelines/__init__.py +26 -0
- cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
- cars/pipelines/conf_resolution/conf_first_resolution.yaml +2 -0
- cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
- cars/pipelines/default/__init__.py +26 -0
- cars/pipelines/default/default_pipeline.py +786 -0
- cars/pipelines/parameters/__init__.py +0 -0
- cars/pipelines/parameters/advanced_parameters.py +417 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -0
- cars/pipelines/parameters/dsm_inputs.py +918 -0
- cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
- cars/pipelines/parameters/output_constants.py +52 -0
- cars/pipelines/parameters/output_parameters.py +454 -0
- cars/pipelines/parameters/sensor_inputs.py +842 -0
- cars/pipelines/parameters/sensor_inputs_constants.py +49 -0
- cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
- cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
- cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
- cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
- cars/pipelines/pipeline.py +119 -0
- cars/pipelines/pipeline_constants.py +31 -0
- cars/pipelines/pipeline_template.py +139 -0
- cars/pipelines/unit/__init__.py +26 -0
- cars/pipelines/unit/unit_pipeline.py +2850 -0
- cars/starter.py +167 -0
- cars-1.0.0rc1.dist-info/METADATA +292 -0
- cars-1.0.0rc1.dist-info/RECORD +200 -0
- cars-1.0.0rc1.dist-info/WHEEL +6 -0
- cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
|
@@ -0,0 +1,735 @@
|
|
|
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 dense_matching application class.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# pylint: disable= C0302
|
|
26
|
+
|
|
27
|
+
# Standard imports
|
|
28
|
+
import logging
|
|
29
|
+
import os
|
|
30
|
+
from typing import Dict, Tuple
|
|
31
|
+
|
|
32
|
+
# Third party imports
|
|
33
|
+
import numpy as np
|
|
34
|
+
import pandas
|
|
35
|
+
import xarray as xr
|
|
36
|
+
from json_checker import And, Checker, Or
|
|
37
|
+
|
|
38
|
+
import cars.applications.sparse_matching.sparse_matching_constants as sm_cst
|
|
39
|
+
import cars.orchestrator.orchestrator as ocht
|
|
40
|
+
from cars.applications import application_constants
|
|
41
|
+
|
|
42
|
+
# CARS imports
|
|
43
|
+
from cars.applications.sparse_matching import sparse_matching_algo
|
|
44
|
+
from cars.applications.sparse_matching.abstract_sparse_matching_app import (
|
|
45
|
+
SparseMatching,
|
|
46
|
+
)
|
|
47
|
+
from cars.core import constants as cst
|
|
48
|
+
from cars.core.utils import safe_makedirs
|
|
49
|
+
from cars.data_structures import cars_dataset
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class Sift(SparseMatching, short_name=["sift"]):
|
|
53
|
+
"""
|
|
54
|
+
SparseMatching
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
# pylint: disable=too-many-instance-attributes
|
|
58
|
+
|
|
59
|
+
def __init__(self, conf=None):
|
|
60
|
+
"""
|
|
61
|
+
Init function of SparseMatching
|
|
62
|
+
|
|
63
|
+
:param conf: configuration for matching
|
|
64
|
+
:return: a application_to_use object
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
super().__init__(conf=conf)
|
|
68
|
+
|
|
69
|
+
# check conf
|
|
70
|
+
self.used_method = self.used_config["method"]
|
|
71
|
+
self.disparity_margin = self.used_config["disparity_margin"]
|
|
72
|
+
self.elevation_delta_lower_bound = self.used_config[
|
|
73
|
+
"elevation_delta_lower_bound"
|
|
74
|
+
]
|
|
75
|
+
self.elevation_delta_upper_bound = self.used_config[
|
|
76
|
+
"elevation_delta_upper_bound"
|
|
77
|
+
]
|
|
78
|
+
self.strip_margin = self.used_config["strip_margin"]
|
|
79
|
+
self.epipolar_error_upper_bound = self.used_config[
|
|
80
|
+
"epipolar_error_upper_bound"
|
|
81
|
+
]
|
|
82
|
+
self.epipolar_error_maximum_bias = self.used_config[
|
|
83
|
+
"epipolar_error_maximum_bias"
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
# minimum number of matches to continue with
|
|
87
|
+
self.minimum_nb_matches = self.used_config["minimum_nb_matches"]
|
|
88
|
+
|
|
89
|
+
# sifts
|
|
90
|
+
self.sift_matching_threshold = self.used_config[
|
|
91
|
+
"sift_matching_threshold"
|
|
92
|
+
]
|
|
93
|
+
self.sift_n_octave = self.used_config["sift_n_octave"]
|
|
94
|
+
self.sift_n_scale_per_octave = self.used_config[
|
|
95
|
+
"sift_n_scale_per_octave"
|
|
96
|
+
]
|
|
97
|
+
self.sift_peak_threshold = self.used_config["sift_peak_threshold"]
|
|
98
|
+
self.sift_edge_threshold = self.used_config["sift_edge_threshold"]
|
|
99
|
+
self.sift_magnification = self.used_config["sift_magnification"]
|
|
100
|
+
self.sift_window_size = self.used_config["sift_window_size"]
|
|
101
|
+
self.sift_back_matching = self.used_config["sift_back_matching"]
|
|
102
|
+
self.match_filter_knn = self.used_config["match_filter_knn"]
|
|
103
|
+
self.match_filter_constant = self.used_config["match_filter_constant"]
|
|
104
|
+
self.match_filter_mean_factor = self.used_config[
|
|
105
|
+
"match_filter_mean_factor"
|
|
106
|
+
]
|
|
107
|
+
self.match_filter_dev_factor = self.used_config[
|
|
108
|
+
"match_filter_dev_factor"
|
|
109
|
+
]
|
|
110
|
+
self.decimation_factor = self.used_config["decimation_factor"]
|
|
111
|
+
self.used_band = self.used_config["used_band"]
|
|
112
|
+
|
|
113
|
+
# Saving files
|
|
114
|
+
self.save_intermediate_data = self.used_config["save_intermediate_data"]
|
|
115
|
+
|
|
116
|
+
self.disparity_bounds_estimation = self.used_config[
|
|
117
|
+
"disparity_bounds_estimation"
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
# Init orchestrator
|
|
121
|
+
self.orchestrator = None
|
|
122
|
+
|
|
123
|
+
def check_conf(self, conf):
|
|
124
|
+
"""
|
|
125
|
+
Check configuration
|
|
126
|
+
|
|
127
|
+
:param conf: configuration to check
|
|
128
|
+
:type conf: dict
|
|
129
|
+
|
|
130
|
+
:return: overloaded configuration
|
|
131
|
+
:rtype: dict
|
|
132
|
+
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
# init conf
|
|
136
|
+
if conf is not None:
|
|
137
|
+
overloaded_conf = conf.copy()
|
|
138
|
+
else:
|
|
139
|
+
conf = {}
|
|
140
|
+
overloaded_conf = {}
|
|
141
|
+
|
|
142
|
+
# Overload conf
|
|
143
|
+
overloaded_conf["method"] = conf.get("method", "sift")
|
|
144
|
+
overloaded_conf["disparity_margin"] = conf.get("disparity_margin", 0.02)
|
|
145
|
+
overloaded_conf["elevation_delta_lower_bound"] = conf.get(
|
|
146
|
+
"elevation_delta_lower_bound", None
|
|
147
|
+
)
|
|
148
|
+
overloaded_conf["decimation_factor"] = conf.get("decimation_factor", 30)
|
|
149
|
+
overloaded_conf["elevation_delta_upper_bound"] = conf.get(
|
|
150
|
+
"elevation_delta_upper_bound", None
|
|
151
|
+
)
|
|
152
|
+
overloaded_conf["strip_margin"] = conf.get("strip_margin", 10)
|
|
153
|
+
overloaded_conf["epipolar_error_upper_bound"] = conf.get(
|
|
154
|
+
"epipolar_error_upper_bound", 10.0
|
|
155
|
+
)
|
|
156
|
+
overloaded_conf["epipolar_error_maximum_bias"] = conf.get(
|
|
157
|
+
"epipolar_error_maximum_bias", 50.0
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# minimum number of matches to continue with
|
|
161
|
+
overloaded_conf["minimum_nb_matches"] = conf.get(
|
|
162
|
+
"minimum_nb_matches", 90
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# sifts params
|
|
166
|
+
overloaded_conf["sift_matching_threshold"] = conf.get(
|
|
167
|
+
"sift_matching_threshold", 0.7
|
|
168
|
+
)
|
|
169
|
+
overloaded_conf["sift_n_octave"] = conf.get("sift_n_octave", 8)
|
|
170
|
+
overloaded_conf["sift_n_scale_per_octave"] = conf.get(
|
|
171
|
+
"sift_n_scale_per_octave", 3
|
|
172
|
+
)
|
|
173
|
+
overloaded_conf["sift_peak_threshold"] = conf.get(
|
|
174
|
+
"sift_peak_threshold", 4.0
|
|
175
|
+
)
|
|
176
|
+
overloaded_conf["sift_edge_threshold"] = conf.get(
|
|
177
|
+
"sift_edge_threshold", 10.0
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
overloaded_conf["sift_magnification"] = conf.get(
|
|
181
|
+
"sift_magnification", 7.0
|
|
182
|
+
)
|
|
183
|
+
overloaded_conf["sift_window_size"] = conf.get("sift_window_size", 2)
|
|
184
|
+
overloaded_conf["sift_back_matching"] = conf.get(
|
|
185
|
+
"sift_back_matching", True
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
overloaded_conf["match_filter_knn"] = conf.get("match_filter_knn", 25)
|
|
189
|
+
|
|
190
|
+
overloaded_conf["match_filter_constant"] = conf.get(
|
|
191
|
+
"match_filter_constant", 0.0
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
overloaded_conf["match_filter_mean_factor"] = conf.get(
|
|
195
|
+
"match_filter_mean_factor", 1.3
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
overloaded_conf["match_filter_dev_factor"] = conf.get(
|
|
199
|
+
"match_filter_dev_factor", 3.0
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
overloaded_conf["used_band"] = conf.get("used_band", "b0")
|
|
203
|
+
|
|
204
|
+
# Saving files
|
|
205
|
+
overloaded_conf["save_intermediate_data"] = conf.get(
|
|
206
|
+
"save_intermediate_data", False
|
|
207
|
+
)
|
|
208
|
+
self.save_intermediate_data = overloaded_conf["save_intermediate_data"]
|
|
209
|
+
|
|
210
|
+
# confidence filtering parameters
|
|
211
|
+
overloaded_conf["disparity_bounds_estimation"] = conf.get(
|
|
212
|
+
"disparity_bounds_estimation", {}
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
sparse_matching_schema = {
|
|
216
|
+
"method": str,
|
|
217
|
+
"disparity_margin": float,
|
|
218
|
+
"minimum_nb_matches": And(int, lambda x: x > 0),
|
|
219
|
+
"elevation_delta_lower_bound": Or(int, float, None),
|
|
220
|
+
"elevation_delta_upper_bound": Or(int, float, None),
|
|
221
|
+
"strip_margin": And(int, lambda x: x > 0),
|
|
222
|
+
"epipolar_error_upper_bound": And(float, lambda x: x > 0),
|
|
223
|
+
"epipolar_error_maximum_bias": And(float, lambda x: x >= 0),
|
|
224
|
+
"sift_matching_threshold": And(float, lambda x: x > 0),
|
|
225
|
+
"sift_n_octave": And(int, lambda x: x > 0),
|
|
226
|
+
"sift_n_scale_per_octave": And(int, lambda x: x > 0),
|
|
227
|
+
"sift_peak_threshold": Or(float, int),
|
|
228
|
+
"sift_edge_threshold": float,
|
|
229
|
+
"sift_magnification": And(float, lambda x: x > 0),
|
|
230
|
+
"sift_window_size": And(int, lambda x: x > 0),
|
|
231
|
+
"decimation_factor": And(int, lambda x: x > 0),
|
|
232
|
+
"sift_back_matching": bool,
|
|
233
|
+
"match_filter_knn": int,
|
|
234
|
+
"match_filter_constant": Or(int, float),
|
|
235
|
+
"match_filter_mean_factor": Or(int, float),
|
|
236
|
+
"match_filter_dev_factor": Or(int, float),
|
|
237
|
+
"used_band": str,
|
|
238
|
+
"save_intermediate_data": bool,
|
|
239
|
+
"disparity_bounds_estimation": dict,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# Check conf
|
|
243
|
+
checker = Checker(sparse_matching_schema)
|
|
244
|
+
checker.validate(overloaded_conf)
|
|
245
|
+
|
|
246
|
+
self.check_conf_disparity_bounds_estimation(overloaded_conf)
|
|
247
|
+
|
|
248
|
+
# Check consistency between bounds for elevation delta
|
|
249
|
+
elevation_delta_lower_bound = overloaded_conf[
|
|
250
|
+
"elevation_delta_lower_bound"
|
|
251
|
+
]
|
|
252
|
+
elevation_delta_upper_bound = overloaded_conf[
|
|
253
|
+
"elevation_delta_upper_bound"
|
|
254
|
+
]
|
|
255
|
+
if None not in (
|
|
256
|
+
elevation_delta_lower_bound,
|
|
257
|
+
elevation_delta_upper_bound,
|
|
258
|
+
):
|
|
259
|
+
if elevation_delta_lower_bound > elevation_delta_upper_bound:
|
|
260
|
+
raise ValueError(
|
|
261
|
+
"Upper bound must be bigger than "
|
|
262
|
+
"lower bound for expected elevation delta"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
return overloaded_conf
|
|
266
|
+
|
|
267
|
+
def get_required_bands(self):
|
|
268
|
+
"""
|
|
269
|
+
Get bands required by this application
|
|
270
|
+
|
|
271
|
+
:return: required bands for left and right image
|
|
272
|
+
:rtype: dict
|
|
273
|
+
"""
|
|
274
|
+
required_bands = {}
|
|
275
|
+
required_bands["left"] = [self.used_band]
|
|
276
|
+
required_bands["right"] = [self.used_band]
|
|
277
|
+
return required_bands
|
|
278
|
+
|
|
279
|
+
def check_conf_disparity_bounds_estimation(self, overloaded_conf):
|
|
280
|
+
"""
|
|
281
|
+
Check the disparity bounds estimation conf
|
|
282
|
+
"""
|
|
283
|
+
overloaded_conf["disparity_bounds_estimation"]["activated"] = (
|
|
284
|
+
overloaded_conf["disparity_bounds_estimation"].get(
|
|
285
|
+
"activated", True
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
overloaded_conf["disparity_bounds_estimation"]["percentile"] = (
|
|
289
|
+
overloaded_conf["disparity_bounds_estimation"].get("percentile", 1)
|
|
290
|
+
)
|
|
291
|
+
overloaded_conf["disparity_bounds_estimation"]["lower_margin"] = (
|
|
292
|
+
overloaded_conf["disparity_bounds_estimation"].get(
|
|
293
|
+
"lower_margin", 500
|
|
294
|
+
)
|
|
295
|
+
)
|
|
296
|
+
overloaded_conf["disparity_bounds_estimation"]["upper_margin"] = (
|
|
297
|
+
overloaded_conf["disparity_bounds_estimation"].get(
|
|
298
|
+
"upper_margin", 1000
|
|
299
|
+
)
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
disparity_bounds_estimation_schema = {
|
|
303
|
+
"activated": bool,
|
|
304
|
+
"percentile": Or(int, float),
|
|
305
|
+
"upper_margin": int,
|
|
306
|
+
"lower_margin": int,
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
checker_disparity_bounds_estimation_schema = Checker(
|
|
310
|
+
disparity_bounds_estimation_schema
|
|
311
|
+
)
|
|
312
|
+
checker_disparity_bounds_estimation_schema.validate(
|
|
313
|
+
overloaded_conf["disparity_bounds_estimation"]
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
def get_save_matches(self):
|
|
317
|
+
"""
|
|
318
|
+
Get save_matches parameter
|
|
319
|
+
|
|
320
|
+
:return: true is save_matches activated
|
|
321
|
+
:rtype: bool
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
return self.save_intermediate_data
|
|
325
|
+
|
|
326
|
+
def get_disparity_margin(self):
|
|
327
|
+
"""
|
|
328
|
+
Get disparity margin corresponding to sparse matches
|
|
329
|
+
|
|
330
|
+
:return: margin in percent
|
|
331
|
+
|
|
332
|
+
"""
|
|
333
|
+
return self.disparity_margin
|
|
334
|
+
|
|
335
|
+
def get_strip_margin(self):
|
|
336
|
+
"""
|
|
337
|
+
Get strip margin corresponding to sparse matches
|
|
338
|
+
|
|
339
|
+
:return: margin in percent
|
|
340
|
+
|
|
341
|
+
"""
|
|
342
|
+
return self.strip_margin
|
|
343
|
+
|
|
344
|
+
def get_epipolar_error_upper_bound(self):
|
|
345
|
+
"""
|
|
346
|
+
Get epipolar error upper bound corresponding to sparse matches
|
|
347
|
+
|
|
348
|
+
:return: margin
|
|
349
|
+
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
return self.epipolar_error_upper_bound
|
|
353
|
+
|
|
354
|
+
def get_minimum_nb_matches(self):
|
|
355
|
+
"""
|
|
356
|
+
Get minimum_nb_matches :
|
|
357
|
+
get the minimum number of matches
|
|
358
|
+
|
|
359
|
+
:return: minimum_nb_matches
|
|
360
|
+
|
|
361
|
+
"""
|
|
362
|
+
|
|
363
|
+
return self.minimum_nb_matches
|
|
364
|
+
|
|
365
|
+
def get_epipolar_error_maximum_bias(self):
|
|
366
|
+
"""
|
|
367
|
+
Get epipolar error maximum bias corresponding to sparse matches
|
|
368
|
+
|
|
369
|
+
:return: margin
|
|
370
|
+
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
return self.epipolar_error_maximum_bias
|
|
374
|
+
|
|
375
|
+
def get_match_filter_knn(self):
|
|
376
|
+
"""
|
|
377
|
+
Get match_filter_knn :
|
|
378
|
+
number of neighboors used to measure isolation of matches
|
|
379
|
+
|
|
380
|
+
:return: match_filter_knn
|
|
381
|
+
|
|
382
|
+
"""
|
|
383
|
+
return self.match_filter_knn
|
|
384
|
+
|
|
385
|
+
def get_match_filter_constant(self):
|
|
386
|
+
"""
|
|
387
|
+
Get get_match_filter_constant :
|
|
388
|
+
constant in the formula to compute threshold of outliers
|
|
389
|
+
|
|
390
|
+
:return: match_filter_constant
|
|
391
|
+
|
|
392
|
+
"""
|
|
393
|
+
return self.match_filter_constant
|
|
394
|
+
|
|
395
|
+
def get_match_filter_mean_factor(self):
|
|
396
|
+
"""
|
|
397
|
+
Get match_filter_mean_factor :
|
|
398
|
+
factor of mean in the formula
|
|
399
|
+
to compute threshold of outliers
|
|
400
|
+
|
|
401
|
+
:return: match_filter_mean_factor
|
|
402
|
+
|
|
403
|
+
"""
|
|
404
|
+
return self.match_filter_mean_factor
|
|
405
|
+
|
|
406
|
+
def get_match_filter_dev_factor(self):
|
|
407
|
+
"""
|
|
408
|
+
Get match_filter_dev_factor :
|
|
409
|
+
factor of deviation in the formula
|
|
410
|
+
to compute threshold of outliers
|
|
411
|
+
|
|
412
|
+
:return: match_filter_dev_factor
|
|
413
|
+
|
|
414
|
+
"""
|
|
415
|
+
return self.match_filter_dev_factor
|
|
416
|
+
|
|
417
|
+
def get_decimation_factor(self):
|
|
418
|
+
"""
|
|
419
|
+
Get decimation_factor
|
|
420
|
+
|
|
421
|
+
:return: decimation_factor
|
|
422
|
+
|
|
423
|
+
"""
|
|
424
|
+
return self.decimation_factor
|
|
425
|
+
|
|
426
|
+
def set_decimation_factor(self, value):
|
|
427
|
+
"""
|
|
428
|
+
set decimation_factor
|
|
429
|
+
|
|
430
|
+
"""
|
|
431
|
+
self.decimation_factor = value
|
|
432
|
+
|
|
433
|
+
def run( # pylint: disable=too-many-positional-arguments
|
|
434
|
+
self,
|
|
435
|
+
epipolar_image_left,
|
|
436
|
+
epipolar_image_right,
|
|
437
|
+
disp_to_alt_ratio,
|
|
438
|
+
orchestrator=None,
|
|
439
|
+
pair_folder=None,
|
|
440
|
+
pair_key="PAIR_0",
|
|
441
|
+
classif_bands_to_mask=None,
|
|
442
|
+
):
|
|
443
|
+
"""
|
|
444
|
+
Run Matching application.
|
|
445
|
+
|
|
446
|
+
Create left and right CarsDataset filled with pandas.DataFrame ,
|
|
447
|
+
corresponding to epipolar 2D disparities, on the same geometry
|
|
448
|
+
that epipolar_image_left and epipolar_image_right.
|
|
449
|
+
|
|
450
|
+
:param epipolar_image_left: tiled left epipolar. CarsDataset contains:
|
|
451
|
+
|
|
452
|
+
- N x M Delayed tiles \
|
|
453
|
+
Each tile will be a future xarray Dataset containing:
|
|
454
|
+
|
|
455
|
+
- data with keys : "im", "msk", "texture"
|
|
456
|
+
- attrs with keys: "margins" with "disp_min" and "disp_max"
|
|
457
|
+
"transform", "crs", "valid_pixels", "no_data_mask",
|
|
458
|
+
"no_data_img"
|
|
459
|
+
- attributes containing:
|
|
460
|
+
"largest_epipolar_region","opt_epipolar_tile_size"
|
|
461
|
+
:type epipolar_image_left: CarsDataset
|
|
462
|
+
:param epipolar_image_right: tiled right epipolar.CarsDataset contains:
|
|
463
|
+
|
|
464
|
+
- N x M Delayed tiles \
|
|
465
|
+
Each tile will be a future xarray Dataset containing:
|
|
466
|
+
|
|
467
|
+
- data with keys : "im", "msk", "texture"
|
|
468
|
+
- attrs with keys: "margins" with "disp_min" and "disp_max"\
|
|
469
|
+
"transform", "crs", "valid_pixels", "no_data_mask",\
|
|
470
|
+
"no_data_img"
|
|
471
|
+
- attributes containing:"largest_epipolar_region", \
|
|
472
|
+
"opt_epipolar_tile_size"
|
|
473
|
+
:type epipolar_image_right: CarsDataset
|
|
474
|
+
:param disp_to_alt_ratio: disp to alti ratio
|
|
475
|
+
:type disp_to_alt_ratio: float
|
|
476
|
+
:param orchestrator: orchestrator used
|
|
477
|
+
:param pair_folder: folder used for current pair
|
|
478
|
+
:type pair_folder: str
|
|
479
|
+
:param pair_key: pair key id
|
|
480
|
+
:type pair_key: str
|
|
481
|
+
:param classif_bands_to_mask: bands from classif to mask
|
|
482
|
+
:type classif_bands_to_mask: list of str / int
|
|
483
|
+
|
|
484
|
+
:return left matches, right matches. Each CarsDataset contains:
|
|
485
|
+
|
|
486
|
+
- N x M Delayed tiles \
|
|
487
|
+
Each tile will be a future pandas DataFrame containing:
|
|
488
|
+
- data : (L, 4) shape matches
|
|
489
|
+
- attributes containing "disp_lower_bound", "disp_upper_bound",\
|
|
490
|
+
"elevation_delta_lower_bound","elevation_delta_upper_bound"
|
|
491
|
+
|
|
492
|
+
:rtype: Tuple(CarsDataset, CarsDataset)
|
|
493
|
+
"""
|
|
494
|
+
# Default orchestrator
|
|
495
|
+
if orchestrator is None:
|
|
496
|
+
# Create default sequential orchestrator for current application
|
|
497
|
+
# be awere, no out_json will be shared between orchestrators
|
|
498
|
+
# No files saved
|
|
499
|
+
self.orchestrator = ocht.Orchestrator(
|
|
500
|
+
orchestrator_conf={"mode": "sequential"}
|
|
501
|
+
)
|
|
502
|
+
else:
|
|
503
|
+
self.orchestrator = orchestrator
|
|
504
|
+
|
|
505
|
+
if pair_folder is None:
|
|
506
|
+
pair_folder = os.path.join(self.orchestrator.out_dir, "tmp")
|
|
507
|
+
|
|
508
|
+
if epipolar_image_left.dataset_type == "arrays":
|
|
509
|
+
# Create CarsDataset
|
|
510
|
+
# Epipolar_disparity
|
|
511
|
+
epipolar_disparity_map_left = cars_dataset.CarsDataset(
|
|
512
|
+
"points", name="sparse_matching_" + pair_key
|
|
513
|
+
)
|
|
514
|
+
epipolar_disparity_map_left.create_empty_copy(epipolar_image_left)
|
|
515
|
+
|
|
516
|
+
# Update attributes to get epipolar info
|
|
517
|
+
epipolar_disparity_map_left.attributes.update(
|
|
518
|
+
epipolar_image_left.attributes
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
# Save disparity maps
|
|
522
|
+
if self.save_intermediate_data:
|
|
523
|
+
safe_makedirs(pair_folder)
|
|
524
|
+
|
|
525
|
+
self.orchestrator.add_to_save_lists(
|
|
526
|
+
os.path.join(pair_folder, "epi_matches_left"),
|
|
527
|
+
None,
|
|
528
|
+
epipolar_disparity_map_left,
|
|
529
|
+
cars_ds_name="epi_matches_left",
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Compute disparity range
|
|
533
|
+
if self.elevation_delta_lower_bound is None:
|
|
534
|
+
disp_upper_bound = np.inf
|
|
535
|
+
else:
|
|
536
|
+
disp_upper_bound = (
|
|
537
|
+
-self.elevation_delta_lower_bound / disp_to_alt_ratio
|
|
538
|
+
)
|
|
539
|
+
if self.elevation_delta_upper_bound is None:
|
|
540
|
+
disp_lower_bound = -np.inf
|
|
541
|
+
else:
|
|
542
|
+
disp_lower_bound = (
|
|
543
|
+
-self.elevation_delta_upper_bound / disp_to_alt_ratio
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
attributes = {
|
|
547
|
+
"disp_lower_bound": disp_lower_bound,
|
|
548
|
+
"disp_upper_bound": disp_upper_bound,
|
|
549
|
+
"elevation_delta_lower_bound": self.elevation_delta_lower_bound,
|
|
550
|
+
"elevation_delta_upper_bound": self.elevation_delta_upper_bound,
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
epipolar_disparity_map_left.attributes.update(attributes)
|
|
554
|
+
|
|
555
|
+
# Get saving infos in order to save tiles when they are computed
|
|
556
|
+
[saving_info_left] = self.orchestrator.get_saving_infos(
|
|
557
|
+
[epipolar_disparity_map_left]
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
# Update orchestrator out_json
|
|
561
|
+
updating_infos = {
|
|
562
|
+
application_constants.APPLICATION_TAG: {
|
|
563
|
+
sm_cst.SPARSE_MATCHING_RUN_TAG: {
|
|
564
|
+
pair_key: {
|
|
565
|
+
sm_cst.DISP_LOWER_BOUND: disp_lower_bound,
|
|
566
|
+
sm_cst.DISP_UPPER_BOUND: disp_upper_bound,
|
|
567
|
+
},
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
orchestrator.update_out_info(updating_infos)
|
|
572
|
+
logging.info(
|
|
573
|
+
"Generate disparity: Number tiles: {}".format(
|
|
574
|
+
epipolar_disparity_map_left.shape[1]
|
|
575
|
+
* epipolar_disparity_map_left.shape[0]
|
|
576
|
+
)
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
# Add to replace list so tiles will be readable at the same time
|
|
580
|
+
self.orchestrator.add_to_replace_lists(
|
|
581
|
+
epipolar_disparity_map_left, cars_ds_name="epi_matches_left"
|
|
582
|
+
)
|
|
583
|
+
# Generate disparity maps
|
|
584
|
+
total_nb_band_sift = epipolar_disparity_map_left.shape[0]
|
|
585
|
+
|
|
586
|
+
step = int(np.round(100 / self.decimation_factor))
|
|
587
|
+
|
|
588
|
+
if total_nb_band_sift in (1, 2):
|
|
589
|
+
step = 1
|
|
590
|
+
elif total_nb_band_sift == 3:
|
|
591
|
+
step = 2
|
|
592
|
+
|
|
593
|
+
for row in range(0, total_nb_band_sift, step):
|
|
594
|
+
# initialize list of matches
|
|
595
|
+
full_saving_info_left = ocht.update_saving_infos(
|
|
596
|
+
saving_info_left, row=row, col=0
|
|
597
|
+
)
|
|
598
|
+
# Compute matches
|
|
599
|
+
if type(None) not in (
|
|
600
|
+
type(epipolar_image_left[row, 0]),
|
|
601
|
+
type(epipolar_image_right[row, 0]),
|
|
602
|
+
):
|
|
603
|
+
(
|
|
604
|
+
epipolar_disparity_map_left[row, 0]
|
|
605
|
+
) = self.orchestrator.cluster.create_task(
|
|
606
|
+
compute_matches_wrapper, nout=1
|
|
607
|
+
)(
|
|
608
|
+
epipolar_image_left[row, 0],
|
|
609
|
+
epipolar_image_right[row, 0],
|
|
610
|
+
used_band=self.used_band,
|
|
611
|
+
matching_threshold=self.sift_matching_threshold,
|
|
612
|
+
n_octave=self.sift_n_octave,
|
|
613
|
+
n_scale_per_octave=self.sift_n_scale_per_octave,
|
|
614
|
+
peak_threshold=self.sift_peak_threshold,
|
|
615
|
+
edge_threshold=self.sift_edge_threshold,
|
|
616
|
+
magnification=self.sift_magnification,
|
|
617
|
+
window_size=self.sift_window_size,
|
|
618
|
+
backmatching=self.sift_back_matching,
|
|
619
|
+
disp_lower_bound=disp_lower_bound,
|
|
620
|
+
disp_upper_bound=disp_upper_bound,
|
|
621
|
+
saving_info_left=full_saving_info_left,
|
|
622
|
+
classif_bands_to_mask=classif_bands_to_mask,
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
else:
|
|
626
|
+
logging.error(
|
|
627
|
+
"SparseMatching application doesn't "
|
|
628
|
+
"support this input data format"
|
|
629
|
+
)
|
|
630
|
+
|
|
631
|
+
return epipolar_disparity_map_left, None
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
def compute_matches_wrapper( # pylint: disable=too-many-positional-arguments
|
|
635
|
+
left_image_object: xr.Dataset,
|
|
636
|
+
right_image_object: xr.Dataset,
|
|
637
|
+
used_band="b0",
|
|
638
|
+
matching_threshold=None,
|
|
639
|
+
n_octave=None,
|
|
640
|
+
n_scale_per_octave=None,
|
|
641
|
+
peak_threshold=None,
|
|
642
|
+
edge_threshold=None,
|
|
643
|
+
magnification=None,
|
|
644
|
+
window_size=None,
|
|
645
|
+
backmatching=None,
|
|
646
|
+
disp_lower_bound=None,
|
|
647
|
+
disp_upper_bound=None,
|
|
648
|
+
saving_info_left=None,
|
|
649
|
+
classif_bands_to_mask=None,
|
|
650
|
+
) -> Dict[str, Tuple[xr.Dataset, xr.Dataset]]:
|
|
651
|
+
"""
|
|
652
|
+
Compute matches from image objects.
|
|
653
|
+
This function will be run as a delayed task.
|
|
654
|
+
|
|
655
|
+
User must provide saving infos to save properly created datasets
|
|
656
|
+
|
|
657
|
+
:param left_image_object: tiled Left image dataset with :
|
|
658
|
+
|
|
659
|
+
- cst.EPI_IMAGE
|
|
660
|
+
- cst.EPI_MSK (if given)
|
|
661
|
+
- cst.EPI_TEXTURE (for left, if given)
|
|
662
|
+
:type left_image_object: xr.Dataset with :
|
|
663
|
+
|
|
664
|
+
- cst.EPI_IMAGE
|
|
665
|
+
- cst.EPI_MSK (if given)
|
|
666
|
+
- cst.EPI_TEXTURE (for left, if given)
|
|
667
|
+
:param right_image_object: tiled Right image
|
|
668
|
+
:type right_image_object: xr.Dataset
|
|
669
|
+
:param classif_bands_to_mask: bands from classif to mask
|
|
670
|
+
:type classif_bands_to_mask: list of str / int
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
:return: Left matches object, Right matches object (if exists)
|
|
674
|
+
|
|
675
|
+
Returned objects are composed of :
|
|
676
|
+
|
|
677
|
+
- dataframe (None for right object) with :
|
|
678
|
+
- TODO
|
|
679
|
+
"""
|
|
680
|
+
|
|
681
|
+
# Create mask
|
|
682
|
+
# TODO : remove overwriting of EPI_MSK
|
|
683
|
+
saved_left_mask = np.copy(left_image_object[cst.EPI_MSK].values)
|
|
684
|
+
saved_right_mask = np.copy(right_image_object[cst.EPI_MSK].values)
|
|
685
|
+
|
|
686
|
+
# Compute matches
|
|
687
|
+
matches = sparse_matching_algo.dataset_matching(
|
|
688
|
+
left_image_object,
|
|
689
|
+
right_image_object,
|
|
690
|
+
used_band,
|
|
691
|
+
matching_threshold=matching_threshold,
|
|
692
|
+
n_octave=n_octave,
|
|
693
|
+
n_scale_per_octave=n_scale_per_octave,
|
|
694
|
+
peak_threshold=peak_threshold,
|
|
695
|
+
edge_threshold=edge_threshold,
|
|
696
|
+
magnification=magnification,
|
|
697
|
+
window_size=window_size,
|
|
698
|
+
backmatching=backmatching,
|
|
699
|
+
disp_lower_bound=disp_lower_bound,
|
|
700
|
+
disp_upper_bound=disp_upper_bound,
|
|
701
|
+
classif_bands_to_mask=classif_bands_to_mask,
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
# Filter matches outside disparity range
|
|
705
|
+
if disp_lower_bound is not None and disp_upper_bound is not None:
|
|
706
|
+
filtered_nb_matches = matches.shape[0]
|
|
707
|
+
|
|
708
|
+
matches = matches[matches[:, 2] - matches[:, 0] >= disp_lower_bound]
|
|
709
|
+
matches = matches[matches[:, 2] - matches[:, 0] <= disp_upper_bound]
|
|
710
|
+
|
|
711
|
+
logging.debug(
|
|
712
|
+
"{} matches discarded because they fall outside of disparity range "
|
|
713
|
+
"defined by --elevation_delta_lower_bound and "
|
|
714
|
+
"--elevation_delta_upper_bound: [{} pix., {} pix.]".format(
|
|
715
|
+
filtered_nb_matches - matches.shape[0],
|
|
716
|
+
disp_lower_bound,
|
|
717
|
+
disp_upper_bound,
|
|
718
|
+
)
|
|
719
|
+
)
|
|
720
|
+
else:
|
|
721
|
+
logging.debug("Matches outside disparity range were not filtered")
|
|
722
|
+
|
|
723
|
+
# convert to Dataframe
|
|
724
|
+
left_matches_dataframe = pandas.DataFrame(matches)
|
|
725
|
+
|
|
726
|
+
# recover initial mask data in input images
|
|
727
|
+
# TODO remove with proper dataset creation
|
|
728
|
+
left_image_object[cst.EPI_MSK].values = saved_left_mask
|
|
729
|
+
right_image_object[cst.EPI_MSK].values = saved_right_mask
|
|
730
|
+
|
|
731
|
+
cars_dataset.fill_dataframe(
|
|
732
|
+
left_matches_dataframe, saving_info=saving_info_left, attributes=None
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
return left_matches_dataframe
|