cars 1.0.0a3__cp311-cp311-win_amd64.whl → 1.0.0a4__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cars might be problematic. Click here for more details.
- cars/__init__.py +3 -3
- cars/applications/__init__.py +0 -3
- cars/applications/application_template.py +20 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +80 -36
- cars/applications/dem_generation/dem_generation_algo.py +1 -1
- cars/applications/dem_generation/dem_generation_wrappers.py +23 -57
- cars/applications/dem_generation/dichotomic_generation_app.py +3 -3
- cars/applications/dem_generation/rasterization_app.py +100 -41
- cars/applications/dense_match_filling/__init__.py +1 -1
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
- cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
- cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
- cars/applications/dense_match_filling/zero_padding_app.py +10 -5
- cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
- cars/applications/dense_matching/census_mccnn_sgm_app.py +38 -39
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cp311-win_amd64.pyd +0 -0
- cars/applications/dense_matching/dense_matching_algo.py +48 -14
- cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
- cars/applications/dense_matching/disparity_grid_algo.py +84 -62
- cars/applications/dense_matching/loaders/pandora_loader.py +91 -33
- cars/applications/dsm_filling/border_interpolation_app.py +1 -7
- cars/applications/dsm_filling/bulldozer_filling_app.py +2 -8
- cars/applications/dsm_filling/exogenous_filling_app.py +4 -9
- cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
- cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
- cars/applications/grid_generation/grid_correction_app.py +4 -1
- cars/applications/grid_generation/grid_generation_algo.py +7 -2
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
- cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
- cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
- cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
- cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
- cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +2 -1
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
- cars/applications/point_cloud_outlier_removal/small_components_app.py +96 -267
- cars/applications/point_cloud_outlier_removal/statistical_app.py +116 -275
- cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -1
- cars/applications/rasterization/rasterization_algo.py +18 -6
- cars/applications/rasterization/rasterization_wrappers.py +2 -1
- cars/applications/rasterization/simple_gaussian_app.py +60 -113
- cars/applications/resampling/abstract_resampling_app.py +1 -1
- cars/applications/resampling/bicubic_resampling_app.py +3 -1
- cars/applications/resampling/resampling_algo.py +16 -4
- cars/applications/resampling/resampling_wrappers.py +3 -1
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
- cars/applications/sparse_matching/sift_app.py +3 -3
- cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
- cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
- cars/applications/triangulation/abstract_triangulation_app.py +1 -1
- cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +6 -4
- cars/applications/triangulation/triangulation_wrappers.py +1 -0
- cars/bundleadjustment.py +6 -6
- cars/cars.py +11 -9
- cars/core/cars_logging.py +80 -49
- cars/core/constants.py +0 -1
- cars/core/datasets.py +5 -2
- cars/core/geometry/abstract_geometry.py +256 -25
- cars/core/geometry/shareloc_geometry.py +110 -82
- cars/core/inputs.py +57 -19
- cars/core/outputs.py +1 -1
- cars/core/preprocessing.py +17 -3
- cars/core/projection.py +9 -6
- cars/core/tiling.py +10 -3
- cars/data_structures/cars_dataset.py +5 -5
- cars/data_structures/corresponding_tiles_tools.py +0 -103
- cars/data_structures/format_transformation.py +4 -1
- cars/devibrate.py +6 -3
- cars/extractroi.py +20 -21
- cars/orchestrator/cluster/abstract_cluster.py +15 -5
- cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
- cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
- cars/orchestrator/cluster/log_wrapper.py +148 -21
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +11 -3
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
- cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
- cars/orchestrator/cluster/sequential_cluster.py +5 -4
- cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
- cars/orchestrator/orchestrator.py +14 -3
- cars/orchestrator/registry/id_generator.py +1 -0
- cars/orchestrator/registry/saver_registry.py +2 -2
- cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
- cars/pipelines/default/default_pipeline.py +462 -1073
- cars/pipelines/parameters/advanced_parameters.py +74 -64
- cars/pipelines/parameters/advanced_parameters_constants.py +2 -5
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -314
- cars/pipelines/parameters/dsm_inputs.py +40 -4
- cars/pipelines/parameters/output_parameters.py +2 -2
- cars/pipelines/parameters/sensor_inputs.py +30 -75
- cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
- cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
- cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
- cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
- cars/pipelines/pipeline_template.py +1 -3
- cars/pipelines/unit/unit_pipeline.py +527 -1016
- cars/starter.py +4 -3
- cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/RECORD +115 -131
- cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
- cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
- cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
- cars/applications/dense_match_filling/cpp/__init__.py +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.dll.a +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp311-win_amd64.pyd +0 -0
- cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
- cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
- cars/applications/dense_match_filling/cpp/meson.build +0 -9
- cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
- cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
- cars/applications/dense_match_filling/plane_app.py +0 -556
- cars/applications/hole_detection/__init__.py +0 -30
- cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
- cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
- cars/applications/hole_detection/hole_detection_algo.py +0 -144
- cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
- cars/applications/point_cloud_denoising/__init__.py +0 -29
- cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
- cars/applications/point_cloud_fusion/__init__.py +0 -30
- cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
- cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
- cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
- cars-1.0.0a3.dist-info/DELVEWHEEL +0 -2
- 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.0a3.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
- {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,552 @@
|
|
|
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
|
+
# pylint: disable=too-many-lines
|
|
22
|
+
"""
|
|
23
|
+
This module is responsible for the transition between triangulation and
|
|
24
|
+
rasterization steps
|
|
25
|
+
"""
|
|
26
|
+
# pylint: disable=C0302
|
|
27
|
+
|
|
28
|
+
# Standard imports
|
|
29
|
+
import logging
|
|
30
|
+
from typing import List, Tuple, Union
|
|
31
|
+
|
|
32
|
+
# Third party imports
|
|
33
|
+
import numpy as np
|
|
34
|
+
import pandas as pd
|
|
35
|
+
import xarray as xr
|
|
36
|
+
|
|
37
|
+
from cars.applications.dense_matching import dense_matching_wrappers
|
|
38
|
+
|
|
39
|
+
# CARS imports
|
|
40
|
+
from cars.core import constants as cst
|
|
41
|
+
from cars.core import projection
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def filter_cloud_with_mask(crop_cloud, crop_terrain_tile_data_msk):
|
|
45
|
+
"""
|
|
46
|
+
Delete masked points with terrain tile mask
|
|
47
|
+
|
|
48
|
+
:param crop_cloud: the point cloud
|
|
49
|
+
:param crop_terrain_tile_data_msk: terrain tile mask
|
|
50
|
+
"""
|
|
51
|
+
crop_terrain_tile_data_msk = np.ravel(crop_terrain_tile_data_msk)
|
|
52
|
+
|
|
53
|
+
crop_terrain_tile_data_msk_pos = np.nonzero(~crop_terrain_tile_data_msk)
|
|
54
|
+
|
|
55
|
+
crop_cloud = np.delete(crop_cloud, crop_terrain_tile_data_msk_pos[0], 0)
|
|
56
|
+
|
|
57
|
+
return crop_cloud
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# pylint: disable=too-many-positional-arguments
|
|
61
|
+
def compute_terrain_msk(
|
|
62
|
+
dsm_epsg,
|
|
63
|
+
xmin,
|
|
64
|
+
xmax,
|
|
65
|
+
ymin,
|
|
66
|
+
ymax,
|
|
67
|
+
margin,
|
|
68
|
+
epsg,
|
|
69
|
+
point_cloud,
|
|
70
|
+
full_x,
|
|
71
|
+
full_y,
|
|
72
|
+
):
|
|
73
|
+
"""
|
|
74
|
+
Compute terrain tile msk bounds
|
|
75
|
+
|
|
76
|
+
If the point clouds are not in the same referential as the roi,
|
|
77
|
+
it is converted using the dsm_epsg
|
|
78
|
+
|
|
79
|
+
:param dsm_epsg: epsg code for the CRS of the final output raster
|
|
80
|
+
:param xmin: xmin of the rasterization grid
|
|
81
|
+
(if None, the whole clouds are combined)
|
|
82
|
+
:param xmax: xmax of the rasterization grid
|
|
83
|
+
(if None, the whole clouds are combined)
|
|
84
|
+
:param ymin: ymin of the rasterization grid
|
|
85
|
+
(if None, the whole clouds are combined)
|
|
86
|
+
:param ymax: ymax of the rasterization grid
|
|
87
|
+
(if None, the whole clouds are combined)
|
|
88
|
+
:param margin: Margin added for each tile, in meter or degree.
|
|
89
|
+
(default value: 0)
|
|
90
|
+
:param epsg: epsg code of the input cloud
|
|
91
|
+
:param point_cloud: the point cloud
|
|
92
|
+
:param full_x: point_cloud[X]
|
|
93
|
+
:param full_y: point_cloud[Y]
|
|
94
|
+
"""
|
|
95
|
+
if epsg != dsm_epsg:
|
|
96
|
+
(
|
|
97
|
+
full_x,
|
|
98
|
+
full_y,
|
|
99
|
+
) = projection.get_converted_xy_np_arrays_from_dataset(
|
|
100
|
+
point_cloud, dsm_epsg
|
|
101
|
+
)
|
|
102
|
+
msk_xmin = np.where(full_x > xmin - margin, True, False)
|
|
103
|
+
msk_xmax = np.where(full_x < xmax + margin, True, False)
|
|
104
|
+
msk_ymin = np.where(full_y > ymin - margin, True, False)
|
|
105
|
+
msk_ymax = np.where(full_y < ymax + margin, True, False)
|
|
106
|
+
terrain_tile_data_msk = np.logical_and(
|
|
107
|
+
msk_xmin,
|
|
108
|
+
np.logical_and(msk_xmax, np.logical_and(msk_ymin, msk_ymax)),
|
|
109
|
+
)
|
|
110
|
+
terrain_tile_data_msk_pos = terrain_tile_data_msk.astype(np.int8).nonzero()
|
|
111
|
+
|
|
112
|
+
return terrain_tile_data_msk, terrain_tile_data_msk_pos
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def create_point_cloud_index(cloud_sample):
|
|
116
|
+
"""
|
|
117
|
+
Create point cloud index from cloud list keys and color inputs
|
|
118
|
+
"""
|
|
119
|
+
cloud_indexes_with_types = {
|
|
120
|
+
cst.X: "float64",
|
|
121
|
+
cst.Y: "float64",
|
|
122
|
+
cst.Z: "float64",
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Add Z_inf Z_sup, and performance maps if computed
|
|
126
|
+
for key in list(cloud_sample.keys()):
|
|
127
|
+
if (
|
|
128
|
+
cst.POINT_CLOUD_LAYER_INF in key
|
|
129
|
+
or cst.POINT_CLOUD_LAYER_SUP in key
|
|
130
|
+
or cst.POINT_CLOUD_PERFORMANCE_MAP_ROOT in key
|
|
131
|
+
):
|
|
132
|
+
cloud_indexes_with_types[key] = "float32"
|
|
133
|
+
|
|
134
|
+
# Add mask index
|
|
135
|
+
if cst.EPI_MSK in cloud_sample:
|
|
136
|
+
cloud_indexes_with_types[cst.POINT_CLOUD_MSK] = "uint8"
|
|
137
|
+
|
|
138
|
+
# Add color indexes
|
|
139
|
+
if cst.EPI_TEXTURE in cloud_sample:
|
|
140
|
+
band_color = list(cloud_sample.coords[cst.BAND_IM].to_numpy())
|
|
141
|
+
color_type = "float32"
|
|
142
|
+
if "color_type" in cloud_sample.attrs:
|
|
143
|
+
color_type = cloud_sample.attrs["color_type"]
|
|
144
|
+
for band in band_color:
|
|
145
|
+
band_index = "{}_{}".format(cst.POINT_CLOUD_CLR_KEY_ROOT, band)
|
|
146
|
+
cloud_indexes_with_types[band_index] = color_type
|
|
147
|
+
|
|
148
|
+
# Add classif indexes
|
|
149
|
+
if cst.EPI_CLASSIFICATION in cloud_sample:
|
|
150
|
+
band_classif = list(cloud_sample.coords[cst.BAND_CLASSIF].to_numpy())
|
|
151
|
+
for band in band_classif:
|
|
152
|
+
band_index = "{}_{}".format(cst.POINT_CLOUD_CLASSIF_KEY_ROOT, band)
|
|
153
|
+
cloud_indexes_with_types[band_index] = "boolean"
|
|
154
|
+
|
|
155
|
+
# Add filling information indexes
|
|
156
|
+
if cst.EPI_FILLING in cloud_sample:
|
|
157
|
+
band_filling = list(cloud_sample.coords[cst.BAND_FILLING].to_numpy())
|
|
158
|
+
for band in band_filling:
|
|
159
|
+
band_index = "{}_{}".format(cst.POINT_CLOUD_FILLING_KEY_ROOT, band)
|
|
160
|
+
cloud_indexes_with_types[band_index] = "uint8"
|
|
161
|
+
|
|
162
|
+
# Add ambiguity information index
|
|
163
|
+
if cst.EPI_AMBIGUITY in cloud_sample:
|
|
164
|
+
cloud_indexes_with_types[cst.EPI_AMBIGUITY] = "float32"
|
|
165
|
+
|
|
166
|
+
return cloud_indexes_with_types
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# pylint: disable=too-many-positional-arguments
|
|
170
|
+
def add_information_to_cloud(
|
|
171
|
+
input_cloud, cloud_indexes, bbox, target_cloud, input_array, output_column
|
|
172
|
+
):
|
|
173
|
+
"""
|
|
174
|
+
Add color information for a current cloud_list item
|
|
175
|
+
|
|
176
|
+
:param cloud: source point cloud dataset
|
|
177
|
+
:type cloud: xr.Dataset
|
|
178
|
+
:param cloud_indexes: list of band data to extract
|
|
179
|
+
:type cloud_indexes: list[str]
|
|
180
|
+
:param bbox: bbox of interest
|
|
181
|
+
:type bbox: list[int]
|
|
182
|
+
:param crop_cloud: target flatten point cloud
|
|
183
|
+
:type crop_cloud: np.array[columns, points]
|
|
184
|
+
:param input_array: index of input to extract from cloud
|
|
185
|
+
:type input_array: str
|
|
186
|
+
:param output_column: index of crop_cloud to fill
|
|
187
|
+
:type input_array: str
|
|
188
|
+
"""
|
|
189
|
+
if input_array in input_cloud:
|
|
190
|
+
full_array = input_cloud[input_array]
|
|
191
|
+
if len(full_array.shape) == 3:
|
|
192
|
+
# Array with multiple bands
|
|
193
|
+
array = full_array[:, bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
|
|
194
|
+
for column_name in cloud_indexes:
|
|
195
|
+
if output_column in column_name:
|
|
196
|
+
band_name = column_name.replace(output_column + "_", "")
|
|
197
|
+
band = array.loc[band_name]
|
|
198
|
+
index = cloud_indexes.index(column_name)
|
|
199
|
+
target_cloud[index, :] = np.ravel(band.values)
|
|
200
|
+
elif len(full_array.shape) == 2:
|
|
201
|
+
# Array with single band
|
|
202
|
+
array = full_array[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
|
|
203
|
+
index = cloud_indexes.index(output_column)
|
|
204
|
+
target_cloud[index, :] = np.ravel(array.values)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def get_color_type(clouds):
|
|
208
|
+
"""
|
|
209
|
+
Get color type of the tiles and if the same type.
|
|
210
|
+
|
|
211
|
+
:param cloud_list: list of clouds
|
|
212
|
+
:type cloud_list: xarray Dataset
|
|
213
|
+
|
|
214
|
+
:return: color type of the tiles list
|
|
215
|
+
:rtype: str
|
|
216
|
+
|
|
217
|
+
"""
|
|
218
|
+
color_types = []
|
|
219
|
+
for cloud_id, cloud_item in enumerate(clouds):
|
|
220
|
+
if cst.EPI_TEXTURE in clouds[cloud_id]:
|
|
221
|
+
if "color_type" in cloud_item.attrs:
|
|
222
|
+
color_types.append(cloud_item.attrs["color_type"])
|
|
223
|
+
if color_types:
|
|
224
|
+
color_type_set = set(color_types)
|
|
225
|
+
if len(color_type_set) > 1:
|
|
226
|
+
logging.warning("The tiles colors don't have the same type.")
|
|
227
|
+
return color_types[0]
|
|
228
|
+
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def filter_cloud(
|
|
233
|
+
cloud: pd.DataFrame,
|
|
234
|
+
index_elt_to_remove: List[int],
|
|
235
|
+
filtered_elt_pos: bool = False,
|
|
236
|
+
) -> Tuple[pd.DataFrame, Union[None, pd.DataFrame]]:
|
|
237
|
+
"""
|
|
238
|
+
Filter all points of the cloud DataFrame
|
|
239
|
+
which index is in the index_elt_to_remove list.
|
|
240
|
+
|
|
241
|
+
If filtered_elt_pos is set to True, the information of the removed elements
|
|
242
|
+
positions in their original epipolar images are returned.
|
|
243
|
+
|
|
244
|
+
To do so the cloud DataFrame has to be build
|
|
245
|
+
with the 'with_coords' option activated.
|
|
246
|
+
|
|
247
|
+
:param cloud: combined cloud
|
|
248
|
+
as returned by the create_combined_cloud function
|
|
249
|
+
:param index_elt_to_remove: indexes of lines
|
|
250
|
+
to filter in the cloud DataFrame
|
|
251
|
+
:param filtered_elt_pos: if filtered_elt_pos is set to True,
|
|
252
|
+
the removed points positions in their original epipolar images are
|
|
253
|
+
returned, otherwise it is set to None
|
|
254
|
+
:return: Tuple composed of the filtered cloud DataFrame and
|
|
255
|
+
the filtered elements epipolar position information
|
|
256
|
+
(or None for the latter if filtered_elt_pos is set to False
|
|
257
|
+
or if the cloud Dataframe has not been build with with_coords option)
|
|
258
|
+
"""
|
|
259
|
+
if filtered_elt_pos and not (
|
|
260
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_I in cloud.columns
|
|
261
|
+
and cst.POINT_CLOUD_COORD_EPI_GEOM_J in cloud.columns
|
|
262
|
+
and cst.POINT_CLOUD_ID_IM_EPI in cloud.columns
|
|
263
|
+
):
|
|
264
|
+
logging.warning(
|
|
265
|
+
"In filter_cloud: the filtered_elt_pos has been activated but "
|
|
266
|
+
"the cloud Datafram has not been build with option with_coords. "
|
|
267
|
+
"The positions cannot be retrieved."
|
|
268
|
+
)
|
|
269
|
+
filtered_elt_pos = False
|
|
270
|
+
|
|
271
|
+
# retrieve removed points position in their original epipolar images
|
|
272
|
+
if filtered_elt_pos:
|
|
273
|
+
labels = [
|
|
274
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_I,
|
|
275
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_J,
|
|
276
|
+
cst.POINT_CLOUD_ID_IM_EPI,
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
removed_elt_pos_infos = cloud.loc[
|
|
280
|
+
cloud.index.values[index_elt_to_remove], labels
|
|
281
|
+
].values
|
|
282
|
+
|
|
283
|
+
removed_elt_pos_infos = pd.DataFrame(
|
|
284
|
+
removed_elt_pos_infos, columns=labels
|
|
285
|
+
)
|
|
286
|
+
else:
|
|
287
|
+
removed_elt_pos_infos = None
|
|
288
|
+
|
|
289
|
+
# remove points from the cloud
|
|
290
|
+
cloud = cloud.drop(index=cloud.index.values[index_elt_to_remove])
|
|
291
|
+
|
|
292
|
+
return cloud, removed_elt_pos_infos
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# pylint: disable=too-many-positional-arguments
|
|
296
|
+
def depth_map_dataset_to_dataframe( # noqa: C901
|
|
297
|
+
cloud_dataset: xr.Dataset,
|
|
298
|
+
dsm_epsg: int,
|
|
299
|
+
xmin: float = None,
|
|
300
|
+
xmax: float = None,
|
|
301
|
+
ymin: int = None,
|
|
302
|
+
ymax: int = None,
|
|
303
|
+
margin: float = 0,
|
|
304
|
+
with_coords: bool = False,
|
|
305
|
+
) -> Tuple[pd.DataFrame, int]:
|
|
306
|
+
"""
|
|
307
|
+
Combine a list of clouds (and their colors) into a pandas dataframe
|
|
308
|
+
structured with the following labels:
|
|
309
|
+
|
|
310
|
+
- if no colors in input and no mask data present in cloud_list datasets:
|
|
311
|
+
labels=[cst.X, cst.Y, cst.Z] \
|
|
312
|
+
The combined cloud has x, y, z columns
|
|
313
|
+
|
|
314
|
+
- if no colors in input and mask data present in cloud_list datasets:
|
|
315
|
+
labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK]\
|
|
316
|
+
The mask values are added to the dataframe.
|
|
317
|
+
|
|
318
|
+
- if colors are set in input and mask data are present \
|
|
319
|
+
in the cloud_list datasets:
|
|
320
|
+
labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK,\
|
|
321
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"0",\
|
|
322
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"1",\
|
|
323
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"2"]\
|
|
324
|
+
Color channels information are added to the dataframe.
|
|
325
|
+
|
|
326
|
+
- if colors in input, mask data present in the cloud_list datasets and\
|
|
327
|
+
the with_coords option is activated:
|
|
328
|
+
labels=[cst.X, cst.Y, cst.Z, cst.POINT_CLOUD_MSK,\
|
|
329
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"0",\
|
|
330
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"1",\
|
|
331
|
+
cst.POINT_CLOUD_CLR_KEY_ROOT+"2"\
|
|
332
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_I,\
|
|
333
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_J,\
|
|
334
|
+
cst.POINT_CLOUD_ID_IM_EPI]\
|
|
335
|
+
The pixel position of the xyz point in the original epipolar\
|
|
336
|
+
image (coord_epi_geom_i, coord_epi_geom_j) are added\
|
|
337
|
+
to the dataframe along with the index of its original cloud\
|
|
338
|
+
in the cloud_list input.
|
|
339
|
+
- if confidence intervals on Z in input, then\
|
|
340
|
+
[cst.Z_INF, cst.Z_SUP] are also added to the labels
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
:param dsm_epsg: epsg code for the CRS of the final output raster
|
|
344
|
+
:param xmin: xmin of the rasterization grid
|
|
345
|
+
(if None, the whole clouds are combined)
|
|
346
|
+
:param xmax: xmax of the rasterization grid
|
|
347
|
+
(if None, the whole clouds are combined)
|
|
348
|
+
:param ymin: ymin of the rasterization grid
|
|
349
|
+
(if None, the whole clouds are combined)
|
|
350
|
+
:param ymax: ymax of the rasterization grid
|
|
351
|
+
(if None, the whole clouds are combined)
|
|
352
|
+
:param margin: Margin added for each tile, in meter or degree.
|
|
353
|
+
(default value: 0)
|
|
354
|
+
:param with_coords: Option enabling the adding to the combined cloud
|
|
355
|
+
of information of each point to retrieve their positions
|
|
356
|
+
in the original epipolar images
|
|
357
|
+
:return: Tuple formed with the combined clouds and color
|
|
358
|
+
in a single pandas dataframe and the epsg code
|
|
359
|
+
"""
|
|
360
|
+
epsg = int(cloud_dataset.attrs[cst.EPSG])
|
|
361
|
+
|
|
362
|
+
# Compute margin/roi and final number of data to add to the combined cloud
|
|
363
|
+
roi = (
|
|
364
|
+
xmin is not None
|
|
365
|
+
and xmax is not None
|
|
366
|
+
and ymin is not None
|
|
367
|
+
and ymax is not None
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
# Create point cloud index
|
|
371
|
+
cloud_indexes_with_types = create_point_cloud_index(cloud_dataset)
|
|
372
|
+
|
|
373
|
+
# Add coords
|
|
374
|
+
if with_coords:
|
|
375
|
+
cloud_indexes_with_types.update(
|
|
376
|
+
{
|
|
377
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_I: "uint16",
|
|
378
|
+
cst.POINT_CLOUD_COORD_EPI_GEOM_J: "uint16",
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
cloud_indexes = list(cloud_indexes_with_types.keys())
|
|
383
|
+
|
|
384
|
+
# crop point cloud if is not created from tif depth maps
|
|
385
|
+
if (
|
|
386
|
+
cst.EPI_MARGINS in cloud_dataset.attrs
|
|
387
|
+
and cst.ROI in cloud_dataset.attrs
|
|
388
|
+
):
|
|
389
|
+
ref_roi, _, _ = dense_matching_wrappers.compute_cropped_roi(
|
|
390
|
+
cloud_dataset.attrs[cst.EPI_MARGINS],
|
|
391
|
+
0,
|
|
392
|
+
cloud_dataset.attrs[cst.ROI],
|
|
393
|
+
cloud_dataset.sizes[cst.ROW],
|
|
394
|
+
cloud_dataset.sizes[cst.COL],
|
|
395
|
+
)
|
|
396
|
+
cloud_dataset = cloud_dataset.isel(
|
|
397
|
+
row=slice(ref_roi[1], ref_roi[3]),
|
|
398
|
+
col=slice(ref_roi[0], ref_roi[2]),
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
full_x = cloud_dataset[cst.X].values
|
|
402
|
+
full_y = cloud_dataset[cst.Y].values
|
|
403
|
+
full_z = cloud_dataset[cst.Z].values
|
|
404
|
+
|
|
405
|
+
# get mask of points inside the roi (plus margins)
|
|
406
|
+
if roi:
|
|
407
|
+
# Compute terrain tile bounds
|
|
408
|
+
# if the point clouds are not in the same referential as the roi,
|
|
409
|
+
# it is converted using the dsm_epsg
|
|
410
|
+
(
|
|
411
|
+
terrain_tile_data_msk,
|
|
412
|
+
terrain_tile_data_msk_pos,
|
|
413
|
+
) = compute_terrain_msk(
|
|
414
|
+
dsm_epsg,
|
|
415
|
+
xmin,
|
|
416
|
+
xmax,
|
|
417
|
+
ymin,
|
|
418
|
+
ymax,
|
|
419
|
+
margin,
|
|
420
|
+
epsg,
|
|
421
|
+
cloud_dataset,
|
|
422
|
+
full_x,
|
|
423
|
+
full_y,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# if the point clouds are not in the same referential as the roi,
|
|
427
|
+
# retrieve the initial values
|
|
428
|
+
if epsg != dsm_epsg:
|
|
429
|
+
full_x = cloud_dataset[cst.X].values
|
|
430
|
+
full_y = cloud_dataset[cst.Y].values
|
|
431
|
+
|
|
432
|
+
# if no point is found, return Empty cloud
|
|
433
|
+
if terrain_tile_data_msk_pos[0].shape[0] == 0:
|
|
434
|
+
logging.error("No points found to transform")
|
|
435
|
+
return pd.DataFrame(columns=cloud_indexes), epsg
|
|
436
|
+
|
|
437
|
+
# get useful data bounding box
|
|
438
|
+
bbox = [
|
|
439
|
+
np.min(terrain_tile_data_msk_pos[0]),
|
|
440
|
+
np.min(terrain_tile_data_msk_pos[1]),
|
|
441
|
+
np.max(terrain_tile_data_msk_pos[0]),
|
|
442
|
+
np.max(terrain_tile_data_msk_pos[1]),
|
|
443
|
+
]
|
|
444
|
+
else:
|
|
445
|
+
bbox = [0, 0, full_y.shape[0] - 1, full_y.shape[1] - 1]
|
|
446
|
+
|
|
447
|
+
# add (x, y, z) information to the current cloud
|
|
448
|
+
crop_x = full_x[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
|
|
449
|
+
crop_y = full_y[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
|
|
450
|
+
crop_z = full_z[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1]
|
|
451
|
+
|
|
452
|
+
flatten_cloud = np.zeros(
|
|
453
|
+
(
|
|
454
|
+
len(cloud_indexes),
|
|
455
|
+
(bbox[2] - bbox[0] + 1) * (bbox[3] - bbox[1] + 1),
|
|
456
|
+
)
|
|
457
|
+
)
|
|
458
|
+
flatten_cloud[cloud_indexes.index(cst.X), :] = np.ravel(crop_x)
|
|
459
|
+
flatten_cloud[cloud_indexes.index(cst.Y), :] = np.ravel(crop_y)
|
|
460
|
+
flatten_cloud[cloud_indexes.index(cst.Z), :] = np.ravel(crop_z)
|
|
461
|
+
|
|
462
|
+
# add additional information to point cloud
|
|
463
|
+
arrays_to_add_to_point_cloud = [
|
|
464
|
+
(cst.EPI_TEXTURE, cst.POINT_CLOUD_CLR_KEY_ROOT),
|
|
465
|
+
(cst.EPI_MSK, cst.POINT_CLOUD_MSK),
|
|
466
|
+
(cst.EPI_CLASSIFICATION, cst.POINT_CLOUD_CLASSIF_KEY_ROOT),
|
|
467
|
+
(cst.EPI_FILLING, cst.POINT_CLOUD_FILLING_KEY_ROOT),
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
# Add layer inf and sup
|
|
471
|
+
for array_name in cloud_dataset:
|
|
472
|
+
if cst.POINT_CLOUD_LAYER_SUP_OR_INF_ROOT in array_name:
|
|
473
|
+
arrays_to_add_to_point_cloud.append((array_name, array_name))
|
|
474
|
+
|
|
475
|
+
# add performance map
|
|
476
|
+
for array_name in cloud_dataset:
|
|
477
|
+
if cst.POINT_CLOUD_PERFORMANCE_MAP_ROOT in array_name:
|
|
478
|
+
arrays_to_add_to_point_cloud.append((array_name, array_name))
|
|
479
|
+
|
|
480
|
+
# add ambiguity layer, drop confidence_* layers
|
|
481
|
+
for array_name in cloud_dataset:
|
|
482
|
+
if (
|
|
483
|
+
cst.EPI_AMBIGUITY in array_name
|
|
484
|
+
and cst.EPI_CONFIDENCE_KEY_ROOT not in array_name
|
|
485
|
+
):
|
|
486
|
+
arrays_to_add_to_point_cloud.append((array_name, array_name))
|
|
487
|
+
|
|
488
|
+
# add denoising info layers
|
|
489
|
+
for array_name in cloud_dataset:
|
|
490
|
+
if cst.EPI_DENOISING_INFO_KEY_ROOT in array_name:
|
|
491
|
+
arrays_to_add_to_point_cloud.append((array_name, array_name))
|
|
492
|
+
|
|
493
|
+
for input_band, output_column in arrays_to_add_to_point_cloud:
|
|
494
|
+
add_information_to_cloud(
|
|
495
|
+
cloud_dataset,
|
|
496
|
+
cloud_indexes,
|
|
497
|
+
bbox,
|
|
498
|
+
flatten_cloud,
|
|
499
|
+
input_band,
|
|
500
|
+
output_column,
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
# add the original image coordinates information to the current cloud
|
|
504
|
+
if with_coords:
|
|
505
|
+
coords_line = np.linspace(bbox[0], bbox[2], bbox[2] - bbox[0] + 1)
|
|
506
|
+
coords_col = np.linspace(bbox[1], bbox[3], bbox[3] - bbox[1] + 1)
|
|
507
|
+
coords_col, coords_line = np.meshgrid(coords_col, coords_line)
|
|
508
|
+
|
|
509
|
+
flatten_cloud[
|
|
510
|
+
cloud_indexes.index(cst.POINT_CLOUD_COORD_EPI_GEOM_I), :
|
|
511
|
+
] = np.ravel(coords_line)
|
|
512
|
+
flatten_cloud[
|
|
513
|
+
cloud_indexes.index(cst.POINT_CLOUD_COORD_EPI_GEOM_J), :
|
|
514
|
+
] = np.ravel(coords_col)
|
|
515
|
+
|
|
516
|
+
# Transpose point cloud
|
|
517
|
+
flatten_cloud = flatten_cloud.transpose()
|
|
518
|
+
|
|
519
|
+
# remove masked data (pandora + out of the terrain tile points)
|
|
520
|
+
crop_terrain_tile_data_msk = (
|
|
521
|
+
cloud_dataset[cst.POINT_CLOUD_CORR_MSK].values[
|
|
522
|
+
bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1
|
|
523
|
+
]
|
|
524
|
+
== 255
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
if roi:
|
|
528
|
+
crop_terrain_tile_data_msk = np.logical_and(
|
|
529
|
+
crop_terrain_tile_data_msk,
|
|
530
|
+
terrain_tile_data_msk[bbox[0] : bbox[2] + 1, bbox[1] : bbox[3] + 1],
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
flatten_cloud = filter_cloud_with_mask(
|
|
534
|
+
flatten_cloud, crop_terrain_tile_data_msk
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
# Remove points with nan values on X, Y or Z
|
|
538
|
+
xyz_indexes = np.array(
|
|
539
|
+
[
|
|
540
|
+
cloud_indexes.index(cst.X),
|
|
541
|
+
cloud_indexes.index(cst.Y),
|
|
542
|
+
cloud_indexes.index(cst.Z),
|
|
543
|
+
]
|
|
544
|
+
)
|
|
545
|
+
flatten_cloud = flatten_cloud[
|
|
546
|
+
~np.any(np.isnan(flatten_cloud[:, xyz_indexes]), axis=1)
|
|
547
|
+
]
|
|
548
|
+
|
|
549
|
+
pd_cloud = pd.DataFrame(flatten_cloud, columns=cloud_indexes)
|
|
550
|
+
pd_cloud = pd_cloud.astype(cloud_indexes_with_types)
|
|
551
|
+
|
|
552
|
+
return pd_cloud, epsg
|
|
@@ -38,7 +38,7 @@ from cars.core import constants_disparity as cst_disp
|
|
|
38
38
|
from cars.core import projection
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
def triangulate(
|
|
41
|
+
def triangulate( # pylint: disable=too-many-positional-arguments
|
|
42
42
|
geometry_plugin,
|
|
43
43
|
sensor1,
|
|
44
44
|
sensor2,
|
|
@@ -109,7 +109,7 @@ def triangulate(
|
|
|
109
109
|
return point_clouds
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
def triangulate_matches(
|
|
112
|
+
def triangulate_matches( # pylint: disable=too-many-positional-arguments
|
|
113
113
|
geometry_plugin,
|
|
114
114
|
sensor1,
|
|
115
115
|
sensor2,
|
|
@@ -118,6 +118,7 @@ def triangulate_matches(
|
|
|
118
118
|
grid1,
|
|
119
119
|
grid2,
|
|
120
120
|
matches,
|
|
121
|
+
interpolation_method=None,
|
|
121
122
|
):
|
|
122
123
|
"""
|
|
123
124
|
This function will perform triangulation from sift matches
|
|
@@ -162,6 +163,7 @@ def triangulate_matches(
|
|
|
162
163
|
matches,
|
|
163
164
|
grid1,
|
|
164
165
|
grid2,
|
|
166
|
+
interpolation_method=interpolation_method,
|
|
165
167
|
)
|
|
166
168
|
|
|
167
169
|
disparity = np.array([matches[:, 2] - matches[:, 0]])
|
|
@@ -189,7 +191,7 @@ def triangulate_matches(
|
|
|
189
191
|
return point_cloud
|
|
190
192
|
|
|
191
193
|
|
|
192
|
-
def triangulate_sparse_matches(
|
|
194
|
+
def triangulate_sparse_matches( # pylint: disable=too-many-positional-arguments
|
|
193
195
|
sensor1,
|
|
194
196
|
sensor2,
|
|
195
197
|
geomodel1,
|
|
@@ -263,7 +265,7 @@ def triangulate_sparse_matches(
|
|
|
263
265
|
return pd_cloud
|
|
264
266
|
|
|
265
267
|
|
|
266
|
-
def compute_point_cloud(
|
|
268
|
+
def compute_point_cloud( # pylint: disable=too-many-positional-arguments
|
|
267
269
|
geometry_plugin,
|
|
268
270
|
sensor1,
|
|
269
271
|
sensor2,
|
cars/bundleadjustment.py
CHANGED
|
@@ -407,7 +407,7 @@ def write_rpcs_as_geom(refined_rpcs, out_dir):
|
|
|
407
407
|
return geoms_filenames
|
|
408
408
|
|
|
409
409
|
|
|
410
|
-
def new_rpcs_from_matches(
|
|
410
|
+
def new_rpcs_from_matches( # pylint: disable=too-many-positional-arguments
|
|
411
411
|
sensors,
|
|
412
412
|
config_directory,
|
|
413
413
|
sparse_matching_directory,
|
|
@@ -429,7 +429,7 @@ def new_rpcs_from_matches(
|
|
|
429
429
|
matches_filename = os.path.join(
|
|
430
430
|
sparse_matching_directory,
|
|
431
431
|
"dump_dir",
|
|
432
|
-
"sparse_matching
|
|
432
|
+
"sparse_matching",
|
|
433
433
|
"_".join(pair),
|
|
434
434
|
"filtered_matches.npy",
|
|
435
435
|
)
|
|
@@ -592,13 +592,13 @@ def cars_bundle_adjustment(conf, no_run_sparse, output_format="yaml"):
|
|
|
592
592
|
sparse_matching_config["output"]["product_level"] = []
|
|
593
593
|
sparse_matching_config["advanced"] = {}
|
|
594
594
|
sparse_matching_config["advanced"]["epipolar_resolutions"] = [1]
|
|
595
|
-
if "sparse_matching
|
|
596
|
-
sparse_matching_config["applications"]["
|
|
597
|
-
sparse_matching_config["applications"]["sparse_matching
|
|
595
|
+
if "sparse_matching" not in sparse_matching_config["applications"]:
|
|
596
|
+
sparse_matching_config["applications"]["all"] = {"sparse_matching": {}}
|
|
597
|
+
sparse_matching_config["applications"]["all"]["sparse_matching"][
|
|
598
598
|
"save_intermediate_data"
|
|
599
599
|
] = True
|
|
600
600
|
|
|
601
|
-
sparse_matching_config["applications"]["sparse_matching
|
|
601
|
+
sparse_matching_config["applications"]["all"]["sparse_matching"][
|
|
602
602
|
"decimation_factor"
|
|
603
603
|
] = 100
|
|
604
604
|
|
cars/cars.py
CHANGED
|
@@ -126,11 +126,13 @@ def main_cli(args, dry_run=False): # noqa: C901
|
|
|
126
126
|
loglevel = getattr(args, "loglevel", "PROGRESS").upper()
|
|
127
127
|
out_dir = config["output"]["directory"]
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
# do not set logging if pipeline is default (already defined
|
|
130
|
+
if config.get("advanced", {}).get("pipeline", "default") != "default":
|
|
131
|
+
cars_logging.setup_logging(
|
|
132
|
+
loglevel,
|
|
133
|
+
out_dir=os.path.join(out_dir, "logs"),
|
|
134
|
+
pipeline=pipeline_name,
|
|
135
|
+
)
|
|
134
136
|
|
|
135
137
|
logging.debug("Show argparse arguments: {}".format(args))
|
|
136
138
|
|
|
@@ -143,11 +145,11 @@ def main_cli(args, dry_run=False): # noqa: C901
|
|
|
143
145
|
used_pipeline.run(args)
|
|
144
146
|
|
|
145
147
|
# Generate summary of tasks
|
|
146
|
-
if
|
|
147
|
-
config.get("advanced", {}).get("epipolar_resolutions"), list
|
|
148
|
-
):
|
|
148
|
+
if config.get("advanced", {}).get("pipeline", "default") != "default":
|
|
149
149
|
log_wrapper.generate_summary(
|
|
150
|
-
out_dir,
|
|
150
|
+
os.path.join(out_dir, "logs"),
|
|
151
|
+
used_pipeline.used_conf,
|
|
152
|
+
clean_worker_logs=True,
|
|
151
153
|
)
|
|
152
154
|
|
|
153
155
|
cars_logging.add_progress_message(
|