From f2623225d2aca1665c874307618a5124942ed03e Mon Sep 17 00:00:00 2001 From: Marie Leconte Date: Fri, 31 Jan 2025 11:13:15 +0100 Subject: [PATCH 1/2] fix: disparity to index with subpix on cost_volume --- pandora2d/refinement/dichotomy_cpp.py | 71 +++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/pandora2d/refinement/dichotomy_cpp.py b/pandora2d/refinement/dichotomy_cpp.py index 4ef3926..1948771 100644 --- a/pandora2d/refinement/dichotomy_cpp.py +++ b/pandora2d/refinement/dichotomy_cpp.py @@ -120,10 +120,12 @@ def refinement_method( # pylint: disable=too-many-locals # TO BE REMOVE WHEN CRITERIA MAP WILL BE FINISHED criteria_map = create_criteria_map(cost_volumes, disp_map, img_left, invalid_disparity_map_mask) + subpixel = cost_volumes.attrs["subpixel"] + # Convert disparity maps to np.array to optimise performance # Transforming disparity maps into index maps - row_map = (row_map.to_numpy() - cost_volumes.disp_row.values[0]).astype(np.float64) - col_map = (col_map.to_numpy() - cost_volumes.disp_col.values[0]).astype(np.float64) + row_map = (disparity_to_index(row_map, cost_volumes.disp_row.values[0], subpixel)).astype(np.float64) + col_map = (disparity_to_index(col_map, cost_volumes.disp_col.values[0], subpixel)).astype(np.float64) refinement_bind.compute_dichotomy( cost_volumes.cost_volumes.data.ravel().astype(np.float64), @@ -132,14 +134,14 @@ def refinement_method( # pylint: disable=too-many-locals cost_values.ravel().astype(np.float64), criteria_map.ravel(), refinement_bind.Cost_volume_size(cost_volumes.cost_volumes.shape), - cost_volumes.attrs["subpixel"], + subpixel, self.cfg["iterations"], self.filter.cpp_instance, cost_volumes.attrs["type_measure"], ) # Inverse transforming index maps into disparity maps - col_map += cost_volumes.disp_col.values[0] - row_map += cost_volumes.disp_row.values[0] + col_map = index_to_disparity(col_map, cost_volumes.disp_col.values[0], subpixel) + row_map = index_to_disparity(row_map, cost_volumes.disp_row.values[0], subpixel) # Log about precision subpixel_to_iteration = cost_volumes.attrs["subpixel"].bit_length() - 1 @@ -149,6 +151,65 @@ def refinement_method( # pylint: disable=too-many-locals return col_map, row_map, cost_values +def disparity_to_index(disparity_map: xr.DataArray, shift: int, subpixel: int) -> np.ndarray: + """ + Transform a disparity map to index map. Indexes correspond to (row/col) disparities in cost volume. + + Example: + - with subpixel=1 : + + * disparity_map = -2 -1 -1 1 + -1 0 -1 -1 + 0 1 1 1 + + * disparities range = [-4 -3 -2 -1 0 1 2 3] + + * index_map = 2 3 3 5 + 3 4 3 3 + 4 5 5 5 + + - with subpixel=2 : + + * disparity_map = -4 -2 -1.5 -2.5 + -4 -1 -1 -1 + -4 -1.5 -1 -1.5 + + * disparities range = [-4 -3.5 -3 -2.5 -2 -1.5 -1] + + * index_map = 0 4 5 3 + 0 6 6 6 + 0 5 6 5 + + :param disparity_map: 2D map + :type disparity_map: xarray.DataArray + :param shift: the first value of the disparity coordinates in the cost volume + :type shift: int + :param subpixel: :sub-sampling of cost_volume + :type subpixel: int + :return: the index map + :rtype: np.ndarray + """ + return (disparity_map.to_numpy() - shift) * subpixel + + +def index_to_disparity(index_map: np.ndarray, shift: int, subpixel: int) -> np.ndarray: + """ + Transform an index map to disparity map. Indexes correspond to (row/col) disparities in cost volume. + + For examples, see disparity_to_index method. + + :param index_map: 2D map + :type index_map: np.ndarray + :param shift: the first value of the disparity coordinates in the cost volume + :type shift: int + :param subpixel: :sub-sampling of cost_volume + :type subpixel: int + :return: the index map + :rtype: np.ndarray + """ + return (index_map / subpixel) + shift + + def create_cost_values_map(cost_volumes: xr.Dataset, disp_map: xr.Dataset) -> Tuple[np.ndarray, np.ndarray]: """ Return the map with best matching score From baf6b211dbeac7477c0fcea42d9d15e15f38910a Mon Sep 17 00:00:00 2001 From: Marie Leconte Date: Fri, 31 Jan 2025 16:20:32 +0100 Subject: [PATCH 2/2] test: add test to check change disparity to index and reverse opertation --- .../test_refinement/test_dichotomy.py | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/tests/unit_tests/test_refinement/test_dichotomy.py b/tests/unit_tests/test_refinement/test_dichotomy.py index 4ea3121..f1cdf0d 100644 --- a/tests/unit_tests/test_refinement/test_dichotomy.py +++ b/tests/unit_tests/test_refinement/test_dichotomy.py @@ -1191,3 +1191,98 @@ def test_non_uniform_disparity_grid( # pylint: disable=too-many-arguments # For point [1,0] col disparity range is not [min_disparity_col, max_disparity_col] but [min_disparity_col, 0], # we check that resulting disparity row is in this range. assert result_disp_col[1, 0] in range(min_disparity_col, 0 + 1) + + +class TestChangeDisparityToIndex: + + @pytest.mark.parametrize( + ["map", "shift", "subpixel", "expected"], + [ + pytest.param( + xr.DataArray( + data=[[1, 2, 3], [2, 2, 3]], + dims=("row", "col"), + coords={"row": np.arange(2), "col": np.arange(3)}, + ), + 1, # disparity range starts at 1 + 1, + np.array([[0, 1, 2], [1, 1, 2]]), + id="positive disparity", + ), + pytest.param( + xr.DataArray( + data=[[-1, -2, -3], [-2, -2, -3]], + dims=("row", "col"), + coords={"row": np.arange(2), "col": np.arange(3)}, + ), + -4, # disparity range starts at -4 + 1, + np.array([[3, 2, 1], [2, 2, 1]]), + id="negative disparity", + ), + pytest.param( + xr.DataArray( + data=[[-1, -2.5, -3], [-2, -2.5, -3]], + dims=("row", "col"), + coords={"row": np.arange(2), "col": np.arange(3)}, + ), + -4, # disparity range starts at -4 + 2, + np.array([[6, 3, 2], [4, 3, 2]]), + id="negative disparity and subpixel=0.5", + ), + pytest.param( + xr.DataArray( + data=[[-1, -2.5, -3], [-2, -2.5, -3]], + dims=("row", "col"), + coords={"row": np.arange(2), "col": np.arange(3)}, + ), + -4, # disparity range starts at -4 + 4, + np.array([[12.0, 6, 4.0], [8, 6, 4]]), + id="negative disparity and subpixel=0.25", + ), + ], + ) + def test_disparity_to_index(self, map, shift, subpixel, expected): + """Test disparity_to_index method""" + result = refinement.dichotomy_cpp.disparity_to_index(map, shift, subpixel) + np.testing.assert_array_equal(result, expected) + + @pytest.mark.parametrize( + ["map", "shift", "subpixel", "expected"], + [ + pytest.param( + np.array([[0, 1, 2], [1, 1, 2]]), + 1, # disparity range starts at 1 + 1, + np.array([[1, 2, 3], [2, 2, 3]]), + id="positive disparity", + ), + pytest.param( + np.array([[3, 2, 1], [2, 2, 1]]), + -4, # disparity range starts at -4 + 1, + np.array([[-1, -2, -3], [-2, -2, -3]]), + id="negative disparity", + ), + pytest.param( + np.array([[3.0625, 2, 1.0625], [2, 2, 1]]), + -4, # disparity range starts at -4 and precision = 0.0625 + 2, + np.array([[-2.46875, -3.0, -3.46875], [-3.0, -3.0, -3.5]]), + id="negative disparity and subpixel=0.5", + ), + pytest.param( + np.array([[3.0625, 2, 1.0625], [2, 2, 1]]), + -4, # disparity range starts at -4 and precision = 0.0625 + 4, + np.array([[-3.234375, -3.5, -3.734375], [-3.5, -3.5, -3.75]]), + id="negative disparity and subpixel=0.5", + ), + ], + ) + def test_index_to_disparity(self, map, shift, subpixel, expected): + """Test index_to_disparity_method""" + result = refinement.dichotomy_cpp.index_to_disparity(map, shift, subpixel) + np.testing.assert_array_equal(result, expected)