2014-07-05 55 views
6

嗨python愛好者!SciPy medfilt錯誤結果

我目前正在研究信號過濾,並決定使用SciPy。沒什麼特別的,只是日常工作的自動化。

所以,這裏是代碼

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

但問題是,返回sequense計算錯誤

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計算的不是它嗎?同樣,如果的子序列[2,6,5,4]中位數是5和4,我們需要在它們之間取平均值,所以中位數是4.5。

有人能解釋我誰在這​​種情況下得到了正確的結果嗎?

回答

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的做到這一點幾乎是肯定的相關速度:它是一種通過多次做同一件事情優化,這是很容易優化median爲一大堆5元素數組,而不是優化它的一大堆5元素數組,以及兩個4元素數組和2個3元素數組。肯定有一個論點是不應該用零填充,而是用邊界值填充,但應該注意的是,沒有邊界策略是完美的;處理邊界問題的理想方法將取決於您的特定信號。

如果你看到Wikipedia's description of median filters,它們通過在邊緣填充邊緣值來擴展信號的邊緣,這也是合理的。他們還注意到這三種處理邊界問題的其他方法:

  • 避免處理邊界,不管是否裁剪信號邊界。
  • 從信號中的其他位置獲取條目。例如,對於圖像,可以選擇來自遠水平或垂直邊界的條目。
  • 縮小邊界附近的窗口,以便每個窗口都已滿(如您所做的那樣。)

最後,你真的需要嘗試不同的選擇,看看什麼對你的信號最適合。這種濾波的核心假設是你的信號會非常大,並且邊界問題不應該是關鍵的(因爲大部分信號不存在於邊界上)。不過,如果SciPy允許您選擇它應該在邊界上執行的操作,那就太好了!

+0

只是爲了擴大這個答案一點,那些尋找替代滾動平均的功能可以看看: 熊貓滾滾位數: http://pandas.pydata.org/pandas-docs/stable/computation.html# moving-rolling-statistics-moments and scipy.ndimage: http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.ndimage.filters.median_filter.html – ConnectedSystems