SciPy medfilt错误的结果

im_*_*ous 7 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))
Run Code Online (Sandbox Code Playgroud)

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

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.]
Run Code Online (Sandbox Code Playgroud)

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

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

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

tbe*_*lay 16

我相信你和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
Run Code Online (Sandbox Code Playgroud)

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

如果您看到维基百科对中值滤波器的描述,它们会通过用边缘值填充它来扩展任一边缘的信号,这似乎也是合理的.他们还注意到处理边界问题的其他三种方式:

  • 避免处理边界,之后有或没有裁剪信号边界.
  • 从信号中的其他位置获取条目.例如,对于图像,可以选择来自远水平或垂直边界的条目.
  • 缩小边界附近的窗口,使每个窗口都满了(就像你已经完成的那样.)

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