diff --git a/CHANGELOG.md b/CHANGELOG.md index 73c06a2..8e02699 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 1.5.0a1 (Novembre 2023) + +### Changed +- Adding check for geometric_prior option in check_conf function. [#88] +- New format for disparity in the user configuration file. [#87] +- Change read_img function to create_dataset_from_inputs. [#83] +- Update with new API of Pandora run and compute_cost_volume function. [#94] + + ## 1.4.0 (April 2023) ### Added diff --git a/pandora_plugin_libsgm/abstract_sgm.py b/pandora_plugin_libsgm/abstract_sgm.py index 3a89f72..447c584 100644 --- a/pandora_plugin_libsgm/abstract_sgm.py +++ b/pandora_plugin_libsgm/abstract_sgm.py @@ -54,13 +54,15 @@ class AbstractSGM(optimization.AbstractOptimization): _DIRECTIONS = [[0, 1], [1, 0], [1, 1], [1, -1], [0, -1], [-1, 0], [-1, -1], [-1, 1]] _USE_CONFIDENCE = False - def __init__(self, **cfg: Union[str, int, float, bool, dict]): + def __init__(self, img: xr.Dataset, **cfg: Union[str, int, float, bool, dict]): """ + :param img: xarray.Dataset of image with metadata + :type img: xarray.Dataset :param cfg: optional configuration, {'P1': value, 'P2': value, 'alpha': value, 'beta': value, 'gamma': value, 'p2_method': value} :type cfg: dict """ - self.cfg = self.check_conf(**cfg) + self.cfg = self.check_conf(img, **cfg) self._sgm_version = self.cfg["sgm_version"] self._overcounting = self.cfg["overcounting"] self._min_cost_paths = self.cfg["min_cost_paths"] @@ -78,10 +80,14 @@ def desc(self): Describes the optimization method """ - def check_conf(self, **cfg: Union[str, int, float, bool, dict]) -> Dict[str, Union[str, int, float, bool, dict]]: + def check_conf( + self, img: xr.Dataset, **cfg: Union[str, int, float, bool, dict] + ) -> Dict[str, Union[str, int, float, bool, dict]]: """ Add default values to the dictionary if there are missing elements and check if the dictionary is correct + :param img: xarray.Dataset of image with metadata + :type img: xarray.Dataset :param cfg: optimization configuration :type cfg: dict :return cfg: optimization configuration updated @@ -101,6 +107,14 @@ def check_conf(self, **cfg: Union[str, int, float, bool, dict]) -> Dict[str, Uni if cfg["optimization_method"] == "sgm" and "geometric_prior" in cfg: logging.error("Geometric prior not available for SGM optimization") sys.exit(1) + + if "geometric_prior" in cfg: + source = cfg["geometric_prior"]["source"] + if source in ["classif", "segm"] and not source in img.data_vars: + logging.error( + "For performing the 3SGM optimization step in the pipeline, left %s must be present.", source + ) + sys.exit(1) schema = { "sgm_version": And(str, lambda x: is_method(x, ["c++", "python_libsgm", "python_libsgm_parall"])), diff --git a/pandora_plugin_libsgm/lib_3sgm.py b/pandora_plugin_libsgm/lib_3sgm.py index dbf5275..484a5d3 100644 --- a/pandora_plugin_libsgm/lib_3sgm.py +++ b/pandora_plugin_libsgm/lib_3sgm.py @@ -47,13 +47,15 @@ class SEGSEMSGM(abstract_sgm.AbstractSGM): _GEOMETRIC_PRIOR = {"source": "internal"} _AVAILABLE_GEOMETRIC_PRIOR = ["internal", "classif", "segm"] - def __init__(self, **cfg: Union[str, int, float, bool]): + def __init__(self, img: xr.Dataset, **cfg: Union[str, int, float, bool]): """ + :param img: xarray.Dataset of image with metadata + :type img: xarray.Dataset :param cfg: optional configuration, {} :type cfg: dict :return: None """ - super().__init__(**cfg) + super().__init__(img, **cfg) self.cfg = self.check_geometric_prior(cfg) self._geometric_prior = self.cfg["geometric_prior"] if self._geometric_prior["source"] == "classif": # type: ignore diff --git a/setup.cfg b/setup.cfg index 9c2a4a2..68072ab 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,7 +43,7 @@ install_requires = numpy rasterio libsgm==0.4.* - pandora>=1.5.0 + pandora==1.6.0a1 xarray json-checker diff --git a/tests/conftest.py b/tests/conftest.py index 2247c37..6441cd8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -45,80 +45,86 @@ def configurations_path(resource_path_root): @pytest.fixture() def left_cones(inputs_path): """Cones images.""" - path = inputs_path / "left.png" - return pandora.read_img(str(path), no_data=np.nan, mask=None) + return pandora.create_dataset_from_inputs( + {"img": str(inputs_path / "left.png"), "nodata": np.nan, "mask": None, "disp": [-60, 0]} + ) @pytest.fixture() def right_cones(inputs_path): """Cones images.""" - path = inputs_path / "right.png" - return pandora.read_img(str(path), no_data=np.nan, mask=None) + return pandora.create_dataset_from_inputs( + {"img": str(inputs_path / "right.png"), "nodata": np.nan, "mask": None, "disp": [0, 60]} + ) @pytest.fixture() def left_rgb(inputs_path): """Cones images.""" - path = inputs_path / "left_rgb.tif" - return pandora.read_img(str(path), no_data=np.nan, mask=None) + return pandora.create_dataset_from_inputs( + {"img": str(inputs_path / "left_rgb.tif"), "nodata": np.nan, "mask": None, "disp": [-60, 0]} + ) @pytest.fixture() def right_rgb(inputs_path): """Cones images.""" - path = inputs_path / "right_rgb.tif" - return pandora.read_img(str(path), no_data=np.nan, mask=None) + return pandora.create_dataset_from_inputs( + {"img": str(inputs_path / "right_rgb.tif"), "nodata": np.nan, "mask": None} + ) @pytest.fixture() def left_cones_classif(inputs_path): """Cones images with classification.""" - path = inputs_path / "left.png" - classif_path = inputs_path / "left_classif.tif" - return pandora.read_img( - str(path), - no_data=np.nan, - mask=None, - classif=str(classif_path), + return pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "left.png"), + "nodata": np.nan, + "mask": None, + "classif": str(inputs_path / "left_classif.tif"), + "disp": [-60, 0], + } ) @pytest.fixture() def right_cones_classif(inputs_path): """Cones images with classification.""" - path = inputs_path / "right.png" - classif_path = inputs_path / "right_classif.tif" - return pandora.read_img( - str(path), - no_data=np.nan, - mask=None, - classif=str(classif_path), + return pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "right.png"), + "nodata": np.nan, + "mask": None, + "classif": str(inputs_path / "right_classif.tif"), + } ) @pytest.fixture() def left_cones_segm(inputs_path): """Cones images with segmentation.""" - path = inputs_path / "left.png" - segment_path = inputs_path / "left_classif.tif" - return pandora.read_img( - str(path), - no_data=np.nan, - mask=None, - segm=str(segment_path), + return pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "left.png"), + "nodata": np.nan, + "mask": None, + "segm": str(inputs_path / "left_classif.tif"), + "disp": [-60, 0], + } ) @pytest.fixture() def right_cones_segm(inputs_path): """Cones images with segmentation.""" - path = inputs_path / "right.png" - segment_path = inputs_path / "right_classif.tif" - return pandora.read_img( - str(path), - no_data=np.nan, - mask=None, - segm=str(segment_path), + return pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "right.png"), + "nodata": np.nan, + "mask": None, + "segm": str(inputs_path / "right_classif.tif"), + } ) diff --git a/tests/test_lib3sgm.py b/tests/test_lib3sgm.py index 308cede..5c1d3a5 100644 --- a/tests/test_lib3sgm.py +++ b/tests/test_lib3sgm.py @@ -71,6 +71,32 @@ def user_cfg(configurations_path): return pandora.read_config_file(str(configurations_path / "3sgm.json")) +@pytest.fixture() +def inputs_with_classif(inputs_path): + return { + "img_left": str(inputs_path / "left.png"), + "left_classif": str(inputs_path / "left_classif.tif"), + "disp_left": [-60, 0], + "nodata_left": "NaN", + "img_right": str(inputs_path / "right.png"), + "right_classif": str(inputs_path / "right_classif.tif"), + "nodata_right": "NaN", + } + + +@pytest.fixture() +def inputs_with_segment(inputs_path): + return { + "img_left": str(inputs_path / "left.png"), + "left_segm": str(inputs_path / "left_classif.tif"), + "disp_left": [-60, 0], + "nodata_left": "NaN", + "img_right": str(inputs_path / "right.png"), + "right_segm": str(inputs_path / "right_classif.tif"), + "nodata_right": "NaN", + } + + class TestPlugin3SGM: """ TestPlugin class allows to test pandora + plugin_lib3sgm @@ -90,7 +116,7 @@ def test_lib3sgm(self, left_cones, right_cones, disp_left, disp_right, user_cfg) pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -122,7 +148,7 @@ def test_compute_optimization_layer_none_layer_in_dataset(self, left_crafted, co pandora.import_plugin() # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) classif_arr = optimization_.compute_optimization_layer(cost_volume, left_crafted, left_crafted["im"].data.shape) @@ -137,9 +163,6 @@ def test_optimization_layer_with_3sgm(self, cost_volume, user_cfg): # Import pandora plugins pandora.import_plugin() - # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) - data = np.array(([1, 1, 1, 1], [1, 1, 2, 1], [1, 1, 4, 1]), dtype=np.float32) left = xr.Dataset( {"im": (["row", "col"], data)}, @@ -154,6 +177,9 @@ def test_optimization_layer_with_3sgm(self, cost_volume, user_cfg): ) gt_default_prior_array = np.ones(left["im"].shape, dtype=np.float32) + # Load plugins + optimization_ = optimization.AbstractOptimization(left, **user_cfg["pipeline"]["optimization"]) + cv_in = copy.deepcopy(cost_volume) prior_array_out = optimization_.compute_optimization_layer(cv_in, left, left["im"].data.shape) @@ -182,7 +208,7 @@ def test_user_initiate_3sgm_with_geomprior_internal(self, left_cones, right_cone pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -220,7 +246,7 @@ def test_user_initiate_3sgm_with_none_geomprior_classif(self, left_cones, right_ # Pandora pipeline should fail with pytest.raises(SystemExit): - _, _ = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + _, _ = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) def test_user_initiate_3sgm_with_none_geomprior_segmentation(self, left_cones, right_cones, user_cfg): """ @@ -242,7 +268,7 @@ def test_user_initiate_3sgm_with_none_geomprior_segmentation(self, left_cones, r # Pandora pipeline should fail with pytest.raises(SystemExit): - _, _ = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + _, _ = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) @staticmethod def test_user_initiate_3sgm_with_geomprior_segmentation(user_cfg, inputs_path, outputs_path): @@ -252,17 +278,22 @@ def test_user_initiate_3sgm_with_geomprior_segmentation(user_cfg, inputs_path, o """ # Add mask to left data - masked_left = pandora.read_img( - str(inputs_path / "left.png"), - no_data=np.nan, - mask=None, - segm=str(inputs_path / "white_band_mask.png"), + masked_left = pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "left.png"), + "nodata": np.nan, + "mask": None, + "segm": str(inputs_path / "white_band_mask.png"), + "disp": [-60, 0], + } ) - masked_right = pandora.read_img( - str(inputs_path / "right.png"), - no_data=np.nan, - mask=None, - segm=str(inputs_path / "white_band_mask.png"), + masked_right = pandora.create_dataset_from_inputs( + { + "img": str(inputs_path / "right.png"), + "nodata": np.nan, + "mask": None, + "segm": str(inputs_path / "white_band_mask.png"), + } ) # Ground truth @@ -280,7 +311,7 @@ def test_user_initiate_3sgm_with_geomprior_segmentation(user_cfg, inputs_path, o # Instantiate machine pandora_machine = PandoraMachine() - left, right = pandora.run(pandora_machine, masked_left, masked_right, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, masked_left, masked_right, user_cfg) # Compares the calculated right disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -299,7 +330,7 @@ def test_user_initiate_3sgm_with_geomprior_segmentation(user_cfg, inputs_path, o assert common.error(right["disparity_map"].data, gt_right, 2) <= 0.15 def test_classif_on_right_and_left_with_one_class( - self, left_cones_classif, right_cones_classif, user_cfg, inputs_path, outputs_path + self, left_cones_classif, right_cones_classif, user_cfg, inputs_with_classif, outputs_path ): """ Optimization on one existing band for left and right classification with validation step. @@ -313,16 +344,7 @@ def test_classif_on_right_and_left_with_one_class( } # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -333,7 +355,7 @@ def test_classif_on_right_and_left_with_one_class( # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, right = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -356,7 +378,7 @@ def test_classif_on_right_and_left_with_one_class( assert common.error(right["disparity_map"].data, gt_right, 2) <= 0.15 def test_classif_on_right_and_left_with_two_classes( - self, left_cones_classif, right_cones_classif, user_cfg, inputs_path, outputs_path + self, left_cones_classif, right_cones_classif, user_cfg, inputs_with_classif, outputs_path ): """ Optimization on two existing bands for left and right classification with validation step. @@ -370,16 +392,7 @@ def test_classif_on_right_and_left_with_two_classes( } # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -390,7 +403,7 @@ def test_classif_on_right_and_left_with_two_classes( # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, right = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -412,7 +425,7 @@ def test_classif_on_right_and_left_with_two_classes( # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(right["disparity_map"].data, gt_right, 2) <= 0.15 - def test_classif_on_right_and_left_with_wrong_class(self, user_cfg, inputs_path): + def test_classif_on_right_and_left_with_wrong_class(self, user_cfg, inputs_with_classif): """ Optimization on wrong band for left and right classification with validation step. "peuplier" band doesn't exists. @@ -427,16 +440,7 @@ def test_classif_on_right_and_left_with_wrong_class(self, user_cfg, inputs_path) } # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -448,7 +452,7 @@ def test_classif_on_right_and_left_with_wrong_class(self, user_cfg, inputs_path) with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_right_and_left_with_no_class(self, user_cfg, inputs_path): + def test_classif_on_right_and_left_with_no_class(self, user_cfg, inputs_with_classif): """ Optimization for left and right classification with wrong configuration with validation step. Classes are required for source as "classif" in geometric_prior. @@ -460,16 +464,7 @@ def test_classif_on_right_and_left_with_no_class(self, user_cfg, inputs_path): user_cfg["pipeline"]["optimization"]["geometric_prior"] = {"source": "classif"} # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -481,7 +476,7 @@ def test_classif_on_right_and_left_with_no_class(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_right_with_validation(self, user_cfg, inputs_path): + def test_classif_on_right_with_validation(self, user_cfg, inputs_with_classif): """ Optimization with only right classification present Validation step requires both left and right classifications @@ -498,15 +493,8 @@ def test_classif_on_right_with_validation(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["left_classif"] # Import pandora plugins pandora.import_plugin() @@ -518,7 +506,7 @@ def test_classif_on_right_with_validation(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_left_with_validation(self, user_cfg, inputs_path): + def test_classif_on_left_with_validation(self, user_cfg, inputs_with_classif): """ Optimization for left classification with validation step. Validation step requires both left and right classifications @@ -535,15 +523,8 @@ def test_classif_on_left_with_validation(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["right_classif"] # Import pandora plugins pandora.import_plugin() @@ -555,7 +536,9 @@ def test_classif_on_left_with_validation(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_right_and_left(self, left_cones_segm, right_cones_segm, user_cfg, inputs_path, outputs_path): + def test_segm_on_right_and_left( + self, left_cones_segm, right_cones_segm, user_cfg, inputs_with_segment, outputs_path + ): """ Optimization left and right segmentation with validation step. """ @@ -565,16 +548,7 @@ def test_segm_on_right_and_left(self, left_cones_segm, right_cones_segm, user_cf user_cfg["pipeline"]["optimization"]["geometric_prior"] = {"source": "segm"} # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment # Import pandora plugins pandora.import_plugin() @@ -585,7 +559,7 @@ def test_segm_on_right_and_left(self, left_cones_segm, right_cones_segm, user_cf # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, right = pandora.run(pandora_machine, left_cones_segm, right_cones_segm, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones_segm, right_cones_segm, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -607,7 +581,7 @@ def test_segm_on_right_and_left(self, left_cones_segm, right_cones_segm, user_cf # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(right["disparity_map"].data, gt_right, 2) <= 0.15 - def test_segm_with_classes(self, user_cfg, inputs_path): + def test_segm_with_classes(self, user_cfg, inputs_with_classif): """ Optimization left and right segmentation with validation step and classes instantiated. Classes are not available for segmentation step @@ -622,16 +596,7 @@ def test_segm_with_classes(self, user_cfg, inputs_path): } # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -643,7 +608,7 @@ def test_segm_with_classes(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_right(self, user_cfg, inputs_path): + def test_segm_on_right(self, user_cfg, inputs_with_segment): """ Optimization right segmentation with validation step. Validation step requires both left and right segmentation. @@ -657,15 +622,8 @@ def test_segm_on_right(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment + del user_cfg["input"]["left_segm"] # Import pandora plugins pandora.import_plugin() @@ -677,7 +635,7 @@ def test_segm_on_right(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_left(self, user_cfg, inputs_path): + def test_segm_on_left(self, user_cfg, inputs_with_segment): """ Optimization left segmentation with validation step. Validation step requires both left and right segmentation. @@ -691,15 +649,8 @@ def test_segm_on_left(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment + del user_cfg["input"]["right_segm"] # Import pandora plugins pandora.import_plugin() @@ -712,7 +663,7 @@ def test_segm_on_left(self, user_cfg, inputs_path): _ = check_conf(user_cfg, pandora_machine) def test_classif_on_left_with_correct_class( - self, left_cones_classif, right_cones, user_cfg, inputs_path, outputs_path + self, left_cones_classif, right_cones, user_cfg, inputs_with_classif, outputs_path ): """ Optimization on one existing band left classification without validation step. @@ -722,7 +673,6 @@ def test_classif_on_left_with_correct_class( # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add a segmentation and classes user_cfg["pipeline"]["optimization"]["geometric_prior"] = { @@ -731,15 +681,8 @@ def test_classif_on_left_with_correct_class( } # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["right_classif"] # Import pandora plugins pandora.import_plugin() @@ -750,7 +693,7 @@ def test_classif_on_left_with_correct_class( # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, _ = pandora.run(pandora_machine, left_cones_classif, right_cones, -60, 0, user_cfg) + left, _ = pandora.run(pandora_machine, left_cones_classif, right_cones, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -764,7 +707,7 @@ def test_classif_on_left_with_correct_class( assert common.error(left["disparity_map"].data, gt_left, 2) <= 0.15 def test_classif_on_left_and_right_with_correct_class( - self, left_cones_classif, right_cones_classif, user_cfg, inputs_path, outputs_path + self, left_cones_classif, right_cones_classif, user_cfg, inputs_with_classif, outputs_path ): """ Optimization on one existing band for left and right classification without validation step. @@ -779,19 +722,9 @@ def test_classif_on_left_and_right_with_correct_class( # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -802,7 +735,7 @@ def test_classif_on_left_and_right_with_correct_class( # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, _ = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, -60, 0, user_cfg) + left, _ = pandora.run(pandora_machine, left_cones_classif, right_cones_classif, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -815,7 +748,7 @@ def test_classif_on_left_and_right_with_correct_class( # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(left["disparity_map"].data, gt_left, 2) <= 0.15 - def test_classif_on_right_with_correct_class(self, user_cfg, inputs_path): + def test_classif_on_right_with_correct_class(self, user_cfg, inputs_with_classif): """ Optimization with right classification without validation step. Classification without validation step requires left classification. @@ -835,15 +768,8 @@ def test_classif_on_right_with_correct_class(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["left_classif"] # Import pandora plugins pandora.import_plugin() @@ -855,7 +781,9 @@ def test_classif_on_right_with_correct_class(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_left_without_validation(self, left_cones_segm, right_cones, user_cfg, inputs_path, outputs_path): + def test_segm_on_left_without_validation( + self, left_cones_segm, right_cones, user_cfg, inputs_with_segment, outputs_path + ): """ Optimization on left image with segmentation without validation step. """ @@ -866,18 +794,10 @@ def test_segm_on_left_without_validation(self, left_cones_segm, right_cones, use # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "img_right": str(inputs_path / "right.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment + del user_cfg["input"]["right_segm"] # Import pandora plugins pandora.import_plugin() @@ -887,7 +807,7 @@ def test_segm_on_left_without_validation(self, left_cones_segm, right_cones, use user_cfg = check_conf(user_cfg, pandora_machine) - left, _ = pandora.run(pandora_machine, left_cones_segm, right_cones, -60, 0, user_cfg) + left, _ = pandora.run(pandora_machine, left_cones_segm, right_cones, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -901,7 +821,7 @@ def test_segm_on_left_without_validation(self, left_cones_segm, right_cones, use assert common.error(left["disparity_map"].data, gt_left, 2) <= 0.15 def test_segm_on_left_and_right_without_validation( - self, left_cones_segm, right_cones_segm, user_cfg, inputs_path, outputs_path + self, left_cones_segm, right_cones_segm, user_cfg, inputs_with_segment, outputs_path ): """ Optimization on left and right image with segmentation without validation step. @@ -913,19 +833,9 @@ def test_segm_on_left_and_right_without_validation( # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment # Import pandora plugins pandora.import_plugin() @@ -936,7 +846,7 @@ def test_segm_on_left_and_right_without_validation( # Check configuration user_cfg = check_conf(user_cfg, pandora_machine) - left, _ = pandora.run(pandora_machine, left_cones_segm, right_cones_segm, -60, 0, user_cfg) + left, _ = pandora.run(pandora_machine, left_cones_segm, right_cones_segm, user_cfg) # Ground truth gt_left = rasterio.open(outputs_path / "left_disparity_3sgm.tif").read(1) @@ -949,7 +859,7 @@ def test_segm_on_left_and_right_without_validation( # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(left["disparity_map"].data, gt_left, 2) <= 0.15 - def test_segm_on_right_without_validation(self, user_cfg, inputs_path): + def test_segm_on_right_without_validation(self, user_cfg, inputs_with_segment): """ Optimization with right segmentation without validation step. Segmentation without validation step requires left segmentation. @@ -966,15 +876,8 @@ def test_segm_on_right_without_validation(self, user_cfg, inputs_path): user_cfg["pipeline"]["disparity"]["invalid_disparity"] = np.nan # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "left_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment + del user_cfg["input"]["left_segm"] # Import pandora plugins pandora.import_plugin() @@ -986,7 +889,7 @@ def test_segm_on_right_without_validation(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_left_and_right_with_classes(self, user_cfg, inputs_path): + def test_segm_on_left_and_right_with_classes(self, user_cfg, inputs_with_segment): """ Optimization with right and left segmentation with classes without validation step. Classes are not available for segmentation step @@ -1002,19 +905,9 @@ def test_segm_on_left_and_right_with_classes(self, user_cfg, inputs_path): # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment # Import pandora plugins pandora.import_plugin() @@ -1026,7 +919,7 @@ def test_segm_on_left_and_right_with_classes(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_segm_on_left_with_classes(self, user_cfg, inputs_path): + def test_segm_on_left_with_classes(self, user_cfg, inputs_with_segment): """ Optimization with left segmentation with classes without validation step. Classes are not available for segmentation step @@ -1042,20 +935,9 @@ def test_segm_on_left_with_classes(self, user_cfg, inputs_path): # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_segm": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_segm": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_segment # Import pandora plugins pandora.import_plugin() @@ -1067,7 +949,7 @@ def test_segm_on_left_with_classes(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_left_with_false_classes(self, user_cfg, inputs_path): + def test_classif_on_left_with_false_classes(self, user_cfg, inputs_with_classif): """ Optimization with left classification with false classes without validation step. Check that the check_conf function raises an error. @@ -1082,19 +964,10 @@ def test_classif_on_left_with_false_classes(self, user_cfg, inputs_path): # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["right_classif"] # Import pandora plugins pandora.import_plugin() @@ -1106,7 +979,7 @@ def test_classif_on_left_with_false_classes(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_left_without_classes(self, user_cfg, inputs_path): + def test_classif_on_left_without_classes(self, user_cfg, inputs_with_classif): """ Optimization with left classification with no classes without validation step. Check that the check_conf function raises an error. @@ -1118,19 +991,10 @@ def test_classif_on_left_without_classes(self, user_cfg, inputs_path): # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif + del user_cfg["input"]["right_classif"] # Import pandora plugins pandora.import_plugin() @@ -1142,7 +1006,7 @@ def test_classif_on_left_without_classes(self, user_cfg, inputs_path): with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_left_and_right_with_wrong_classes(self, user_cfg, inputs_path): + def test_classif_on_left_and_right_with_wrong_classes(self, user_cfg, inputs_with_classif): """ Optimization with left and right classification with wrong classes without validation step. Check that the check_conf function raises an error. @@ -1157,20 +1021,9 @@ def test_classif_on_left_and_right_with_wrong_classes(self, user_cfg, inputs_pat # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -1182,7 +1035,7 @@ def test_classif_on_left_and_right_with_wrong_classes(self, user_cfg, inputs_pat with pytest.raises(SystemExit): _ = check_conf(user_cfg, pandora_machine) - def test_classif_on_left_and_right_without_classes(self, user_cfg, inputs_path): + def test_classif_on_left_and_right_without_classes(self, user_cfg, inputs_with_classif): """ Optimization with left and right classification without classes without validation step. Check that the check_conf function raises an error. @@ -1194,20 +1047,9 @@ def test_classif_on_left_and_right_without_classes(self, user_cfg, inputs_path): # Remove validation step del user_cfg["pipeline"]["validation"] del user_cfg["pipeline"]["filter.after.validation"] - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" - user_cfg["pipeline"]["right_disp_map"]["method"] = "none" # Add inputs - user_cfg["input"] = { - "img_left": str(inputs_path / "left.png"), - "left_classif": str(inputs_path / "left_classif.tif"), - "img_right": str(inputs_path / "right.png"), - "right_classif": str(inputs_path / "right_classif.tif"), - "disp_min": -60, - "disp_max": 0, - "nodata_left": "NaN", - "nodata_right": "NaN", - } + user_cfg["input"] = inputs_with_classif # Import pandora plugins pandora.import_plugin() @@ -1230,8 +1072,7 @@ def test_user_initiate_3sgm_and_validation_with_one_geomprior_segmentation(self, "img_left": str(inputs_path / "left.png"), "img_right": str(inputs_path / "right.png"), "left_segm": str(inputs_path / "white_band_mask.png"), - "disp_min": -60, - "disp_max": 0, + "disp_left": [-60, 0], } # Add a segmentation geometric_prior @@ -1261,8 +1102,7 @@ def test_user_initiate_3sgm_and_validation_with_one_geomprior_classification(sel "img_left": str(inputs_path / "left.png"), "img_right": str(inputs_path / "right.png"), "right_classif": str(inputs_path / "white_band_mask.png"), - "disp_min": -60, - "disp_max": 0, + "disp_left": [-60, 0], } # Add a geometric_prior diff --git a/tests/test_libsgm.py b/tests/test_libsgm.py index ab87192..840ea1f 100644 --- a/tests/test_libsgm.py +++ b/tests/test_libsgm.py @@ -99,7 +99,7 @@ def test_libsgm(self, left_cones, right_cones, disp_left, disp_right, user_cfg): pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -125,7 +125,9 @@ def test_libsgm(self, left_cones, right_cones, disp_left, disp_right, user_cfg): # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(right["disparity_map"].data, disp_right, 2) <= 0.15 - def test_libsgm_negative_disparities(self, left_cones, right_cones, disp_left, disp_right, user_cfg): + def test_libsgm_negative_disparities( + self, left_cones, right_cones, disp_left, disp_right, user_cfg + ): """ Test pandora + plugin_libsgm, with negative disparities @@ -138,7 +140,7 @@ def test_libsgm_negative_disparities(self, left_cones, right_cones, disp_left, d pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, -1, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -176,7 +178,7 @@ def test_libsgm_positive_disparities(self, left_cones, right_cones, disp_left, d # Instantiate machine pandora_machine = PandoraMachine() - right, left = pandora.run(pandora_machine, right_cones, left_cones, 1, 60, user_cfg) + right, left = pandora.run(pandora_machine, right_cones, left_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -209,7 +211,7 @@ def test_libsgm_zncc(self, left_cones, right_cones, disp_left_zncc, disp_right_z pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the disparity maps are not equal, raise an error @@ -237,13 +239,18 @@ def test_number_of_disp(self, left_crafted, right_crafted, user_cfg): # Load plugins matching_cost_ = matching_cost.AbstractMatchingCost(**user_cfg["pipeline"]["matching_cost"]) - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) # Import pandora plugins pandora.import_plugin() # Computes the cost volume dataset - cv = matching_cost_.compute_cost_volume(img_left=left_crafted, img_right=right_crafted, disp_min=-2, disp_max=2) + cv = matching_cost_.compute_cost_volume( + img_left=left_crafted, + img_right=right_crafted, + grid_disp_min=np.full((left_crafted.dims["row"], left_crafted.dims["col"]), -2), + grid_disp_max=np.full((left_crafted.dims["row"], left_crafted.dims["col"]), 2), + ) # Disparities which give a minimum local cost, in indices disp_path = np.array( @@ -308,7 +315,7 @@ def test_number_of_disp_with_previous_confidence(self, left_crafted, right_craft # Load plugins matching_cost_ = matching_cost.AbstractMatchingCost(**user_cfg["pipeline"]["matching_cost"]) - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) confidence_ = cost_volume_confidence.AbstractCostVolumeConfidence( **user_cfg["pipeline"]["cost_volume_confidence"] ) @@ -317,7 +324,12 @@ def test_number_of_disp_with_previous_confidence(self, left_crafted, right_craft pandora.import_plugin() # Computes the cost volume dataset - cv = matching_cost_.compute_cost_volume(img_left=left_crafted, img_right=right_crafted, disp_min=-2, disp_max=2) + cv = matching_cost_.compute_cost_volume( + img_left=left_crafted, + img_right=right_crafted, + grid_disp_min=np.full((left_crafted.dims["row"], left_crafted.dims["col"]), -2), + grid_disp_max=np.full((left_crafted.dims["row"], left_crafted.dims["col"]), 2), + ) _, cv = confidence_.confidence_prediction(None, left_crafted, right_crafted, cv) # Disparities which give a minimum local cost, in indices disp_path = np.array( @@ -371,7 +383,7 @@ def test_number_of_disp_with_previous_confidence(self, left_crafted, right_craft # Check if the calculated confidence_measure is equal to the ground truth (same shape and all elements equals) np.testing.assert_array_equal(cv_updated["confidence_measure"].data[:, :, -1], gt_disp) - def test_apply_confidence_no_confidence(self, cost_volume, user_cfg): + def test_apply_confidence_no_confidence(self, left_crafted, cost_volume, user_cfg): """ Test plugin_libsgm apply_confidence function, with user asking for confidence usage, without any in dataser """ @@ -382,7 +394,7 @@ def test_apply_confidence_no_confidence(self, cost_volume, user_cfg): pandora.import_plugin() # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) # Test use_confidence = False @@ -406,7 +418,7 @@ def test_apply_confidence_no_confidence(self, cost_volume, user_cfg): # Check if confidence_is_int is right assert confidence_is_int - def test_apply_confidence_no_confidence_dataarray(self, cost_volume, user_cfg): + def test_apply_confidence_no_confidence_dataarray(self, left_crafted, cost_volume, user_cfg): """ Test plugin_libsgm apply_confidence function, with user asking for confidence usage, without any in dataser """ @@ -417,7 +429,7 @@ def test_apply_confidence_no_confidence_dataarray(self, cost_volume, user_cfg): pandora.import_plugin() # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) # Test use_confidence = True @@ -441,7 +453,7 @@ def test_apply_confidence_no_confidence_dataarray(self, cost_volume, user_cfg): # Check if confidence_is_int is right assert confidence_is_int - def test_apply_confidence_with_confidence_dataarray(self, cost_volume, user_cfg): + def test_apply_confidence_with_confidence_dataarray(self, left_crafted, cost_volume, user_cfg): """ Test plugin_libsgm apply_confidence function, with user asking for confidence usage, without any in dataser """ @@ -452,7 +464,7 @@ def test_apply_confidence_with_confidence_dataarray(self, cost_volume, user_cfg) pandora.import_plugin() # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) # Test use_confidence = True @@ -505,7 +517,7 @@ def test_optimization_layer_with_sgm(self, left_crafted, cost_volume, user_cfg): pandora.import_plugin() # Load plugins - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_crafted, **user_cfg["pipeline"]["optimization"]) cv_in = copy.deepcopy(cost_volume) @@ -536,7 +548,7 @@ def test_user_initiate_sgm_with_geomprior(self, left_cones, right_cones, user_cf # Pandora pipeline should fail with pytest.raises(SystemExit): - _, _ = pandora.run(pandora_machine, left_cones, right_cones, -60, -1, user_cfg) + _, _ = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) def test_optimization_layer_with_multiband(self, user_cfg, left_rgb, right_rgb): """ @@ -553,13 +565,18 @@ def test_optimization_layer_with_multiband(self, user_cfg, left_rgb, right_rgb): # Load plugins matching_cost_ = matching_cost.AbstractMatchingCost(**user_cfg["pipeline"]["matching_cost"]) - optimization_ = optimization.AbstractOptimization(**user_cfg["pipeline"]["optimization"]) + optimization_ = optimization.AbstractOptimization(left_rgb, **user_cfg["pipeline"]["optimization"]) # Import pandora plugins pandora.import_plugin() # Computes the cost volume dataset - cv = matching_cost_.compute_cost_volume(img_left=left_rgb, img_right=right_rgb, disp_min=-60, disp_max=0) + cv = matching_cost_.compute_cost_volume( + img_left=left_rgb, + img_right=right_rgb, + grid_disp_min=np.full((left_rgb.dims["row"], left_rgb.dims["col"]), -60), + grid_disp_max=np.full((left_rgb.dims["row"], left_rgb.dims["col"]), 0), + ) cv_in = copy.deepcopy(cv) # Get invalid disparities of the cost volume invalid_disp = np.isnan(cv["cost_volume"].data) diff --git a/tests/test_plugin_python.py b/tests/test_plugin_python.py index 7ddc8cd..4e34471 100644 --- a/tests/test_plugin_python.py +++ b/tests/test_plugin_python.py @@ -64,7 +64,7 @@ def test_libsgm(self, left_cones, right_cones, disp_left, disp_right, user_cfg): pandora.import_plugin() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -90,7 +90,9 @@ def test_libsgm(self, left_cones, right_cones, disp_left, disp_right, user_cfg): # If the percentage of pixel errors ( error if ground truth - calculate > 2) is > 0.15, raise an error assert common.error(right["disparity_map"].data, disp_right, 2) <= 0.15 - def test_libsgm_negative_disparities(self, left_cones, right_cones, disp_left, disp_right, user_cfg): + def test_libsgm_negative_disparities( + self, left_cones, right_cones, disp_left, disp_right, user_cfg + ): """ Test pandora + plugin_libsgm, with negative disparities @@ -102,7 +104,7 @@ def test_libsgm_negative_disparities(self, left_cones, right_cones, disp_left, d pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, -1, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -139,7 +141,7 @@ def test_libsgm_positive_disparities(self, left_cones, right_cones, disp_left, d # Instantiate machine pandora_machine = PandoraMachine() - right, left = pandora.run(pandora_machine, right_cones, left_cones, 1, 60, user_cfg) + right, left = pandora.run(pandora_machine, right_cones, left_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error @@ -172,7 +174,7 @@ def test_libsgm_zncc(self, left_cones, right_cones, disp_left_zncc, disp_right_z pandora_machine = PandoraMachine() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_cones, right_cones, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_cones, right_cones, user_cfg) # Compares the calculated left disparity map with the ground truth # If the disparity maps are not equal, raise an error @@ -198,7 +200,7 @@ def test_libsgm_multiband(self, disp_left, disp_right, user_cfg, left_rgb, right pandora.import_plugin() # Run the pandora pipeline - left, right = pandora.run(pandora_machine, left_rgb, right_rgb, -60, 0, user_cfg) + left, right = pandora.run(pandora_machine, left_rgb, right_rgb, user_cfg) # Compares the calculated left disparity map with the ground truth # If the percentage of pixel errors is > 0.20, raise an error diff --git a/tests/testresources/conf/3sgm.json b/tests/testresources/conf/3sgm.json index 9d2ad0c..e508f12 100644 --- a/tests/testresources/conf/3sgm.json +++ b/tests/testresources/conf/3sgm.json @@ -1,18 +1,14 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "census", "window_size": 5, "subpix": 1 }, - "cost_volume_confidence" : { + "cost_volume_confidence": { "confidence_method": "std_intensity" }, - "optimization" : { + "optimization": { "optimization_method": "3sgm", "overcounting": false, "penalty": { @@ -29,19 +25,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - diff --git a/tests/testresources/conf/sgm.json b/tests/testresources/conf/sgm.json index c97b691..48baa06 100644 --- a/tests/testresources/conf/sgm.json +++ b/tests/testresources/conf/sgm.json @@ -1,18 +1,14 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "census", "window_size": 5, "subpix": 1 }, - "cost_volume_confidence" : { + "cost_volume_confidence": { "confidence_method": "std_intensity" }, - "optimization" : { + "optimization": { "optimization_method": "sgm", "overcounting": false, "penalty": { @@ -29,19 +25,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - diff --git a/tests/testresources/conf/sgm_python.json b/tests/testresources/conf/sgm_python.json index a25bce9..e4eb8b1 100644 --- a/tests/testresources/conf/sgm_python.json +++ b/tests/testresources/conf/sgm_python.json @@ -1,16 +1,11 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "census", "window_size": 5, "subpix": 1 }, - - "optimization" : { + "optimization": { "optimization_method": "sgm", "sgm_version": "python_libsgm", "overcounting": false, @@ -21,7 +16,6 @@ "penalty_method": "sgm_penalty" } }, - "disparity": { "disparity_method": "wta", "invalid_disparity": -9999 @@ -29,19 +23,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - diff --git a/tests/testresources/conf/sgm_python_parall.json b/tests/testresources/conf/sgm_python_parall.json index 849df9e..e0201a9 100644 --- a/tests/testresources/conf/sgm_python_parall.json +++ b/tests/testresources/conf/sgm_python_parall.json @@ -1,16 +1,11 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "census", "window_size": 5, "subpix": 1 }, - - "optimization" : { + "optimization": { "optimization_method": "sgm", "sgm_version": "python_libsgm_parall", "overcounting": false, @@ -21,7 +16,6 @@ "penalty_method": "sgm_penalty" } }, - "disparity": { "disparity_method": "wta", "invalid_disparity": -9999 @@ -29,19 +23,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - diff --git a/tests/testresources/conf/sgm_zncc.json b/tests/testresources/conf/sgm_zncc.json index 74e368d..a5b6821 100644 --- a/tests/testresources/conf/sgm_zncc.json +++ b/tests/testresources/conf/sgm_zncc.json @@ -1,16 +1,11 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "zncc", "window_size": 5, "subpix": 1 }, - - "optimization" : { + "optimization": { "optimization_method": "sgm", "overcounting": false, "penalty": { @@ -20,7 +15,6 @@ "penalty_method": "sgm_penalty" } }, - "disparity": { "disparity_method": "wta", "invalid_disparity": -9999 @@ -28,19 +22,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - diff --git a/tests/testresources/conf/sgm_zncc_python.json b/tests/testresources/conf/sgm_zncc_python.json index 8ca4e51..325cd16 100644 --- a/tests/testresources/conf/sgm_zncc_python.json +++ b/tests/testresources/conf/sgm_zncc_python.json @@ -1,16 +1,11 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "zncc", "window_size": 5, "subpix": 1 }, - - "optimization" : { + "optimization": { "optimization_method": "sgm", "sgm_version": "python_libsgm", "overcounting": false, @@ -21,7 +16,6 @@ "penalty_method": "sgm_penalty" } }, - "disparity": { "disparity_method": "wta", "invalid_disparity": -9999 @@ -29,20 +23,17 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 } } } - - diff --git a/tests/testresources/conf/sgm_zncc_python_parall.json b/tests/testresources/conf/sgm_zncc_python_parall.json index 6dc18b0..aeac3bb 100644 --- a/tests/testresources/conf/sgm_zncc_python_parall.json +++ b/tests/testresources/conf/sgm_zncc_python_parall.json @@ -1,16 +1,11 @@ { - "pipeline": - { - "right_disp_map": { - "method": "accurate" - }, - "matching_cost" : { + "pipeline": { + "matching_cost": { "matching_cost_method": "zncc", "window_size": 5, "subpix": 1 }, - - "optimization" : { + "optimization": { "optimization_method": "sgm", "sgm_version": "python_libsgm_parall", "overcounting": false, @@ -21,7 +16,6 @@ "penalty_method": "sgm_penalty" } }, - "disparity": { "disparity_method": "wta", "invalid_disparity": -9999 @@ -29,16 +23,15 @@ "refinement": { "refinement_method": "vfit" }, - "filter" : { + "filter": { "filter_method": "median", "filter_size": 3 }, - - "validation" : { - "validation_method": "cross_checking", + "validation": { + "validation_method": "cross_checking_accurate", "cross_checking_threshold": 1 }, - "filter.after.validation" : { + "filter.after.validation": { "filter_method": "median", "filter_size": 3 }