SciPy medfilt错误的结果

时间:2014-07-05 10:59:38

标签: python numpy scipy median

嗨蟒蛇爱好者!

我目前正在研究用于研究目的的信号过滤,并决定使用SciPy。没什么特别的,只是日常工作的自动化。

所以,这是代码

from scipy.signal import medfilt
print(medfilt([2,6,5,4,0,3,5,7,9,2,0,1], 5))

但问题是返回的序列计算错误

SciPy: [ 2. 4. 4. 4. 4. 4. 5. 5. 5. 2. 1. 0.]
Me   : [ 5. 4.5 4. 4. 4. 4. 5. 5. 5. 2. 1.5 1.]

似乎是,包的开发人员搞砸了一个细节。当光圈(SciPy中的内核)大于要分析的窗口时,还有另一种过滤规则。

例如,kernel=5过滤后的[2, 6, 5]子序列的中位数为5而不是2,因为SciPy计算的不是吗?同样,如果kernel=5对于子序列[2,6,5,4]中位数为5和4,我们需要在它们之间取平均值,因此,中位数为4.5。

有人可以解释一下我在这种情况下得到了正确的结果吗?

1 个答案:

答案 0 :(得分:13)

我相信你和SciPy都有正确的结果。区别在于边界发生的事情,但我相信你和SciPy都做出了有效的选择。

问题是当您的滑动窗口位于边缘时会发生什么,并且没有用于填充滑动窗口的有效数据

您选择取滑动窗口有效部分的中位数,这是有道理的,但可能会增加一些偏差,因为与其他所有点相比,您的边缘点过多。

SciPy选择通过填充零来扩展任一边缘的信号。因此,在边界上,SciPy实质上是在计算

>>> np.median([0, 0, 2, 6, 5])
2.0
>>> np.median([0, 2, 6, 5, 4])
4.0
>>> np.median([9, 2, 0, 1, 0])
1.0
>>> np.median([2, 0, 1, 0, 0])
0.0

SciPy之所以这样做几乎肯定与速度有关:它针对多次做同样的事情进行了优化,并且对于一大堆5元素阵列优化median要比它更容易是针对一大堆5元素阵列以及两个4元素阵列和两个3元素阵列进行优化。肯定有一个论点是它不应该用零填充,而是用边界值填充,但应该注意的是没有边界策略是完美的;处理边界问题的理想方法取决于你的特定信号。

如果你看到Wikipedia's description of median filters,它们会通过用边缘的值填充它来扩展任一边缘的信号,这似乎也是合理的。他们还注意到处理边界问题的其他三种方式:

  • 避免处理边界,无论是否有裁剪信号边界。
  • 从信号中的其他位置获取条目。例如,使用图像,可以选择远水平或垂直边界的条目。
  • 缩小边界附近的窗口,以便每个窗口都已满(正如您所做的那样。)

最后,您真的需要尝试不同的选项,看看什么最适合您的信号。这种滤波的核心假设是你的信号将非常大,并且边界问题永远不应该那么重要(因为边界上不存在大部分信号)。如果SciPy允许你选择它应该在边界做什么,那将是很好的!