Гауссовская фильтрация изображения с помощью Nan в Python

Из списка 2D-координат и третьей переменной (скорости) я создал 2D-массив numpy, охватывающий всю область выборки. Я намерен создать изображение, в котором каждый пиксель содержит среднюю скорость лежащих в нем точек. После этого фильтруйте это изображение с помощью гауссовского фильтра.

Проблема в том, что область неравномерно отбирается. Поэтому у меня есть несколько пикселей без информации ( Nan ) в середине изображения. Когда я пытаюсь фильтровать массив через гауссовский фильтр, распространение Nan разрушает весь образ.

Мне нужно отфильтровать это изображение, но отклонить все пиксели без информации. Другими словами, если пиксель не содержит информации, он не должен учитываться для фильтрации.

Вот пример моего кода для усреднения:

 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 <= x_bins[i+1]) for j, y_bin in enumerate(y_bins[:-1]): bin_xy = (y[bin_x] > y_bins[j]) & (y[bin_x] <= y_bins[j+1]) if (sum(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 

в словах:

Гауссовский фильтр, который игнорирует NaN в заданном массиве U, можно легко получить, применив стандартный гауссовский фильтр к двум вспомогательным массивам V и W и взяв соотношение двух, чтобы получить результат Z.

Здесь V – копия исходного U с заменой NaN на нули, а W – массив единиц с нулями, указывающий положение NaNs в исходном U.

Идея состоит в том, что замена NaN на нули вводит ошибку в отфильтрованном массиве, который, однако, может быть скомпенсирован путем применения того же гауссовского фильтра к другому вспомогательному массиву и объединения двух.

в Python:

 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[U!=U]=0 VV=sp.ndimage.gaussian_filter(V,sigma=2.0) W=0*U.copy()+1 W[U!=U]=0 WW=sp.ndimage.gaussian_filter(W,sigma=2.0) Z=VV/WW , 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[U!=U]=0 VV=sp.ndimage.gaussian_filter(V,sigma=2.0) W=0*U.copy()+1 W[U!=U]=0 WW=sp.ndimage.gaussian_filter(W,sigma=2.0) Z=VV/WW 

в цифрах:

Здесь коэффициенты гауссовского фильтра устанавливаются на [0.25,0.50,0.25] для демонстрационных целей и суммируются до одного 0,25 + 0,50 + 0,25 = 1 без потери общности.

После замены NaN на нули и применения гауссова фильтра (см. Ниже VV) ясно, что нули вводят ошибку, т. Е. Из-за «отсутствующих» данных коэффициенты 0,25 + 0,50 = 0,75 не суммируют до одного больше и поэтому недооценивают «истинную» ценность.

Однако это можно скомпенсировать, используя второй вспомогательный массив (см. WW ниже), который после фильтрации с тем же гауссовским просто содержит сумму коэффициентов.

Таким образом, разделение двух фильтрованных вспомогательных массивов масштабирует коэффициенты таким образом, что они суммируются до единицы, в то время как позиции NaN игнорируются.

 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 

Самое простое – превратить nan s в нули через nan_to_num . Является ли это значимым или нет, это отдельный вопрос.