Antialiasing de imagem #

As imagens são representadas por pixels discretos, na tela ou em um arquivo de imagem. Quando os dados que compõem a imagem tiverem uma resolução diferente de sua representação na tela, veremos efeitos de aliasing. O quão perceptíveis eles são depende de quanto downsampling ocorre na mudança de resolução (se houver).

Ao subamostrar dados, o aliasing é reduzido suavizando primeiro e depois subamostrando os dados suavizados. No Matplotlib, podemos fazer essa suavização antes de mapear os dados para as cores, ou podemos fazer a suavização nos dados RGB(A) na imagem final. A diferença entre eles é mostrada abaixo e controlada com o argumento de palavra-chave interpolation_stage .

A interpolação de imagem padrão no Matplotlib é 'antialiased' e é aplicada aos dados. Isso usa uma interpolação hanning nos dados fornecidos pelo usuário para aliasing reduzido na maioria das situações. Somente quando há upsampling por um fator de 1, 2 ou >=3 é usada a interpolação do vizinho 'mais próximo'.

Outros filtros anti-aliasing podem ser especificados Axes.imshowusando o argumento de palavra-chave de interpolação .

import numpy as np
import matplotlib.pyplot as plt

Primeiro, geramos uma imagem de 450x450 pixels com conteúdo de frequência variável:

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

As seguintes imagens são subamostradas de 450 pixels de dados para 125 pixels ou 250 pixels (dependendo do seu monitor). Os padrões Moire na interpolação 'mais próxima' são causados ​​pelos dados de alta frequência sendo subamostrados. A imagem 'antialiased' ainda tem alguns padrões Moire também, mas eles são bastante reduzidos.

Existem diferenças substanciais entre a interpolação 'dados' e a interpolação 'rgba'. As bandas alternadas de vermelho e azul no terço esquerdo da imagem são subamostradas. Ao interpolar no espaço de 'dados' (o padrão) o filtro antialiasing torna as listras próximas do branco, porque a média de -1 e +1 é zero, e zero é branco neste mapa de cores.

Por outro lado, quando o anti-aliasing ocorre no espaço 'rgba', o vermelho e o azul são combinados visualmente para formar o roxo. Esse comportamento é mais parecido com um pacote de processamento de imagem típico, mas observe que o roxo não está no mapa de cores original, portanto, não é mais possível inverter pixels individuais de volta ao seu valor de dados.

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, interpolação='mais próximo' espaço='dados', interpolação='antialiased' space='dados', interpolação='antialiased' space='rgba'

Mesmo o upsampling de uma imagem com a interpolação 'mais próxima' levará a padrões Moire quando o fator de upsampling não for inteiro. A imagem a seguir aumenta a resolução de 500 pixels de dados para 530 pixels renderizados. Você pode observar uma grade de 30 artefatos semelhantes a linhas que se originam dos 524 - 500 = 24 pixels extras que tiveram que ser compostos. Como a interpolação é 'mais próxima', eles são iguais a uma linha vizinha de pixels e, portanto, estica a imagem localmente para que pareça distorcida.

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()
upsampled pelo fator a 1,048, interpolação = 'mais próximo'

Melhores algoritmos de suavização podem reduzir esse efeito:

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()
upsampled pelo fator a 1.048, interpolação='antialiased'

Além do antialiasing 'hanning' padrão, imshowsuporta vários algoritmos de interpolação diferentes, que podem funcionar melhor ou pior, dependendo do padrão.

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()
interpolação='hanning', interpolação='lanczos'

Referências

O uso das seguintes funções, métodos, classes e módulos é mostrado neste exemplo:

Tempo total de execução do script: (0 minutos 3,316 segundos)

Galeria gerada por Sphinx-Gallery