显示经过滤的数字信号时的Jello效果

时间:2015-09-04 14:06:58

标签: python algorithm python-2.7 numpy signal-processing

我希望通过一些基本过滤(带阻,带通)实时显示一个测量信号。

当我这样做的时候,我会得到一些jello effet(抱歉Gif质量不好)

jello effect

即使它不是正在发生的事情,让我假装我用伪代码实现了这个算法:

 signal = np.array(some_data)
 plot = FuncAnimation(init_function, update_function)

 for each frame:
   - shift signal on the left # make space and discard oldest samples
   - add new samples on the right
   - filtered_signal = filter(signal) # using signal.butter and signal.filtfilt
   - update_plot(filtered_signal) # FuncAnimation update function

我正在寻找摆脱这种不良影响的技巧。有什么想法吗?

编辑1

如果没有动画,则会附加20个连续滤波信号。

enter image description here

  • 第一个图是signal(原始信号)
  • 第二个图包含最后20个filtered_signal
  • 第三个图包含为了更好的可视化而移动的最后一个filtered_signal

编辑2

  • signal是一个固定大小的缓冲区,包含N = 1000个样本
  • filtered_signal是从头开始为每个框架创建的
  • 采样频率为fs = 250Hz
  • 应用2个滤波器:50Hz陷波和[0.5Hz,120Hz]带通

编辑3 这是一个完整的工作示例:

  • 第一个图是原始信号
  • 第二个图是滤波后的信号(带通[0.5Hz,120Hz])

源代码:

import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
import matplotlib.animation as animation
import time


N = 1000
fs = 250
last_update = time.time()
sample_id = 0


def all_samples(length=10000):
    # generate a dummy signal
    st = 1.0 / fs
    t = np.arange(length) * st
    sig1 = 1*np.sin(2*np.pi * 2*t) + 2
    sig2 = 0.25*np.sin(2*np.pi * 3*t) + 4
    sig3 = 2*np.sin(2*np.pi * 4*t) + 5
    return sig1 + sig2 + sig3


def band_pass(low_cut, high_cut, order=2):
    # compute butterworth b, a coefficients
    band = np.array([low_cut, high_cut])
    Wn = band / (float(fs/2.0))
    b, a = signal.butter(order, Wn, 'bandpass')
    return b, a


def filter(raw_signal):
    # apply filter 
    b, a = band_pass(0.5, 120)
    return signal.filtfilt(b, a, raw_signal)


def init():
    # init function for FuncAnimation blit=True
    global axe_raw, line_raw
    global axe_filt, line_filt
    line_filt.set_visible(False)
    line_raw.set_visible(False)
    axe_raw.set_xlim(0, 1000)
    axe_raw.set_ylim(5, 15)
    axe_filt.set_xlim(0, 1000)
    axe_filt.set_ylim(-5, 5)
    return line_raw, line_filt,


def update(n):
    global raw_signal, axe_raw, line_raw
    global axe_filt, line_filt
    global last_update, fs, sample_id
    if n == 1:
        line_raw.set_visible(True)
        line_filt.set_visible(True)

    # add new samples
    now = time.time()
    sample_count = int((now - last_update) * fs)
    raw_signal = np.roll(raw_signal, -sample_count)
    raw_signal[-sample_count:] = all_samples[sample_id:sample_id + sample_count]
    last_update = now
    sample_id += sample_count

    # update plot (raw + filtered)
    line_raw.set_ydata(raw_signal)
    line_filt.set_ydata(filter(raw_signal))


    return line_raw, line_filt


all_samples = all_samples()
raw_signal = np.zeros(N)

# matplotlib animation
figure = plt.figure()
axe_raw = figure.add_subplot(211)
axe_filt = figure.add_subplot(212)
line_raw, = axe_raw.plot(raw_signal)
line_filt, = axe_filt.plot(np.zeros(N))
anim = animation.FuncAnimation(figure,
                               update,
                               init_func=init,
                               interval=5,
                               blit=True)
plt.show()

0 个答案:

没有答案