파이썬에서 샘플링 된 신호에 대한 저역 통과 필터를 작성하는 방법은 무엇입니까?


16

나는 각각의 1ns (1e-9 초)를 샘플링하고 1e4 포인트를 갖는 신호를 가지고 있습니다. 이 신호에서 고주파수를 필터링해야합니다. 10MHz보다 높은 주파수를 필터링해야한다고 가정 해 봅시다. 차단 주파수보다 낮은 주파수의 경우 신호가 변경되지 않고 통과되기를 원합니다. 차단 주파수보다 낮은 주파수에서는 필터의 게인이 1이됩니다. 필터 순서를 지정하고 싶습니다. 즉, 1 차 필터는 차단 주파수 후 20 db / decade 기울기 (파워 롤오프)를 가지며 2 차 필터는 차단 주파수 후 40 db / dec 기울기를가집니다. 고성능 코드가 중요합니다.

답변:


19

버터 기능을 사용하여 설계된 필터의 주파수 응답 은 다음과 같습니다.

버터 워스 필터 응답

그러나 필터를 일정한 단조 필터 설계로 제한 할 이유가 없습니다. 저지 대역과 가파른 전환 대역에서 더 높은 감쇠를 원한다면 다른 옵션이 있습니다. iirdesing을 사용하여 필터를 지정하는 방법에 대한 자세한 내용 은 this를 참조 하십시오 . 버터 설계에 대한 주파수 응답 플롯에서 알 수 있듯이 컷오프 주파수 (-3dB 포인트)는 목표와 거리가 멀다. 필터링 전 다운 샘플링으로이를 완화 할 수 있습니다 (대역폭의 2 % 인 좁은 필터에서는 설계 기능이 어려울 수 있습니다). 컷오프가 지정된 원래 샘플 속도를 필터링하는 방법을 살펴 보겠습니다.

import numpy as np
from scipy import signal
from matplotlib import pyplot as plt

from scipy.signal import fir_filter_design as ffd
from scipy.signal import filter_design as ifd

# setup some of the required parameters
Fs = 1e9           # sample-rate defined in the question, down-sampled

# remez (fir) design arguements
Fpass = 10e6       # passband edge
Fstop = 11.1e6     # stopband edge, transition band 100kHz
Wp = Fpass/(Fs)    # pass normalized frequency
Ws = Fstop/(Fs)    # stop normalized frequency

# iirdesign agruements
Wip = (Fpass)/(Fs/2)
Wis = (Fstop+1e6)/(Fs/2)
Rp = 1             # passband ripple
As = 42            # stopband attenuation

# Create a FIR filter, the remez function takes a list of 
# "bands" and the amplitude for each band.
taps = 4096
br = ffd.remez(taps, [0, Wp, Ws, .5], [1,0], maxiter=10000) 

# The iirdesign takes passband, stopband, passband ripple, 
# and stop attenuation.
bc, ac = ifd.iirdesign(Wip, Wis, Rp, As, ftype='ellip')  
bb, ab = ifd.iirdesign(Wip, Wis, Rp, As, ftype='cheby2') 

원본 샘플 속도 필터

언급 한 바와 같이, 우리는 대역폭의 작은 백분율을 필터링하려고하기 때문에 필터는 급격한 컷오프를 갖지 않습니다. 이 경우, 저역 통과 필터는 더 나은 필터를 얻기 위해 대역폭을 줄일 수 있습니다. python / scipy.signal resample 기능을 사용하여 대역폭을 줄일 수 있습니다.

재 샘플링 기능은 앨리어싱을 방지하기 위해 필터링을 수행합니다. 사전 필터링을 수행하여 앨리어싱을 줄일 수 있으며이 경우 간단히 100으로 다시 샘플링하고 수행 할 수 있지만 필터 생성에 대한 질문이있었습니다. 이 예제에서는 25 씩 다운 샘플링하고 새 필터를 만듭니다.

R = 25;            # how much to down sample by
Fsr = Fs/25.       # down-sampled sample rate
xs = signal.resample(x, len(x)/25.)

FIR 필터의 설계 매개 변수를 업데이트하면 새로운 반응이 나타납니다.

# Down sampled version, create new filter and plot spectrum
R = 25.             # how much to down sample by
Fsr = Fs/R          # down-sampled sample rate
Fstop = 11.1e6      # modified stopband
Wp = Fpass/(Fsr)    # pass normalized frequency
Ws = Fstop/(Fsr)    # stop normalized frequency
taps = 256
br = ffd.remez(taps, [0, Wp, Ws, .5], [1,0], maxiter=10000) 

다운 샘플링 된 필터 응답

다운 샘플링 된 데이터에서 작동하는 필터의 응답이 더 좋습니다. FIR 필터 사용의 또 다른 이점은 선형 위상 응답이 있다는 것입니다.


1
감사합니다. 신호 스펙트럼 그래프를 작성하는 방법
Alex

훌륭한 답변을 주셔서 대단히 감사합니다! Remez를 사용하여 계산 된 계수를 기반으로 FIR 필터를 적용하는 방법을 설명 할 수 있는지 궁금합니다. 나는 어떤 문제를 이해하는 데 filtfilt에 대해 원하는 a매개 변수를.
ali_m

만약 (a 필터 설계에서 계수 일단 B FIR에 대한 B 및 : IIR을위한)는 필터링 수행하는 몇 가지 기능을 사용할 수 lfilter , 말다 , filtfilt를 . 일반적으로 이러한 모든 기능들이 유사한 동작 : 만약 FIR 필터는 단순히 설정되어 있다면, Y = filtfilt (B, A, X)을 A = 1 , X는 입력 신호, (B)는 전나무 계수이다. 이 게시물도 도움 이 될 수 있습니다.
Christopher Felton

5

이 작동합니까?

from __future__ import division
from scipy.signal import butter, lfilter

fs = 1E9 # 1 ns -> 1 GHz
cutoff = 10E6 # 10 MHz
B, A = butter(1, cutoff / (fs / 2), btype='low') # 1st order Butterworth low-pass
filtered_signal = lfilter(B, A, signal, axis=0)

그러나 문서 가 완전하지는 않습니다. 것 같습니다 butter에 대한 래퍼입니다 iirfilter, 더 나은 문서화가 :

N : int 필터의 순서입니다. Wn : array_like 임계 주파수를 제공하는 스칼라 또는 길이 -2 시퀀스.

그러나이 물건의 대부분은 matlab에서 복제되었으므로 설명서 도 볼 수 있습니다.

정규화 된 차단 주파수 Wn은 0과 1 사이의 숫자 여야합니다. 여기서 1은 나이 퀴 스트 주파수, 샘플 당 π 라디안에 해당합니다.

최신 정보:

이 기능에 대한 설명서 를 추가했습니다 . :) Github를 사용하면 쉽게 할 수 있습니다.



1

이 FIR 필터로 좋은 결과를 얻었습니다. 신호 오프셋을 보상하기 위해 "정방향"과 "역방향"으로 필터를 두 번 적용합니다 ( filtfilt기능이 작동하지 않아 이유를 모름).

def firfilt(interval, freq, sampling_rate):
    nfreq = freq/(0.5*sampling_rate)
    taps =  sampling_rate + 1
    a = 1
    b = scipy.signal.firwin(taps, cutoff=nfreq)
    firstpass = scipy.signal.lfilter(b, a, interval)
    secondpass = scipy.signal.lfilter(b, a, firstpass[::-1])[::-1]
    return secondpass

이 코드를 취한 위치와 대역 통과 및 고역 통과 필터 예제를 얻을 수있는 곳에서 설계 및 사용을 필터링하는 훌륭한 리소스는 THIS 입니다.


FIR 필터를 정방향 및 역방향으로 필터링하면 많은 이점이 있다고 생각하지 않습니다. 역 필터링을 통해 비선형 위상 필터에서 선형 위상을 얻을 수 있기 때문에 IIR 필터는 정방향 / 역방향 (여과 필터)의 이점을 얻을 수 있습니다.
Christopher Felton

2
@ChristopherFelton RAW 근전도 신호를 스무딩 된 버전과 동기화하기 위해 역으로 바꿨습니다. 신호를 바꿀 수는 있지만 두 번 필터링하면 문제가 줄어 듭니다. 두 번째 패스가 이미 필터링 된 첫 번째 패스를 거의 변경하지 않는다는 점에 주목할 가치가 있습니다 ... 감사합니다!
heltonbiker

예 지연 (그룹 지연)을 제거하려면 좋은 점입니다.
Christopher Felton

1

의견이 없습니다 ...

@endolith : scipy.signal.filtfilt (B, A, x)를 사용하는 것을 제외하고는 당신과 동일하게 사용합니다. 여기서 x 는 필터링 할 입력 벡터입니다 ( 예 : numpy.random.normal (size = (N))) . filtfilt 는 신호를 정방향 및 역방향으로 전달합니다. 완전성을 위해 (대부분 @endolith와 동일) :

import numpy as np
import scipy.signal as sps

input = np.random.normal(size=(N)) # Random signal as example
bz, az = sps.butter(FiltOrder, Bandwidth/(SamplingFreq/2)) # Gives you lowpass Butterworth as default
output = sps.filtfilt(bz, az, input) # Makes forward/reverse filtering (linear phase filter)

@heltonbiker 가 제안한 filtfilt에는 내가 생각하는 계수 배열이 필요합니다. 복잡한베이스 밴드에서 대역 통과 필터링을 수행해야하는 경우보다 복잡한 구성이 필요하지만 여기서는 문제가되지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.