Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cb413c1

Browse files
committed
Fix an off-by-half-pixel bug when resampling under a nonaffine transform
1 parent a916809 commit cb413c1

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

lib/matplotlib/tests/test_image.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import urllib.request
1010

1111
import numpy as np
12-
from numpy.testing import assert_array_equal
12+
from numpy.testing import assert_allclose, assert_array_equal
1313
from PIL import Image
1414

1515
import matplotlib as mpl
@@ -18,7 +18,7 @@
1818
from matplotlib.image import (AxesImage, BboxImage, FigureImage,
1919
NonUniformImage, PcolorImage)
2020
from matplotlib.testing.decorators import check_figures_equal, image_comparison
21-
from matplotlib.transforms import Bbox, Affine2D, TransformedBbox
21+
from matplotlib.transforms import Bbox, Affine2D, Transform, TransformedBbox
2222
import matplotlib.ticker as mticker
2323

2424
import pytest
@@ -1641,6 +1641,37 @@ def test__resample_valid_output():
16411641
resample(np.zeros((9, 9)), out)
16421642

16431643

1644+
@pytest.mark.parametrize("data, interpolation, expected",
1645+
[(np.array([[0.1, 0.3, 0.2]]), mpl._image.NEAREST,
1646+
np.array([[0.1, 0.1, 0.1, 0.3, 0.3, 0.3, 0.3, 0.2, 0.2, 0.2]])),
1647+
(np.array([[0.1, 0.3, 0.2]]), mpl._image.BILINEAR,
1648+
np.array([[0.1, 0.1, 0.15078125, 0.21096191, 0.27033691, 0.28476562, 0.2546875, 0.22460938, 0.20002441, 0.20002441]])),
1649+
]
1650+
)
1651+
def test__resample_nonaffine(data, interpolation, expected):
1652+
# Test that equivalent affine and nonaffine transforms give the same resampling result
1653+
1654+
# Create a simple affine transform for scaling the input array
1655+
affine_transform = Affine2D().scale(sx=expected.shape[1] / data.shape[1], sy=1)
1656+
1657+
affine_result = np.empty_like(expected)
1658+
mpl._image.resample(data, affine_result, affine_transform, interpolation=interpolation)
1659+
assert_allclose(affine_result, expected)
1660+
1661+
# Create a nonaffine version of the same transform by compositing with a nonaffine identity transform
1662+
class NonAffineIdentityTransform(Transform):
1663+
input_dims = 2
1664+
output_dims = 2
1665+
1666+
def inverted(self):
1667+
return self
1668+
nonaffine_transform = NonAffineIdentityTransform() + affine_transform
1669+
1670+
nonaffine_result = np.empty_like(expected)
1671+
mpl._image.resample(data, nonaffine_result, nonaffine_transform, interpolation=interpolation)
1672+
assert_allclose(nonaffine_result, expected)
1673+
1674+
16441675
def test_axesimage_get_shape():
16451676
# generate dummy image to test get_shape method
16461677
ax = plt.gca()

src/_image_wrapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ _get_transform_mesh(const py::object& transform, const py::ssize_t *dims)
6666

6767
for (auto y = 0; y < dims[0]; ++y) {
6868
for (auto x = 0; x < dims[1]; ++x) {
69-
*p++ = (double)x;
70-
*p++ = (double)y;
69+
*p++ = (double)x + 0.5;
70+
*p++ = (double)y + 0.5;
7171
}
7272
}
7373

0 commit comments

Comments
 (0)