Самый быстрый метод python / numpy для фильтрации ранга ядра 2d на масках массивов (и / или выборочный рейтинг)

Учитывая массив двумерных чисел

MyArray = np.array([[ 8.02, 9.54, 0.82, 7.56, 2.26, 9.47], [ 2.68, 7.3 , 2.74, 3.03, 2.25, 8.84], [ 2.21, 3.62, 0.55, 2.94, 5.77, 0.21], [ 5.78, 5.72, 8.85, 0.24, 5.37, 9.9 ], [ 9.1 , 7.21, 4.14, 9.95, 6.73, 6.08], [ 1.8 , 5.14, 5.02, 6.52, 0.3 , 6.11]]) 

и массив маски

 MyMask = np.array([[ 0., 0., 1., 1., 0., 1.], [ 1., 0., 0., 0., 0., 1.], [ 0., 0., 0., 1., 0., 0.], [ 0., 1., 1., 1., 1., 0.], [ 0., 1., 0., 1., 0., 0.], [ 0., 1., 0., 0., 1., 1.]]) 

Я хочу запустить «дырявый» медианный фильтр, который игнорирует маскированные элементы.

Например, фильтр рангов с ядром

 k = np.array([[ 1, 1, 1], [ 1, 0, 1], [ 1, 1, 1]]); 

будет работать на MyArray : сортировка окрестности, определяемой ядром для каждого элемента MyArray и возврат медианы только не замаскированных элементов (усреднение, если массив является четным числом).

Теперь, в настоящее время я делаю это в непитонных циклах, используя узкое место.nanmedian, сопоставляя маску с NaN. Это дает мне именно то, что мне нужно, но я надеялся полагаться на 2D-манипуляции с массивами.

scipy.signal.order_filter и scipy.ndimage.filters.rank_filter доступны (rank_filter выглядит намного быстрее), но кажется, что они сортируют NaN и Inf в верхней части массива, прежде чем возвращать ранг и смещать результат. Кажется, ни один из этих методов не поддерживает массивы numpy.ma (маскирование) и не принимает массив выборочных рангов (тогда я мог бы заполнить все маски с помощью 0 и смещать мой ранг), и нет очевидного способа изменить ядро ​​для каждое место.

Мне интересно, не пропустил ли я комбинацию и / или функцию python, или я должен искать реализацию новой процедуры в Cython.

Игнорируя обработку границ, внутренние точки указанной проблемы будут

 [[ 0. 0. 0. 0. 0. 0. ] [ 0. 3.18 3.62 2.26 2.645 0. ] [ 0. 2.74 3.325 2.74 2.64 0. ] [ 0. 3.88 3.62 4.955 6.08 0. ] [ 0. 5.02 5.77 5.77 6.52 0. ] [ 0. 0. 0. 0. 0. 0. ]] 

One Solution collect form web for “Самый быстрый метод python / numpy для фильтрации ранга ядра 2d на масках массивов (и / или выборочный рейтинг)”

Один из способов – пожертвовать использованием ОЗУ, чтобы отказаться от петель Python. Т.е. мы взорвали исходный массив, чтобы мы могли сразу применить фильтр на всех подмассивах. Это похоже на широковещательную передачу Numpy.

Для массива 1000×1000 векторизованная функция выполняется примерно в 100 раз быстрее, в моем тестировании.

В моем коде я использовал NaN для маскировки, но с некоторыми дополнительными строками кода вы также могли использовать массивы numpy.ma . И у меня не было nanmedian функции, поэтому я использовал nanmean , производительность должна быть сопоставимой.

 import numpy as np from numpy.lib.stride_tricks import as_strided # test data N = 1000 A = np.random.rand(N, N)*10 mask = np.random.choice([True, False], size=(N, N)) def filter_loop(A, mask): kernel = np.array([[1,1,1],[1,0,1],[1,1,1]], bool) A = A.copy() A[mask] = np.nan N = A.shape[0] - 2 # assuming square matrix out = np.empty((N, N)) for i in xrange(N): for j in xrange(N): out[i,j] = np.nanmean(A[i:i+3, j:j+3][kernel]) return out def filter_broadcast(A, mask): A = A.copy() A[mask] = np.nan N = A.shape[0] - 2 B = as_strided(A, (N, N, 3, 3), A.strides+A.strides) B = B.copy().reshape((N, N, 3*3)) B[:,:,4] = np.nan return np.nanmean(B, axis=2) 
  • Как получить центроиды из иерархической агломерационной кластеризации SciPy?
  • Не удается установить scipy
  • Python curve_fit с несколькими независимыми переменными
  • изменить настройки оси matplotlib
  • Итерация через вектор scipy.sparse (или матрицу)
  • Значение доступа, индекс столбца и данные row_ptr из scipy CSR разреженной матрицы
  • Использование scipy.spatial.Delaunay вместо встроенной версии matplotlib.tri.Triangulation
  • Почему SciPy действует по-разному в IPython и Python?
  • Python - лучший язык программирования в мире.