Skip to content

Commit

Permalink
Merge branch '126-add-functional-tests-dichotomy' into 'release'
Browse files Browse the repository at this point in the history
Resolve "Dichotomie: Ajout de tests fonctionnels"

See merge request 3d/PandoraBox/pandora2d!142
  • Loading branch information
PhML committed Aug 30, 2024
2 parents 059de9f + 89ff71a commit 487b19c
Show file tree
Hide file tree
Showing 72 changed files with 576 additions and 35 deletions.
6 changes: 6 additions & 0 deletions docs/source/userguide/step_by_step/matching_cost.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Configuration and parameters
- 1
- [1,2,4]
- No
* - spline_order
- Spline order used for interpolation when subpix > 1
- int
- 1
- > 0 and < 6
- No


.. note::
Expand Down
18 changes: 13 additions & 5 deletions pandora2d/img_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def remove_roi_margins(dataset: xr.Dataset, cfg: Dict):


def row_zoom_img(
img: np.ndarray, ny: int, subpix: int, coords: Coordinates, ind: int, no_data: Union[int, str]
img: np.ndarray, ny: int, subpix: int, coords: Coordinates, ind: int, no_data: Union[int, str], order: int = 1
) -> xr.Dataset:
"""
Return a list that contains the shifted right images in row
Expand All @@ -355,13 +355,15 @@ def row_zoom_img(
:type ind: int
:param no_data: no_data value in img
:type no_data: Union[int, str]
:param order: The order of the spline interpolation, default is 1. The order has to be in the range 0-5.
:type order: int, optional
:return: an array that contains the shifted right images in row
:rtype: array of xarray.Dataset
"""

shift = 1 / subpix
# For each index, shift the right image for subpixel precision 1/subpix*index
data = zoom(img, ((ny * subpix - (subpix - 1)) / float(ny), 1), order=1)[ind::subpix, :]
data = zoom(img, ((ny * subpix - (subpix - 1)) / float(ny), 1), order=order)[ind::subpix, :]

# Add a row full of no data at the end of data have the same shape as img
# It enables to use Pandora's compute_cost_volume() methods,
Expand All @@ -379,7 +381,7 @@ def row_zoom_img(


def col_zoom_img(
img: np.ndarray, nx: int, subpix: int, coords: Coordinates, ind: int, no_data: Union[int, str]
img: np.ndarray, nx: int, subpix: int, coords: Coordinates, ind: int, no_data: Union[int, str], order: int = 1
) -> xr.Dataset:
"""
Return a list that contains the shifted right images in col
Expand All @@ -398,13 +400,15 @@ def col_zoom_img(
:type ind: int
:param no_data: no_data value in img
:type no_data: Union[int, str]
:param order: The order of the spline interpolation, default is 1. The order has to be in the range 0-5.
:type order: int, optional
:return: an array that contains the shifted right images in col
:rtype: array of xarray.Dataset
"""

shift = 1 / subpix
# For each index, shift the right image for subpixel precision 1/subpix*index
data = zoom(img, (1, (nx * subpix - (subpix - 1)) / float(nx)), order=1)[:, ind::subpix]
data = zoom(img, (1, (nx * subpix - (subpix - 1)) / float(nx)), order=order)[:, ind::subpix]

# Add a col full of no data at the end of data to have the same shape as img
# It enables to use Pandora's compute_cost_volume() methods,
Expand All @@ -420,7 +424,7 @@ def col_zoom_img(
)


def shift_subpix_img(img_right: xr.Dataset, subpix: int, row: bool = True) -> List[xr.Dataset]:
def shift_subpix_img(img_right: xr.Dataset, subpix: int, row: bool = True, order: int = 1) -> List[xr.Dataset]:
"""
Return an array that contains the shifted right images
Expand All @@ -430,6 +434,8 @@ def shift_subpix_img(img_right: xr.Dataset, subpix: int, row: bool = True) -> Li
:type subpix: int
:param column: column to shift (otherwise row)
:type column: bool
:param order: The order of the spline interpolation, default is 1. The order has to be in the range 0-5.
:type order: int, optional
:return: an array that contains the shifted right images
:rtype: array of xarray.Dataset
"""
Expand All @@ -446,6 +452,7 @@ def shift_subpix_img(img_right: xr.Dataset, subpix: int, row: bool = True) -> Li
img_right.coords,
ind,
img_right.attrs["no_data_img"],
order,
).assign_attrs(img_right.attrs)
)
else:
Expand All @@ -457,6 +464,7 @@ def shift_subpix_img(img_right: xr.Dataset, subpix: int, row: bool = True) -> Li
img_right.coords,
ind,
img_right.attrs["no_data_img"],
order,
).assign_attrs(img_right.attrs)
)

Expand Down
13 changes: 12 additions & 1 deletion pandora2d/matching_cost/matching_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def cfg(self) -> Dict[str, Union[str, int, List[int]]]:
"step": self._step,
"window_size": self._window_size,
"subpix": self._subpix,
"spline_order": self._spline_order,
}

@property
Expand Down Expand Up @@ -112,6 +113,16 @@ def _subpix(self) -> int:
"""
return self.pandora_matching_cost_._subpix # pylint: disable=W0212 protected-access

@property
def _spline_order(self) -> int:
"""
Get spline_order, parameter specific to pandora
:return: spline_order: spline_order used
:rtype: spline_order: int
"""
return self.pandora_matching_cost_._spline_order # pylint: disable=W0212 protected-access

@property
def margins(self) -> Margins:
"""
Expand Down Expand Up @@ -326,7 +337,7 @@ def compute_cost_volumes(
row_index = None

# Contains the shifted right images (with subpixel)
imgs_right_shift_subpixel = img_tools.shift_subpix_img(img_right, self._subpix)
imgs_right_shift_subpixel = img_tools.shift_subpix_img(img_right, self._subpix, order=self._spline_order)

for idx, disp_row in enumerate(disps_row):
i_right = int((disp_row % 1) * self._subpix)
Expand Down
30 changes: 23 additions & 7 deletions pandora2d/refinement/dichotomy.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def refinement_method( # pylint: disable=too-many-locals
# Syntax disp_row_init[...] is for assign value back to row_map with np.nditer
(pos_disp_row_init, pos_disp_col_init), disp_row_init[...], disp_col_init[...], cost_value[...] = (
search_new_best_point(
cost_surface.data,
cost_surface,
precision,
(disp_row_init, disp_col_init), # type: ignore # Reason: is 0 dim array
(pos_disp_row_init, pos_disp_col_init),
Expand Down Expand Up @@ -269,6 +269,7 @@ def __init__(self, cost_volumes: xr.Dataset):
:type disparity_margins: Margins
"""
self.cost_volumes = cost_volumes
self.cost_volumes["cost_volumes"].attrs.update({"subpixel": cost_volumes.attrs["subpixel"]})

def __getitem__(self, item):
"""Get cost surface of coordinates item where item is (row, col)."""
Expand All @@ -295,7 +296,7 @@ def all_same(sequence):


def search_new_best_point(
cost_surface: np.ndarray,
cost_surface: xr.DataArray,
precision: float,
initial_disparity: Union[Tuple[np.floating, np.floating], Tuple[int, int]],
initial_position: Union[Tuple[np.floating, np.floating], Tuple[int, int]],
Expand All @@ -307,8 +308,8 @@ def search_new_best_point(
Find best position and cost after interpolation of cost surface for given precision.
:param cost_surface: Disparities in rows and cols of a point
:type cost_surface: np.ndarray
:param precision: subpixellic precision to use
:type cost_surface: xr.Dataarray with subpix attribute
:param precision: subpixellic disparity precision to use
:type precision: float
:param initial_disparity: initial disparities (disp_row, disp_col)
:type initial_disparity: Union[Tuple[np.floating, np.floating], Tuple[int, int]]
Expand Down Expand Up @@ -336,17 +337,32 @@ def search_new_best_point(
disp_row_shifts = np.array([-1, -1, -1, 0, 0, 0, 1, 1, 1], dtype=np.float32) * precision
disp_col_shifts = np.array([-1, 0, 1, -1, 0, 1, -1, 0, 1], dtype=np.float32) * precision

# Whatever the cost_surface.attrs["subpixel"] value, the first precision in the cost surface is always 0.5
# Then we multiply by cost_surface.attrs["subpixel"] to get right new_cols and new_rows

# When there is no subpixel (it equals to 1), precision shift and index shift match:
# the precision shift between two points is 1. So shifting from 0.5 precision corresponds to shift index of 0.5.
# But when there is a subpixel, they do not match anymore:
# in this case, the precision shift between two points is 1/subpix.
# So to get the index corresponding to a given precision shift, we need to multiply this value by subpix.
# For example when subix equals 2, the precision shift between two points is 0.5 while the index shift is still 1.
# So in this case, shifting from 0.5 precision corresponds to shift index of 1
# (`index_shift = 1 = 0.5 * 2 = precision_shift * subpix`)
# In the same way, shifting from 0.25 precision corresponds to shift index of 0.5
# (`index_shift = 0.5 = 0.25 * 2 = precision_shift * subpix`)

# disp_row are along columns in cost_surface, then new_cols are computed from initial_pos_disp_row
new_cols = disp_row_shifts + initial_pos_disp_row
new_cols = disp_row_shifts * cost_surface.attrs["subpixel"] + initial_pos_disp_row

# disp_col are along rows in cost_surface, then new_rows are computed from initial_pos_disp_col
new_rows = disp_col_shifts + initial_pos_disp_col
new_rows = disp_col_shifts * cost_surface.attrs["subpixel"] + initial_pos_disp_col

# New subpixel disparity values
new_rows_disp = disp_row_shifts + initial_disp_row
new_cols_disp = disp_col_shifts + initial_disp_col

# Interpolate points at positions (new_rows[i], new_cols[i])
candidates = filter_dicho.interpolate(cost_surface, (new_cols, new_rows))
candidates = filter_dicho.interpolate(cost_surface.data, (new_cols, new_rows))

# In case a NaN is present in the kernel, candidates will be all-NaNs. Let’s restore initial_position value so
# that best candidate search will be able to find it.
Expand Down
18 changes: 18 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
import pathlib
import re

import json
import numpy as np
import pytest
import rasterio
from pandora.common import write_data_array
import xarray as xr

import pandora2d


def pytest_collection_modifyitems(config, items):
"""
Expand Down Expand Up @@ -219,3 +222,18 @@ def random_seed():
@pytest.fixture()
def random_generator(random_seed):
return np.random.default_rng(random_seed)


@pytest.fixture()
def run_pipeline(tmp_path):
"""Fixture that returns a function to run a pipeline and which returns the output directory path."""

def run(configuration, output_dir="output"):
config_path = tmp_path / "config.json"
with config_path.open("w", encoding="utf-8") as file_:
json.dump(configuration, file_, indent=2)

pandora2d.main(str(config_path), str(tmp_path / output_dir), verbose=False)
return tmp_path

return run
19 changes: 0 additions & 19 deletions tests/functional_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,8 @@
#
"""Module with global test fixtures."""

import json

import pytest

import pandora2d


@pytest.fixture()
def run_pipeline(tmp_path):
"""Fixture that returns a function to run a pipeline and which returns the output directory path."""

def run(configuration, output_dir="output"):
config_path = tmp_path / "config.json"
with config_path.open("w", encoding="utf-8") as file_:
json.dump(configuration, file_, indent=2)

pandora2d.main(str(config_path), str(tmp_path / output_dir), verbose=False)
return tmp_path

return run


@pytest.fixture()
def correct_pipeline_without_refinement():
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 487b19c

Please sign in to comment.