Gaussiano filtrando una imagen con Nan en Python

A partir de una lista de coordenadas 2D y una tercera variable (velocidad), he creado una matriz numpy 2D que cubre todo el área muestreada. Mi intención es crear una imagen, en la que cada píxel contenga la velocidad media de los puntos que se encuentran dentro de él. Después de ese filtro esa imagen con un filtro gaussiano.

El problema es que el área no se muestrea de manera uniforme. Por lo tanto tengo varios píxeles sin información ( Nan ) en el centro de la imagen. Cuando trato de filtrar la matriz a través de un filtro gaussiano, la propagación de Nan arruina toda la imagen.

Necesito filtrar esta imagen, pero rechazando todos los píxeles sin información. En otras palabras, si un píxel no contiene información, entonces no debe tenerse en cuenta para el filtrado.

Aquí hay un ejemplo de mi código para promediar:

 Mean_V = np.zeros([len(x_bins), len(y_bins)]) for i, x_bin in enumerate(x_bins[:-1]): bin_x = (x > x_bins[i]) & (x  y_bins[j]) & (y[bin_x]  0 for x in bin_xy) > 0) : Mean_V[i,j]=np.mean(V[bin_x][bin_xy]) else: Mean_V[i,j]=np.nan 

EDITAR:

Navegando en la web, he terminado con esta pregunta que hice en 2013. La solución a este problema se puede encontrar en la biblioteca de astropy:

http://docs.astropy.org/en/stable/convolution/

La convolución de Astropy reemplaza los píxeles de NaN con una interpolación ponderada por el núcleo de sus vecinos.

¡¡Gracias amigos!!

en palabras:

Un filtro gaussiano que ignora los NaN en una matriz dada U puede obtenerse fácilmente aplicando un filtro gaussiano estándar a dos matrices auxiliares V y W y tomando la relación de las dos para obtener el resultado Z.

Aquí, V es una copia de la U original con NaN reemplazados por ceros y W es una matriz de unos con ceros que indican las posiciones de NaN en la U original.

La idea es que reemplazar los NaN por ceros introduce un error en la matriz filtrada que, sin embargo, se puede compensar aplicando el mismo filtro gaussiano a otra matriz auxiliar y combinando los dos.

en Python:

 import numpy as np import scipy as sp import scipy.ndimage U=sp.randn(10,10) # random array... U[U<2]=np.nan # ...with NaNs for testing V=U.copy() V[np.isnan(U)]=0 VV=sp.ndimage.gaussian_filter(V,sigma=2.0) W=0*U.copy()+1 W[np.isnan(U)]=0 WW=sp.ndimage.gaussian_filter(W,sigma=2.0) Z=VV/WW 

en números:

Aquí los coeficientes del filtro gaussiano se establecen en [0.25,0.50,0.25] para fines de demostración y sumn un 0.25 + 0.50 + 0.25 = 1, sin pérdida de generalidad.

Después de reemplazar los NaN por ceros y aplicar el filtro gaussiano (ver VV a continuación), está claro que los ceros introducen un error, es decir, debido a los datos "faltantes", los coeficientes 0.25 + 0.50 = 0.75 ya no sumn uno. y por lo tanto subestimar el valor "verdadero".

Sin embargo, esto puede compensarse utilizando la segunda matriz auxiliar (cf. WW a continuación) que, después de filtrar con el mismo gaussiano, solo contiene la sum de los coeficientes.

Por lo tanto, al dividir las dos matrices auxiliares filtradas, se escalan los coeficientes de manera que sumen uno, mientras que las posiciones de NaN se ignoran.

 array U 1 2 NaN 1 2 auxiliary V 1 2 0 1 2 auxiliary W 1 1 0 1 1 position abcde filtered VV_b = 0.25*V_a + 0.50*V_b + 0.25*V_c = 0.25*1 + 0.50*2 + 0 = 1.25 filtered WW_b = 0.25*W_a + 0.50*W_b + 0.25*W_c = 0.25*1 + 0.50*1 + 0 = 0.75 ratio Z = VV_b / WW_b = (0.25*1 + 0.50*2) / (0.25*1 + 0.50*1) = 0.333*1 + 0.666*2 = 1.666 

¿Qué hay de reemplazar Z = VV / WW con Z = VV / (WW + épsilon) con épsilon = 0.000001 para manejar automáticamente los casos sin observaciones en la propuesta anterior?

Lo más simple sería convertir nan s en ceros a través de nan_to_num . Si esto es significativo o no es una pregunta separada.