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

Skip to content

Commit 04fad9d

Browse files
committed
ENH: anti-alias down-sampled images
1 parent 9e7a235 commit 04fad9d

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5482,17 +5482,25 @@ def imshow(self, X, cmap=None, norm=None, aspect=None,
54825482
The interpolation method used. If *None*
54835483
:rc:`image.interpolation` is used, which defaults to 'nearest'.
54845484
5485-
Supported values are 'none', 'nearest', 'bilinear', 'bicubic',
5486-
'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser',
5487-
'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc',
5488-
'lanczos'.
5485+
Supported values are 'none', 'antialiased', 'nearest', 'bilinear',
5486+
'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite',
5487+
'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
5488+
'sinc', 'lanczos'.
54895489
54905490
If *interpolation* is 'none', then no interpolation is performed
54915491
on the Agg, ps, pdf and svg backends. Other backends will fall back
54925492
to 'nearest'. Note that most SVG renders perform interpolation at
54935493
rendering and that the default interpolation method they implement
54945494
may differ.
54955495
5496+
If *interpolation* is the default 'antialiased', then 'nearest'
5497+
interpolation is used if the image is upsampled by more than a
5498+
factor of three (i.e. the number of display pixels is at least three
5499+
times the size of the data array). If the upsampling rate is
5500+
smaller than 3, or the image is downsampled, then 'hanning'
5501+
interpolation is used to act as an anti-aliasing filter, unless the
5502+
image happens to be upsampled by exactly a factor of two or one.
5503+
54965504
See
54975505
:doc:`/gallery/images_contours_and_fields/interpolation_methods`
54985506
for an overview of the supported interpolation methods.

lib/matplotlib/image.py

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
# map interpolation strings to module constants
3535
_interpd_ = {
36+
'antialiased': None, # this will use nearest or Hanning if downsampled
3637
'none': _image.NEAREST, # fall back to nearest when not supported
3738
'nearest': _image.NEAREST,
3839
'bilinear': _image.BILINEAR,
@@ -168,11 +169,28 @@ def _resample(
168169
allocating the output array and fetching the relevant properties from the
169170
Image object *image_obj*.
170171
"""
172+
173+
# decide if we need to apply anti-aliasing if the data is upsampled:
174+
# compare the number of displayed pixels to the number of
175+
# the data pixels.
176+
interpolation = image_obj.get_interpolation()
177+
if interpolation == 'antialiased':
178+
# don't antialias if upsampling by an integer number or
179+
# if zooming in more than a factor of 3
180+
# do antialiasing....
181+
# compare the number of displayed pixels of the image to the number of
182+
# the data pixels.
183+
disppixels = int(transform.transform([data.shape[1], 0])[0])
184+
if (disppixels < 3 * data.shape[1] and disppixels != data.shape[1]):
185+
interpolation = 'hanning'
186+
else:
187+
interpolation = 'nearest'
188+
171189
out = np.zeros(out_shape + data.shape[2:], data.dtype) # 2D->2D, 3D->3D.
172190
if resample is None:
173191
resample = image_obj.get_resample()
174192
_image.resample(data, out, transform,
175-
_interpd_[image_obj.get_interpolation()],
193+
_interpd_[interpolation],
176194
resample,
177195
alpha,
178196
image_obj.get_filternorm(),
@@ -354,6 +372,20 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
354372
out_height = int(out_height_base)
355373
out_shape = (out_height, out_width)
356374

375+
# decide if we are going to do anti-aliasing or not on the image
376+
interpolation = self.get_interpolation()
377+
if interpolation == 'antialiased':
378+
# default
379+
interpolation = 'nearest'
380+
# do antialiasing....
381+
# compare the number of displayed pixels to the number of
382+
# the data pixels.
383+
samplerate = t.transform([A.shape[1], 0])[0] / A.shape[1]
384+
if (samplerate < 3 and
385+
np.abs(int(samplerate) - (samplerate)) > 0.0001):
386+
# do anti-aliasing
387+
interpolation = 'hanning'
388+
357389
if not unsampled:
358390
if not (A.ndim == 2 or A.ndim == 3 and A.shape[-1] in (3, 4)):
359391
raise ValueError(f"Invalid shape {A.shape} for image data")
@@ -432,7 +464,6 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
432464
A_scaled += 0.1
433465
# resample the input data to the correct resolution and shape
434466
A_resampled = _resample(self, A_scaled, out_shape, t)
435-
436467
# done with A_scaled now, remove from namespace to be sure!
437468
del A_scaled
438469
# un-scale the resampled data to approximately the
@@ -708,9 +739,9 @@ def set_interpolation(self, s):
708739
709740
Parameters
710741
----------
711-
s : {'nearest', 'bilinear', 'bicubic', 'spline16', 'spline36', \
712-
'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', 'gaussian', \
713-
'bessel', 'mitchell', 'sinc', 'lanczos', 'none'}
742+
s : {'antialiased', 'nearest', 'bilinear', 'bicubic', 'spline16',
743+
'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric', 'catrom', \
744+
'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos', 'none'}
714745
715746
"""
716747
if s is None:

lib/matplotlib/rcsetup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ def _validate_linestyle(ls):
11001100
'mathtext.fallback_to_cm': [True, validate_bool],
11011101

11021102
'image.aspect': ['equal', validate_aspect], # equal, auto, a number
1103-
'image.interpolation': ['nearest', validate_string],
1103+
'image.interpolation': ['antialiased', validate_string],
11041104
'image.cmap': ['viridis', validate_string], # gray, jet, etc.
11051105
'image.lut': [256, validate_int], # lookup table
11061106
'image.origin': ['upper',

matplotlibrc.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@
557557
## * IMAGES *
558558
## ***************************************************************************
559559
#image.aspect : equal ## {equal, auto} or a number
560-
#image.interpolation : nearest ## see help(imshow) for options
560+
#image.interpolation : antialiased ## see help(imshow) for options
561561
#image.cmap : viridis ## A colormap name, gray etc...
562562
#image.lut : 256 ## the size of the colormap lookup table
563563
#image.origin : upper ## {lower, upper}

0 commit comments

Comments
 (0)