簡體   English   中英

如何使用 scipy 和 lfilter 進行實時過濾?

[英]How to real-time filter with scipy and lfilter?

免責聲明:我可能不擅長 DSP,因此我遇到的問題比我應該讓這段代碼工作的要多。

我需要在傳入信號發生時對其進行過濾。 我試圖讓這段代碼工作,但到目前為止我還沒有做到。 參考scipy.signal.lfilter 文檔

import numpy as np
import scipy.signal
import matplotlib.pyplot as plt
from lib import fnlib

samples = 100
x = np.linspace(0, 7, samples)
y = [] # Unfiltered output
y_filt1 = [] # Real-time filtered

nyq = 0.5 * samples
f1_norm = 0.1 / nyq
f2_norm = 2 / nyq
b, a = scipy.signal.butter(2, [f1_norm, f2_norm], 'band', analog=False)
zi = scipy.signal.lfilter_zi(b,a)
zi = zi*(np.sin(0) + 0.1*np.sin(15*0))

這最初將zi設置為zi*y[0 ] ,在本例中為 0。我是從lfilter文檔中的示例代碼中得到的,但我不確定這是否正確。

然后到了我不確定如何處理少數初始樣本的地步。 這里的系數ablen(a) = 5 lfilter將輸入值從現在變為 n-4 時,我是用零填充它,還是需要等到 5 個樣本過去並將它們作為單個塊,然后以相同的方式連續采樣每個下一步?

for i in range(0, len(a)-1): # Append 0 as initial values, wrong?
    y.append(0)

step = 0
for i in xrange(0, samples): #x:
    tmp = np.sin(x[i]) + 0.1*np.sin(15*x[i])
    y.append(tmp)

    # What to do with the inital filterings until len(y) ==  len(a) ?

    if (step> len(a)):
        y_filt, zi = scipy.signal.lfilter(b, a, y[-len(a):], axis=-1, zi=zi)
        y_filt1.append(y_filt[4])

print(len(y))
y = y[4:]
print(len(y))
y_filt2 = scipy.signal.lfilter(b, a, y) # Offline filtered

plt.plot(x, y, x, y_filt1, x, y_filt2)
plt.show()

我想我遇到了同樣的問題,並在https://github.com/scipy/scipy/issues/5116上找到了解決方案:

from scipy import zeros, signal, random

def filter_sbs():
    data = random.random(2000)
    b = signal.firwin(150, 0.004)
    z = signal.lfilter_zi(b, 1)
    result = zeros(data.size)
    for i, x in enumerate(data):
        result[i], z = signal.lfilter(b, 1, [x], zi=z)
    return result

if __name__ == '__main__':
    result = filter_sbs()

這個想法是在每次對lfilter后續調用中傳遞過濾器狀態z 對於前幾個樣本,過濾器可能會給出奇怪的結果,但稍后(取決於過濾器長度)它開始正確運行。

我不相信上面的答案是正確的。 z = signal.lfilter_zi(b,1)初始化濾波器狀態正是導致前幾個樣本變得“奇怪”的原因,如果我正確理解 OP,這就是問題所在。 正如我在評論中所說的那樣,期望的結果是逐個樣本的實現應該完全等同於一次過濾整個數據集(數值精度除外)。 這可以通過將狀態初始化為 0 ( z=zeros(b.size-1) ) 來完成。 這是正確的:

from scipy import signal, random
from numpy import zeros

def filter_sbs(data, b):
    z = zeros(b.size-1)
    result = zeros(data.size)
    for i, x in enumerate(data):
        result[i], z = signal.lfilter(b, 1, [x], zi=z)
    return result
    
def filter(data, b):
    result = signal.lfilter(b,1,data)
    return result

if __name__ == '__main__':
    data = random.random(20000)
    b = signal.firwin(150, 0.004)
    result1 = filter_sbs(data, b)
    result2 = filter(data, b)
    print(result1 - result2)

輸出:

[ 0.00000000e+00  0.00000000e+00  0.00000000e+00 ... -5.55111512e-17
  0.00000000e+00  1.66533454e-16]

我承認我不太確定z = signal.lfilter_zi(b,1)正在做什么(看起來像半余弦),但初始狀態應該為零。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM