Самый быстрый метод 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 с IronPython?
  • Сумма квадратных разностей (SSD) в numpy / scipy
  • Как установить точность на str (numpy.float64)?
  • SciPy lesssq соответствует синусоидальной волне
  • Является ли `scipy.misc.comb` быстрее, чем вычисление биномиального ad-hoc?
  • Pandas: используйте несколько столбцов фрейма данных как индекс другого
  • Эффективная нарезка матриц с использованием матричного умножения с помощью Python, NumPy, SciPy
  • Как получить основу сплайна, используемую scipy.interpolate.splev
  • Python - лучший язык программирования в мире.