Как применить унифицированный фильтр, используя SciPy Image, если данные за пределами границы не подсчитываются? - PullRequest
0 голосов
/ 17 декабря 2018

Я потратил много времени на это, и я знаю, как это сделать вручную, разрезая и индексируя граничные строки / столбцы, но с SciPy должен быть более простой способ.

Мне нужноустановите CVAL (значения для заполнения за края, когда mode=constant) равным NaN, однако это вернет NaN.

Я объясню это с помощью кода и цифр:

import numpy as np
from scipy import ndimage
m = np.reshape(np.arange(0,100),(10,10)).astype(np.float)

picture of the input array Используйте универсальный фильтр SciPy ndimage для вычисления среднего значения с использованием ядра 3x3:

filter = ndimage.uniform_filter(m, size=3, mode='constant')
print(filter[1][1]) # equal to 11
print(filter[9][9]) # I need 93.5, however it gets 41.55 due to zeros

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

Вот что мне нужно для достижения (слева) против mode=constant и CVAL=0 (по умолчанию 0)

scipy avg and what I need

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Один простой подход заключается в использовании Normalized Convolution :

import numpy as np
from scipy import ndimage
m = np.reshape(np.arange(0,100),(10,10)).astype(np.float)

filter = ndimage.uniform_filter(m, size=3, mode='constant')    # normal filter result

weights = ndimage.uniform_filter(np.ones(m.shape), size=3, mode='constant')
filter = filter / weights    # normalized convolution result

print(filter[1][1]) # equal to 11
print(filter[9][9]) # equal to 93.49999999999994 -- rounding error! :)

Мы вычислили результат фильтра, если бы все точки данных были 1 (weights).Это показывает, сколько элементов данных имеется в каждом окне фильтра, и возвращает значение 1 везде, кроме вблизи границы, где это значение уменьшается пропорционально.Разделив результат фильтрации с этими весами, мы корректируем усреднение, принимая во внимание нули, которые были вне области данных.

0 голосов
/ 18 декабря 2018

Это предложение далеко не идеально, потому что оно будет медленным по сравнению с uniform_filter, но оно будет делать то, что вы хотите.

Используя вашу идею использования nan для постоянного значения, вы можетеРеализуйте универсальный фильтр, используя ndimage.generic_filter вместо uniform_filter, с numpy.nanmean в качестве универсальной функции фильтра.

Например, вот ваш примерный массив m:

In [102]: import numpy as np

In [103]: m = np.reshape(np.arange(0,100),(10,10)).astype(np.float)

Применить generic_filter, с numpy.nanmean в качестве применяемой функции:

In [104]: from scipy.ndimage import generic_filter

In [105]: generic_filter(m, np.nanmean, mode='constant', cval=np.nan, size=3)
Out[105]: 
array([[ 5.5,  6. ,  7. ,  8. ,  9. , 10. , 11. , 12. , 13. , 13.5],
       [10.5, 11. , 12. , 13. , 14. , 15. , 16. , 17. , 18. , 18.5],
       [20.5, 21. , 22. , 23. , 24. , 25. , 26. , 27. , 28. , 28.5],
       [30.5, 31. , 32. , 33. , 34. , 35. , 36. , 37. , 38. , 38.5],
       [40.5, 41. , 42. , 43. , 44. , 45. , 46. , 47. , 48. , 48.5],
       [50.5, 51. , 52. , 53. , 54. , 55. , 56. , 57. , 58. , 58.5],
       [60.5, 61. , 62. , 63. , 64. , 65. , 66. , 67. , 68. , 68.5],
       [70.5, 71. , 72. , 73. , 74. , 75. , 76. , 77. , 78. , 78.5],
       [80.5, 81. , 82. , 83. , 84. , 85. , 86. , 87. , 88. , 88.5],
       [85.5, 86. , 87. , 88. , 89. , 90. , 91. , 92. , 93. , 93.5]])
...