Suavizado de imágenes #

Las imágenes se representan mediante píxeles discretos, ya sea en la pantalla o en un archivo de imagen. Cuando los datos que componen la imagen tienen una resolución diferente a su representación en pantalla veremos efectos de aliasing. Lo notables que sean depende de la cantidad de reducción de muestreo que se produzca en el cambio de resolución (si lo hay).

Cuando se realizan submuestreos de datos, el alias se reduce suavizando primero y luego submuestreando los datos suavizados. En Matplotlib, podemos suavizar antes de asignar los datos a colores, o podemos suavizar los datos RGB(A) en la imagen final. La diferencia entre estos se muestra a continuación y se controla con el argumento de palabra clave interpolation_stage .

La interpolación de imagen predeterminada en Matplotlib es 'antialiasing' y se aplica a los datos. Esto utiliza una interpolación de hanning en los datos proporcionados por el usuario para reducir el aliasing en la mayoría de las situaciones. Solo cuando hay un muestreo superior por un factor de 1, 2 o >=3 se utiliza la interpolación del vecino "más cercano".

Se pueden especificar otros filtros de suavizado Axes.imshowutilizando el argumento de palabra clave de interpolación .

import numpy as np
import matplotlib.pyplot as plt

Primero generamos una imagen de 450x450 píxeles con contenido de frecuencia variable:

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

Las siguientes imágenes se submuestrean desde 450 píxeles de datos hasta 125 o 250 píxeles (dependiendo de su pantalla). Los patrones de Moire en la interpolación 'más cercana' son causados ​​por los datos de alta frecuencia que se submuestrean. La imagen 'antialiased' también tiene algunos patrones Moire, pero se han reducido considerablemente.

Existen diferencias sustanciales entre la interpolación de 'datos' y la interpolación de 'rgba'. Las bandas alternas de rojo y azul en el tercio izquierdo de la imagen son submuestreadas. Al interpolar en el espacio de 'datos' (el valor predeterminado), el filtro antialiasing hace que las rayas se acerquen al blanco, porque el promedio de -1 y +1 es cero, y cero es blanco en este mapa de colores.

Por el contrario, cuando el suavizado se produce en el espacio 'rgba', el rojo y el azul se combinan visualmente para formar un violeta. Este comportamiento se parece más a un paquete de procesamiento de imágenes típico, pero tenga en cuenta que el color púrpura no está en el mapa de colores original, por lo que ya no es posible invertir píxeles individuales de nuevo a su valor de datos.

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()
Zoom, interpolación='más cercano' espacio='datos', interpolación='antialiased' space='data', interpolación='antialiased' space='rgba'

Incluso el muestreo ascendente de una imagen con la interpolación 'más cercana' dará lugar a patrones Moire cuando el factor de muestreo ascendente no es un número entero. La siguiente imagen aumenta la muestra de 500 píxeles de datos a 530 píxeles renderizados. Puede notar una cuadrícula de 30 artefactos similares a líneas que se derivan de los 524 - 500 = 24 píxeles adicionales que se tuvieron que crear. Dado que la interpolación es 'más cercana', son lo mismo que una línea vecina de píxeles y, por lo tanto, estiran la imagen localmente para que parezca distorsionada.

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()
sobremuestreado por el factor a 1.048, interpolación = 'más cercano'

Mejores algoritmos de antialiasing pueden reducir este efecto:

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()
sobremuestreado por el factor a 1.048, interpolación = 'antialiased'

Además del antialiasing 'hanning' predeterminado, imshowadmite varios algoritmos de interpolación diferentes, que pueden funcionar mejor o peor según el patrón.

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()
interpolación='hanning', interpolación='lanczos'

Referencias

En este ejemplo se muestra el uso de las siguientes funciones, métodos, clases y módulos:

Tiempo total de ejecución del script: (0 minutos 3.316 segundos)

Galería generada por Sphinx-Gallery