有人发现/理解了scipy.ndimage.median_filter
对于偶数大小是如何工作的吗?因为我测试了很多理论,并试图阅读源代码,但我没有一个解释
(Of当然,最好使用奇数大小以避免移位,但有趣的是median_filter如何准确地计算偶数的大小...)
问题定义:
from scipy.ndimage import median_filter
import numpy as np
arr = np.array([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]])
print('Size 3:')
print(median_filter(arr, size=3, cval=0, mode='constant'))
print('Size 2:')
print(median_filter(arr, size=2, cval=0, mode='constant'))
# with cval=0, mode='constant' we set that input array is extended with zeros
# when window overlaps edges, just for visibility and ease of calculation
输出量
Size 3
[[0. 2. 0.]
[2. 5. 3.]
[0. 5. 0.]]
Size 2
[[0. 1. 2.]
[1. 4. 5.]
[4. 7. 8.]]
如我们所见,size 3
的所有值都与预期值相同,但size 2
的值并不明显。例如,假设窗口形状为(2,2),让我们定义并计算数组元素“9”的所有可能窗口和中值。我们可以用形状为(2,2)的窗口覆盖“9”(或数组中的任何其他值),具体有4种不同变体,如下所示:
相应的中值为:为红色矩形-3、黄色-7、绿色-0、蓝色-4......但输出值为8。即使设想在此之后对这些中值应用一些附加运算(平均值、中值等),这些运算也不明显。
有趣的事实#1
看起来,对于1d median_filter,仅取size-1
(因此,奇数)数。示例:
arr = np.array([1., 2., 3., 4., 5.])
print('1 - ', median_filter(arr, size=1, cval=0, mode='constant'))
print('2 - ', median_filter(arr, size=2, cval=0, mode='constant'))
print('3 - ', median_filter(arr, size=3, cval=0, mode='constant'))
print('4 - ', median_filter(arr, size=4, cval=0, mode='constant'))
print('5 - ', median_filter(arr, size=5, cval=0, mode='constant'))
print('6 - ', median_filter(arr, size=6, cval=0, mode='constant'))
输出量
有趣的事实#2
一般情况下,使用偶数的中值滤波器效果很好,但会使图像模糊,甚至很难确定一些差异或偏移
2条答案
按热度按时间iswrvxsc1#
在scipy.ndimage.median_filter中,当size = 2时会出现一种特殊情况。https://github.com/scipy/scipy/blob/v1.8.1/scipy/ndimage/_filters.py#L1351-L1396
中值滤波器调用函数
_rank_filter
,可在此处找到:https://github.com/scipy/scipy/blob/4cf21e753cf937d1c6c2d2a0e372fbc1dbbeea81/scipy/ndimage/_filters.py#L1244在函数中,您将找到代码:
此外,在前面的函数
rank=size//2
中。在这种情况下,程序执行的是最小值滤波器,而不是真正的中值滤波器(将涉及求平均值)。
条件
rank==0
和rank==size-1
都为真,但控制流优先考虑rank==0
,它对应于代码中的最小过滤器。大小〉=4可能会有不同的效果。
tf7tbtn22#
多亏了Michael Sohnen的回答,现在我明白了它是如何工作的!
我将在我的问题中针对
size=2
的“问题定义”中的示例逐步描述计算过程由于源代码https://github.com/scipy/scipy/blob/4cf21e753cf937d1c6c2d2a0e372fbc1dbbeea81/scipy/ndimage/_filters.py#L1244-L1307
1.首先,
footprint
由size
计算得出。在我们的例子size=2
中,footprint将是一个用True
填充的形状为(2,2)的数组(第1252-1258行)。1.然后,计算
filter_size
(第1267行)numpy.where(footprint, 1, 0)
在数组元素为True时返回1,在数组元素为False时返回0,所有占用空间元素均为True,这意味着filter_size等于41.计算
rank
(第1268-1279行)这意味着在我们的例子中秩等于2
1.找到适当的条件(第1280-1307行)
所以
rank_filter
将被应用到数组中。秩过滤器是如何工作的?它对给定窗口中的值进行排序,然后从排序后的数组中取一个索引为
rank
的元素。排序窗口为[1,2,3,4],第二个索引(* 从零开始 *)上的元素为3。
秩过滤器的特殊情况是最小过滤器(在这种情况下秩=0)、最大过滤器(秩=length_of_an_array)和中值过滤器
1.最后,将秩过滤器应用于原始数组
元素“1”的蓝色窗口,已排序[0 0 0 1],已排序数组的第二个元素- 0
元素“2”的红色窗口,已排序[0 0 1 2],已排序数组的第二个元素- 1
元素“3”的绿色窗口,已排序[0 0 2 3],已排序数组的第二个元素- 2
依此类推......所以,输出数组的第一个原始值[0,1,2]
现在答案与输出相符!