|
5 | 5 |
|
6 | 6 | Images are represented by discrete pixels, either on the screen or in an
|
7 | 7 | image file. When data that makes up the image has a different resolution
|
8 |
| -than its representation on the screen we will see aliasing effects. |
| 8 | +than its representation on the screen we will see aliasing effects. How |
| 9 | +noticeable these are depends on how much down-sampling takes place in |
| 10 | +the change of resolution (if any) |
9 | 11 |
|
10 |
| -The default image interpolation in Matplotlib is 'antialiased'. This uses a |
11 |
| -hanning interpolation for reduced aliasing in most situations. Only when there |
12 |
| -is upsampling by a factor of 1, 2 or >=3 is 'nearest' neighbor interpolation |
13 |
| -used. |
| 12 | +When subsampling data, aliasing is reduced by smoothing first and then |
| 13 | +subsampling the smoothed data. In Matplotlib, we can do that |
| 14 | +smoothing before mapping the data to colors, or we can do the smoothing |
| 15 | +on the RGB(A) data in the final image. The difference between these is |
| 16 | +shown below, and controlled with the *interp_space* keyword argument. |
| 17 | +
|
| 18 | +The default image interpolation in Matplotlib is 'antialiased', and |
| 19 | +it is applied to the data. This uses a |
| 20 | +hanning interpolation on the data provided by the user for reduced aliasing |
| 21 | +in most situations. Only when there is upsampling by a factor of 1, 2 or |
| 22 | +>=3 is 'nearest' neighbor interpolation used. |
14 | 23 |
|
15 | 24 | Other anti-aliasing filters can be specified in `.Axes.imshow` using the
|
16 | 25 | *interpolation* keyword argument.
|
|
21 | 30 |
|
22 | 31 | ###############################################################################
|
23 | 32 | # First we generate a 500x500 px image with varying frequency content:
|
24 |
| -x=np.arange(500)/500-0.5 |
25 |
| -y=np.arange(500)/500-0.5 |
| 33 | +N=450 |
| 34 | +x=np.arange(N)/N-0.5 |
| 35 | +y=np.arange(N)/N-0.5 |
| 36 | +aa=np.ones((N,N)) |
| 37 | +aa[::2, :]=-1 |
26 | 38 |
|
27 | 39 | X,Y=np.meshgrid(x,y)
|
28 | 40 | R=np.sqrt(X**2+Y**2)
|
29 |
| -f0=10 |
30 |
| -k=250 |
| 41 | +f0=5 |
| 42 | +k=100 |
31 | 43 | a=np.sin(np.pi*2* (f0*R+k*R**2/2))
|
32 |
| - |
33 |
| - |
| 44 | +# make the left hand side of this |
| 45 | +a[:int(N/2), :][R[:int(N/2), :]<0.4]=-1 |
| 46 | +a[:int(N/2), :][R[:int(N/2), :]<0.3]=1 |
| 47 | +aa[:,int(N/3):]=a[:,int(N/3):] |
| 48 | +a=aa |
34 | 49 | ###############################################################################
|
35 |
| -# The following images are subsampled from 500 data pixels to 303 rendered |
36 |
| -# pixels. The Moire patterns in the 'nearest' interpolation are caused by the |
37 |
| -# high-frequency data being subsampled. The 'antialiased' image |
| 50 | +# The following images are subsampled from 450 data pixels to either |
| 51 | +# 125 pixels or 250 pixels (depending on your display). |
| 52 | +# The Moire patterns in the 'nearest' interpolation are caused by the |
| 53 | +# high-frequency data being subsampled. The 'antialiased' imaged |
38 | 54 | # still has some Moire patterns as well, but they are greatly reduced.
|
39 |
| -fig,axs=plt.subplots(1,2,figsize=(7,4),constrained_layout=True) |
40 |
| -forax,interpinzip(axs, ['nearest','antialiased']): |
41 |
| -ax.imshow(a,interpolation=interp,cmap='gray') |
42 |
| -ax.set_title(f"interpolation='{interp}'") |
| 55 | +# |
| 56 | +# There are substantial differences between the 'data' interpolation and |
| 57 | +# the 'rgba' interpolation. The alternating bands of red and blue on the |
| 58 | +# left third of the image are subsampled. By interpolating in 'data' space |
| 59 | +# (the default) he antialiasing filter makes the stripes close to white, |
| 60 | +# because the average of -1 and +1 is zero, and zero is white in this |
| 61 | +# colormap. |
| 62 | +# |
| 63 | +# Conversely, when the anti-aliasing occurs in 'rgba' space, the red and |
| 64 | +# blue are combined visually to make purple. This behaviour is more like a |
| 65 | +# typical image processing package. |
| 66 | + |
| 67 | +fig,axs=plt.subplots(2,2,figsize=(5,6),constrained_layout=True) |
| 68 | +axs[0,0].imshow(a,interpolation='nearest',cmap='RdBu_r') |
| 69 | +axs[0,0].set_xlim(100,200) |
| 70 | +axs[0,0].set_ylim(275,175) |
| 71 | +axs[0,0].set_title('Zoom') |
| 72 | + |
| 73 | +forax,interp,spaceinzip(axs.flat[1:], |
| 74 | + ['nearest','antialiased','antialiased'], |
| 75 | + ['data','data','rgba']): |
| 76 | +ax.imshow(a,interpolation=interp,interp_space=space,cmap='RdBu_r') |
| 77 | +ax.set_title(f"interpolation='{interp}'\nspace='{space}'") |
43 | 78 | plt.show()
|
44 | 79 |
|
45 | 80 | ###############################################################################
|
|
63 | 98 | plt.show()
|
64 | 99 |
|
65 | 100 | ###############################################################################
|
66 |
| -# Apart from the default 'hanning' antialiasing `~.Axes.imshow` supports a |
| 101 | +# Apart from the default 'hanning' antialiasing, `~.Axes.imshow` supports a |
67 | 102 | # number of different interpolation algorithms, which may work better or
|
68 | 103 | # worse depending on the pattern.
|
69 | 104 | fig,axs=plt.subplots(1,2,figsize=(7,4),constrained_layout=True)
|
|