图像抗锯齿#

图像由屏幕上或图像文件中的离散像素表示。当构成图像的数据具有与其在屏幕上的表示不同的分辨率时,我们将看到锯齿效果。它们的显着程度取决于在分辨率变化(如果有的话)中发生了多少下采样。

在对数据进行二次采样时,通过先平滑然后对平滑后的数据进行二次采样来减少混叠。在 Matplotlib 中,我们可以在将数据映射到颜色之前进行平滑处理,或者我们可以对最终图像中的 RGB(A) 数据进行平滑处理。它们之间的区别如下所示,并由 interpolation_stage关键字参数控制。

Matplotlib 中的默认图像插值是“抗锯齿”,它应用于数据。这在大多数情况下对用户提供的数据使用汉宁插值以减少混叠。仅当上采样系数为 1、2 或 >=3 时,才使用“最近”邻域插值。

Axes.imshow可以使用 插值关键字参数指定其他抗锯齿过滤器。

import numpy as np
import matplotlib.pyplot as plt

首先,我们生成具有不同频率内容的 450x450 像素图像:

N = 450
x = np.arange(N) / N - 0.5
y = np.arange(N) / N - 0.5
aa = np.ones((N, N))
aa[::2, :] = -1

X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
f0 = 5
k = 100
a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2))
# make the left hand side of this
a[:int(N / 2), :][R[:int(N / 2), :] < 0.4] = -1
a[:int(N / 2), :][R[:int(N / 2), :] < 0.3] = 1
aa[:, int(N / 3):] = a[:, int(N / 3):]
a = aa

以下图像从 450 个数据像素采样到 125 个像素或 250 个像素(取决于您的显示器)。“最近”插值中的莫尔条纹是由对高频数据进行二次采样引起的。图像中的“抗锯齿”仍然有一些摩尔纹图案,但它们大大减少了。

“数据”插值和“rgba”插值之间存在很大差异。图像左侧三分之一的红色和蓝色交替带被二次采样。通过在“数据”空间(默认值)中进行插值,抗锯齿过滤器使条纹接近白色,因为 -1 和 +1 的平均值为零,而在此颜色图中,零为白色。

反之,当“rgba”空间发生抗锯齿时,红色和蓝色在视觉上结合成紫色。这种行为更像是典型的图像处理包,但请注意紫色不在原始颜色图中,因此不再可能将单个像素反转回其数据值。

fig, axs = plt.subplots(2, 2, figsize=(5, 6), constrained_layout=True)
axs[0, 0].imshow(a, interpolation='nearest', cmap='RdBu_r')
axs[0, 0].set_xlim(100, 200)
axs[0, 0].set_ylim(275, 175)
axs[0, 0].set_title('Zoom')

for ax, interp, space in zip(axs.flat[1:],
                             ['nearest', 'antialiased', 'antialiased'],
                             ['data', 'data', 'rgba']):
    ax.imshow(a, interpolation=interp, interpolation_stage=space,
              cmap='RdBu_r')
    ax.set_title(f"interpolation='{interp}'\nspace='{space}'")
plt.show()
缩放,插值='最近' 空间='数据',插值='抗锯齿' 空间='数据',插值='抗锯齿' 空间='rgba'

当上采样因子不是整数时,即使使用“最近”插值对图像进行上采样也会导致莫尔图案。下图将 500 个数据像素上采样到 530 个渲染像素。您可能会注意到一个由 30 个线状伪影组成的网格,这些伪影源于必须弥补的 524 - 500 = 24 个额外像素。由于插值是“最近的”,它们与相邻的像素线相同,因此在局部拉伸图像,使其看起来失真。

fig, ax = plt.subplots(figsize=(6.8, 6.8))
ax.imshow(a, interpolation='nearest', cmap='gray')
ax.set_title("upsampled by factor a 1.048, interpolation='nearest'")
plt.show()
上采样因子 a 1.048,插值='最近的'

更好的抗锯齿算法可以减少这种影响:

fig, ax = plt.subplots(figsize=(6.8, 6.8))
ax.imshow(a, interpolation='antialiased', cmap='gray')
ax.set_title("upsampled by factor a 1.048, interpolation='antialiased'")
plt.show()
上采样因子 a 1.048,插值 ='antialiased'

除了默认的“汉宁”抗锯齿,imshow还支持许多不同的插值算法,这些算法可能会更好或更差,具体取决于模式。

fig, axs = plt.subplots(1, 2, figsize=(7, 4), constrained_layout=True)
for ax, interp in zip(axs, ['hanning', 'lanczos']):
    ax.imshow(a, interpolation=interp, cmap='gray')
    ax.set_title(f"interpolation='{interp}'")
plt.show()
插值='汉宁',插值='lanczos'

参考

此示例中显示了以下函数、方法、类和模块的使用:

脚本总运行时间:(0分3.316秒)

由 Sphinx-Gallery 生成的画廊