From 7e0efe5514417b573f411ce4f372d57be69e0a1a Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Wed, 20 Mar 2019 21:18:41 -0700 Subject: [PATCH] ENH: anti-alias down-sampled images --- .flake8 | 1 + doc/api/next_api_changes/2019-07-17-JMK.rst | 22 +++++ .../image_antialiasing.py | 81 ++++++++++++++++ .../interpolation_methods.py | 5 +- lib/matplotlib/axes/_axes.py | 20 +++- lib/matplotlib/image.py | 40 ++++++-- lib/matplotlib/rcsetup.py | 2 +- lib/matplotlib/tests/test_axes.py | 34 +++++++ lib/matplotlib/tests/test_image.py | 96 ++++++++++++++++++- lib/matplotlib/tests/test_patheffects.py | 2 +- lib/mpl_toolkits/tests/test_axes_grid.py | 3 + lib/mpl_toolkits/tests/test_axes_grid1.py | 4 +- matplotlibrc.template | 2 +- 13 files changed, 289 insertions(+), 23 deletions(-) create mode 100644 doc/api/next_api_changes/2019-07-17-JMK.rst create mode 100644 examples/images_contours_and_fields/image_antialiasing.py diff --git a/.flake8 b/.flake8 index 18ccee841903..152895615a78 100644 --- a/.flake8 +++ b/.flake8 @@ -94,6 +94,7 @@ per-file-ignores = examples/images_contours_and_fields/contourf_hatching.py: E402 examples/images_contours_and_fields/contourf_log.py: E402 examples/images_contours_and_fields/demo_bboximage.py: E402 + examples/images_contours_and_fields/image_antialiasing.py: E402 examples/images_contours_and_fields/image_clip_path.py: E402 examples/images_contours_and_fields/image_demo.py: E402 examples/images_contours_and_fields/image_masked.py: E402 diff --git a/doc/api/next_api_changes/2019-07-17-JMK.rst b/doc/api/next_api_changes/2019-07-17-JMK.rst new file mode 100644 index 000000000000..6e15b9023b77 --- /dev/null +++ b/doc/api/next_api_changes/2019-07-17-JMK.rst @@ -0,0 +1,22 @@ +Default interpolation for `image` is new "antialiased" option +------------------------------------------------------------- + +Images displayed in Matplotlib previously used nearest-neighbor +interpolation, leading to aliasing effects for downscaling and non-integer +upscaling. + +New default for :rc:`image.interpolation` is the new option "antialiased". +`imshow(A, interpolation='antialiased')` will apply a Hanning filter when +resampling the data in A for display (or saving to file) *if* the upsample +rate is less than a factor of three, and not an integer; downsampled data is +always smoothed at resampling. + +To get the old behavior, set :rc:`interpolation` to the old default "nearest" +(or specify the ``interpolation`` kwarg of `.Axes.imshow`) + +To always get the anti-aliasing behavior, no matter what the up/down sample +rate, set :rc:`interpolation` to "hanning" (or one of the other filters +available. + +Note that the "hanning" filter was chosen because it has only a modest +performance penalty. Anti-aliasing can be improved with other filters. diff --git a/examples/images_contours_and_fields/image_antialiasing.py b/examples/images_contours_and_fields/image_antialiasing.py new file mode 100644 index 000000000000..3d2dc32c2ef4 --- /dev/null +++ b/examples/images_contours_and_fields/image_antialiasing.py @@ -0,0 +1,81 @@ +""" +================== +Image Antialiasing +================== + +Images are represented by discrete pixels, either on the screen or in an +image file. When data that makes up the image has a different resolution +than its representation on the screen we will see aliasing effects. + +The default image interpolation in Matplotlib is 'antialiased'. This uses a +hanning interpolation for reduced aliasing in most situations. Only when there +is upsampling by a factor of 1, 2 or >=3 is 'nearest' neighbor interpolation +used. + +Other anti-aliasing filters can be specified in `.Axes.imshow` using the +*interpolation* kwarg. +""" + +import numpy as np +import matplotlib.pyplot as plt + +############################################################################### +# First we generate an image with varying frequency content: +x = np.arange(500) / 500 - 0.5 +y = np.arange(500) / 500 - 0.5 + +X, Y = np.meshgrid(x, y) +R = np.sqrt(X**2 + Y**2) +f0 = 10 +k = 250 +a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2)) + + +############################################################################### +# The following images are subsampled from 1000 data pixels to 604 rendered +# pixels. The Moire patterns in the "nearest" interpolation are caused by the +# high-frequency data being subsampled. The "antialiased" image +# still has some Moire patterns as well, but they are greatly reduced. +fig, axs = plt.subplots(1, 2, figsize=(7, 4), constrained_layout=True) +for n, interp in enumerate(['nearest', 'antialiased']): + im = axs[n].imshow(a, interpolation=interp, cmap='gray') + axs[n].set_title(interp) +plt.show() + +############################################################################### +# Even up-sampling an image will lead to Moire patterns unless the upsample +# is an integer number of pixels. +fig, ax = plt.subplots(1, 1, figsize=(5.3, 5.3)) +ax.set_position([0, 0, 1, 1]) +im = ax.imshow(a, interpolation='nearest', cmap='gray') +plt.show() + +############################################################################### +# The patterns aren't as bad, but still benefit from anti-aliasing +fig, ax = plt.subplots(1, 1, figsize=(5.3, 5.3)) +ax.set_position([0, 0, 1, 1]) +im = ax.imshow(a, interpolation='antialiased', cmap='gray') +plt.show() + +############################################################################### +# If the small Moire patterns in the default "hanning" antialiasing are +# still undesireable, then we can use other filters. +fig, axs = plt.subplots(1, 2, figsize=(7, 4), constrained_layout=True) +for n, interp in enumerate(['hanning', 'lanczos']): + im = axs[n].imshow(a, interpolation=interp, cmap='gray') + axs[n].set_title(interp) +plt.show() + + +############################################################################# +# +# ------------ +# +# References +# """""""""" +# +# The use of the following functions and methods is shown +# in this example: + +import matplotlib +matplotlib.axes.Axes.imshow diff --git a/examples/images_contours_and_fields/interpolation_methods.py b/examples/images_contours_and_fields/interpolation_methods.py index a6fd065137a1..a63777e1d632 100644 --- a/examples/images_contours_and_fields/interpolation_methods.py +++ b/examples/images_contours_and_fields/interpolation_methods.py @@ -9,11 +9,14 @@ If `interpolation` is None, it defaults to the :rc:`image.interpolation` (default: ``'nearest'``). If the interpolation is ``'none'``, then no interpolation is performed for the Agg, ps and pdf backends. Other backends -will default to ``'nearest'``. +will default to ``'antialiased'``. For the Agg, ps and pdf backends, ``interpolation = 'none'`` works well when a big image is scaled down, while ``interpolation = 'nearest'`` works well when a small image is scaled up. + +See :doc:`/gallery/images_contours_and_fields/image_antialiasing` for a +discussion on the default `interpolation="antialiased"` option. """ import matplotlib.pyplot as plt diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index d5cd9e8644a3..da78d698753c 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -5488,10 +5488,10 @@ def imshow(self, X, cmap=None, norm=None, aspect=None, The interpolation method used. If *None* :rc:`image.interpolation` is used, which defaults to 'nearest'. - Supported values are 'none', 'nearest', 'bilinear', 'bicubic', - 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', - 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', - 'lanczos'. + Supported values are 'none', 'antialiased', 'nearest', 'bilinear', + 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', + 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', + 'sinc', 'lanczos'. If *interpolation* is 'none', then no interpolation is performed on the Agg, ps, pdf and svg backends. Other backends will fall back @@ -5499,9 +5499,19 @@ def imshow(self, X, cmap=None, norm=None, aspect=None, rendering and that the default interpolation method they implement may differ. + If *interpolation* is the default 'antialiased', then 'nearest' + interpolation is used if the image is upsampled by more than a + factor of three (i.e. the number of display pixels is at least + three times the size of the data array). If the upsampling rate is + smaller than 3, or the image is downsampled, then 'hanning' + interpolation is used to act as an anti-aliasing filter, unless the + image happens to be upsampled by exactly a factor of two or one. + See :doc:`/gallery/images_contours_and_fields/interpolation_methods` - for an overview of the supported interpolation methods. + for an overview of the supported interpolation methods, and + :doc:`/gallery/images_contours_and_fields/image_antialiasing` for + a discussion of image antialiasing. Some interpolation methods require an additional radius parameter, which can be set by *filterrad*. Additionally, the antigrain image diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py index 94119898b1a2..cbc8f7b68f3b 100644 --- a/lib/matplotlib/image.py +++ b/lib/matplotlib/image.py @@ -33,6 +33,7 @@ # map interpolation strings to module constants _interpd_ = { + 'antialiased': _image.NEAREST, # this will use nearest or Hanning... 'none': _image.NEAREST, # fall back to nearest when not supported 'nearest': _image.NEAREST, 'bilinear': _image.BILINEAR, @@ -168,11 +169,34 @@ def _resample( allocating the output array and fetching the relevant properties from the Image object *image_obj*. """ + + # decide if we need to apply anti-aliasing if the data is upsampled: + # compare the number of displayed pixels to the number of + # the data pixels. + interpolation = image_obj.get_interpolation() + if interpolation == 'antialiased': + # don't antialias if upsampling by an integer number or + # if zooming in more than a factor of 3 + shape = list(data.shape) + if image_obj.origin == 'upper': + shape[0] = 0 + dispx, dispy = transform.transform([shape[1], shape[0]]) + + if ((dispx > 3 * data.shape[1] or + dispx == data.shape[1] or + dispx == 2 * data.shape[1]) and + (dispy > 3 * data.shape[0] or + dispy == data.shape[0] or + dispy == 2 * data.shape[0])): + interpolation = 'nearest' + else: + interpolation = 'hanning' + out = np.zeros(out_shape + data.shape[2:], data.dtype) # 2D->2D, 3D->3D. if resample is None: resample = image_obj.get_resample() _image.resample(data, out, transform, - _interpd_[image_obj.get_interpolation()], + _interpd_[interpolation], resample, alpha, image_obj.get_filternorm(), @@ -432,7 +456,6 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, A_scaled += 0.1 # resample the input data to the correct resolution and shape A_resampled = _resample(self, A_scaled, out_shape, t) - # done with A_scaled now, remove from namespace to be sure! del A_scaled # un-scale the resampled data to approximately the @@ -690,9 +713,10 @@ def get_interpolation(self): """ Return the interpolation method the image uses when resizing. - One of 'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', - 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', - 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', or 'none'. + One of 'antialiased', 'nearest', 'bilinear', 'bicubic', 'spline16', + 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', + 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', + or 'none'. """ return self._interpolation @@ -708,9 +732,9 @@ def set_interpolation(self, s): Parameters ---------- - s : {'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', \ -'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian', \ -'bessel', 'mitchell', 'sinc', 'lanczos', 'none'} + s : {'antialiased', 'nearest', 'bilinear', 'bicubic', 'spline16', +'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', \ +'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', 'none'} """ if s is None: diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 7efb61a1657c..f5ffc1e5c9b5 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -1100,7 +1100,7 @@ def _validate_linestyle(ls): 'mathtext.fallback_to_cm': [True, validate_bool], 'image.aspect': ['equal', validate_aspect], # equal, auto, a number - 'image.interpolation': ['nearest', validate_string], + 'image.interpolation': ['antialiased', validate_string], 'image.cmap': ['viridis', validate_string], # gray, jet, etc. 'image.lut': [256, validate_int], # lookup table 'image.origin': ['upper', diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 2a88d258befa..f7036342d720 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -915,6 +915,8 @@ def test_nonfinite_limits(): @image_comparison(['imshow', 'imshow'], remove_text=True, style='mpl20') def test_imshow(): + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' # Create a NxN image N = 100 (x, y) = np.indices((N, N)) @@ -936,6 +938,8 @@ def test_imshow(): @image_comparison(['imshow_clip'], style='mpl20') def test_imshow_clip(): # As originally reported by Gellule Xg + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' # Create a NxN image N = 100 @@ -3732,6 +3736,10 @@ def test_subplot_key_hash(): remove_text=True, tol=0.07, style='default') def test_specgram_freqs(): '''test axes.specgram in default (psd) mode with sinusoidal stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + n = 1000 Fs = 10. @@ -3784,6 +3792,10 @@ def test_specgram_freqs(): remove_text=True, tol=0.01, style='default') def test_specgram_noise(): '''test axes.specgram in default (psd) mode with noise stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + np.random.seed(0) n = 1000 @@ -3831,6 +3843,10 @@ def test_specgram_noise(): remove_text=True, tol=0.07, style='default') def test_specgram_magnitude_freqs(): '''test axes.specgram in magnitude mode with sinusoidal stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + n = 1000 Fs = 10. @@ -3886,6 +3902,10 @@ def test_specgram_magnitude_freqs(): remove_text=True, style='default') def test_specgram_magnitude_noise(): '''test axes.specgram in magnitude mode with noise stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + np.random.seed(0) n = 1000 @@ -3932,6 +3952,10 @@ def test_specgram_magnitude_noise(): remove_text=True, tol=0.007, style='default') def test_specgram_angle_freqs(): '''test axes.specgram in angle mode with sinusoidal stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + n = 1000 Fs = 10. @@ -3986,6 +4010,10 @@ def test_specgram_angle_freqs(): remove_text=True, style='default') def test_specgram_noise_angle(): '''test axes.specgram in angle mode with noise stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' + np.random.seed(0) n = 1000 @@ -4032,6 +4060,9 @@ def test_specgram_noise_angle(): remove_text=True, style='default') def test_specgram_freqs_phase(): '''test axes.specgram in phase mode with sinusoidal stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' n = 1000 Fs = 10. @@ -4086,6 +4117,9 @@ def test_specgram_freqs_phase(): remove_text=True, style='default') def test_specgram_noise_phase(): '''test axes.specgram in phase mode with noise stimuli''' + + # use former defaults to match existing baseline image + matplotlib.rcParams['image.interpolation'] = 'nearest' np.random.seed(0) n = 1000 diff --git a/lib/matplotlib/tests/test_image.py b/lib/matplotlib/tests/test_image.py index 18d513b2c962..58fb8b610118 100644 --- a/lib/matplotlib/tests/test_image.py +++ b/lib/matplotlib/tests/test_image.py @@ -115,6 +115,88 @@ def test_image_python_io(): plt.imread(buffer) +@check_figures_equal(extensions=['png']) +def test_imshow_subsample(fig_test, fig_ref): + # data is bigger than figure, so subsampling with hanning + np.random.seed(19680801) + dpi = 100 + A = np.random.rand(int(dpi * 5), int(dpi * 5)) + for fig in [fig_test, fig_ref]: + fig.set_size_inches(2, 2) + + axs = fig_test.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='antialiased') + axs = fig_ref.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='hanning') + + +@check_figures_equal(extensions=['png']) +def test_imshow_samesample(fig_test, fig_ref): + # exact resample, so should be same as nearest.... + np.random.seed(19680801) + dpi = 100 + A = np.random.rand(int(dpi * 5), int(dpi * 5)) + for fig in [fig_test, fig_ref]: + fig.set_size_inches(5, 5) + axs = fig_test.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='antialiased') + axs = fig_ref.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='nearest') + + +@check_figures_equal(extensions=['png']) +def test_imshow_doublesample(fig_test, fig_ref): + # should be exactly a double sample, so should use nearest neighbour + # which is the same as "none" + np.random.seed(19680801) + dpi = 100 + A = np.random.rand(int(dpi * 5), int(dpi * 5)) + for fig in [fig_test, fig_ref]: + fig.set_size_inches(10, 10) + axs = fig_test.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='antialiased') + axs = fig_ref.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='nearest') + + +@check_figures_equal(extensions=['png']) +def test_imshow_upsample(fig_test, fig_ref): + # should be less than 3 upsample, so should be nearest... + np.random.seed(19680801) + dpi = 100 + A = np.random.rand(int(dpi * 3), int(dpi * 3)) + for fig in [fig_test, fig_ref]: + fig.set_size_inches(2.9, 2.9) + axs = fig_test.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='antialiased') + axs = fig_ref.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='hanning') + + +@check_figures_equal(extensions=['png']) +def test_imshow_upsample3(fig_test, fig_ref): + # should be greater than 3 upsample, so should be nearest... + np.random.seed(19680801) + dpi = 100 + A = np.random.rand(int(dpi * 3), int(dpi * 3)) + for fig in [fig_test, fig_ref]: + fig.set_size_inches(9.1, 9.1) + axs = fig_test.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='antialiased') + axs = fig_ref.subplots() + axs.set_position([0, 0, 1, 1]) + axs.imshow(A, interpolation='nearest') + + @check_figures_equal() def test_imshow_pil(fig_test, fig_ref): style.use("default") @@ -503,7 +585,8 @@ def test_bbox_image_inverted(): fig, ax = plt.subplots() bbox_im = BboxImage( - TransformedBbox(Bbox([[100, 100], [0, 0]]), ax.transData)) + TransformedBbox(Bbox([[100, 100], [0, 0]]), ax.transData), + interpolation='nearest') bbox_im.set_data(image) bbox_im.set_clip_on(False) ax.set_xlim(0, 100) @@ -513,7 +596,8 @@ def test_bbox_image_inverted(): image = np.identity(10) bbox_im = BboxImage(TransformedBbox(Bbox([[0.1, 0.2], [0.3, 0.25]]), - ax.figure.transFigure)) + ax.figure.transFigure), + interpolation='nearest') bbox_im.set_data(image) bbox_im.set_clip_on(False) ax.add_artist(bbox_im) @@ -854,8 +938,10 @@ def test_imshow_masked_interpolation(): data = np.ma.masked_array(data, mask) fig, ax_grid = plt.subplots(3, 6) + interps = sorted(mimage._interpd_) + interps.remove('antialiased') - for interp, ax in zip(sorted(mimage._interpd_), ax_grid.ravel()): + for interp, ax in zip(interps, ax_grid.ravel()): ax.set_title(interp) ax.imshow(data, norm=n, cmap=cm, interpolation=interp) ax.axis('off') @@ -892,12 +978,13 @@ def test_imshow_clips_rgb_to_valid_range(dtype): @image_comparison(['imshow_flatfield.png'], remove_text=True, style='mpl20') def test_imshow_flatfield(): fig, ax = plt.subplots() - im = ax.imshow(np.ones((5, 5))) + im = ax.imshow(np.ones((5, 5)), interpolation='nearest') im.set_clim(.5, 1.5) @image_comparison(['imshow_bignumbers.png'], remove_text=True, style='mpl20') def test_imshow_bignumbers(): + rcParams['image.interpolation'] = 'nearest' # putting a big number in an array of integers shouldn't # ruin the dynamic range of the resolved bits. fig, ax = plt.subplots() @@ -909,6 +996,7 @@ def test_imshow_bignumbers(): @image_comparison(['imshow_bignumbers_real.png'], remove_text=True, style='mpl20') def test_imshow_bignumbers_real(): + rcParams['image.interpolation'] = 'nearest' # putting a big number in an array of integers shouldn't # ruin the dynamic range of the resolved bits. fig, ax = plt.subplots() diff --git a/lib/matplotlib/tests/test_patheffects.py b/lib/matplotlib/tests/test_patheffects.py index e3b8acd3e461..f96f7dcee9e7 100644 --- a/lib/matplotlib/tests/test_patheffects.py +++ b/lib/matplotlib/tests/test_patheffects.py @@ -29,7 +29,7 @@ def test_patheffect2(): ax2 = plt.subplot(111) arr = np.arange(25).reshape((5, 5)) - ax2.imshow(arr) + ax2.imshow(arr, interpolation='nearest') cntr = ax2.contour(arr, colors="k") plt.setp(cntr.collections, diff --git a/lib/mpl_toolkits/tests/test_axes_grid.py b/lib/mpl_toolkits/tests/test_axes_grid.py index a6745bd05652..d3957cfb34c4 100644 --- a/lib/mpl_toolkits/tests/test_axes_grid.py +++ b/lib/mpl_toolkits/tests/test_axes_grid.py @@ -1,4 +1,5 @@ +import matplotlib from matplotlib.testing.decorators import image_comparison from mpl_toolkits.axes_grid1 import ImageGrid import numpy as np @@ -7,6 +8,8 @@ @image_comparison(['imagegrid_cbar_mode.png'], remove_text=True, style='mpl20') def test_imagegrid_cbar_mode_edge(): + matplotlib.rcParams['image.interpolation'] = 'nearest' + X, Y = np.meshgrid(np.linspace(0, 6, 30), np.linspace(0, 6, 30)) arr = np.sin(X) * np.cos(Y) + 1j*(np.sin(3*Y) * np.cos(Y/2.)) diff --git a/lib/mpl_toolkits/tests/test_axes_grid1.py b/lib/mpl_toolkits/tests/test_axes_grid1.py index fdcde420fb8a..f44fdc85c17c 100644 --- a/lib/mpl_toolkits/tests/test_axes_grid1.py +++ b/lib/mpl_toolkits/tests/test_axes_grid1.py @@ -355,7 +355,7 @@ def test_zooming_with_inverted_axes(): tol={'aarch64': 0.02}.get(platform.machine(), 0.0)) def test_anchored_direction_arrows(): fig, ax = plt.subplots() - ax.imshow(np.zeros((10, 10))) + ax.imshow(np.zeros((10, 10)), interpolation='nearest') simple_arrow = AnchoredDirectionArrows(ax.transAxes, 'X', 'Y') ax.add_artist(simple_arrow) @@ -394,7 +394,7 @@ def test_image_grid(): grid = ImageGrid(fig, 111, nrows_ncols=(2, 2), axes_pad=0.1) for i in range(4): - grid[i].imshow(im) + grid[i].imshow(im, interpolation='nearest') grid[i].set_title('test {0}{0}'.format(i)) diff --git a/matplotlibrc.template b/matplotlibrc.template index 5f5af1cd6242..00dbda291420 100644 --- a/matplotlibrc.template +++ b/matplotlibrc.template @@ -559,7 +559,7 @@ ## * IMAGES * ## *************************************************************************** #image.aspect : equal ## {equal, auto} or a number -#image.interpolation : nearest ## see help(imshow) for options +#image.interpolation : antialiased ## see help(imshow) for options #image.cmap : viridis ## A colormap name, gray etc... #image.lut : 256 ## the size of the colormap lookup table #image.origin : upper ## {lower, upper}