Цифровой фильтр Баттерворта низких частот на Python
В этой статье мы собираемся обсудить, как разработать цифровой фильтр Баттерворта низких частот с использованием Python. Фильтр Баттерворта - это тип фильтра обработки сигналов, который имеет как можно более ровную частотную характеристику в полосе пропускания. Давайте возьмем приведенные ниже спецификации, чтобы разработать фильтр и понаблюдать за амплитудой, фазой и импульсной характеристикой цифрового фильтра Баттерворта.
Технические характеристики следующие:
- Частота дискретизации 40 кГц
- Граничная частота полосы пропускания 4 кГц
- Граничная частота полосы задерживания 8 кГц
- Пульсации полосы пропускания 0,5 дБ
- Минимальное затухание в полосе заграждения 40 дБ
Мы построим график амплитуды, фазы и импульсной характеристики фильтра.
Пошаговый подход:
Step 1: Importing all the necessary libraries.
Python3
# import required modules import numpy as np import matplotlib.pyplot as plt from scipy import signal import math |
Step 2: Define variables with the given specifications of the filter.
Python3
# Specifications of Filter # sampling frequency f_sample = 40000 # pass band frequency f_pass = 4000 # stop band frequency f_stop = 8000 # pass band ripple fs = 0.5 # pass band freq in radian wp = f_pass / (f_sample / 2 ) # stop band freq in radian ws = f_stop / (f_sample / 2 ) # Sampling Time Td = 1 # pass band ripple g_pass = 0.5 # stop band attenuation g_stop = 40 |
Step3: Building the filter using signal.buttord function.
Python3
# Conversion to prewrapped analog frequency omega_p = ( 2 / Td) * np.tan(wp / 2 ) omega_s = ( 2 / Td) * np.tan(ws / 2 ) # Design of Filter using signal.buttord function N, Wn = signal.buttord(omega_p, omega_s, g_pass, g_stop, analog = True ) # Printing the values of order & cut-off frequency! print ( "Order of the Filter=" , N) # N is the order # Wn is the cut-off freq of the filter print ( "Cut-off frequency= {:.3f} rad/s " . format (Wn)) # Conversion in Z-domain # b is the numerator of the filter & a is the denominator b, a = signal.butter(N, Wn, "low" , True ) z, p = signal.bilinear(b, a, fs) # w is the freq in z-domain & h is the magnitude in z-domain w, h = signal.freqz(z, p, 512 ) |
Выход:
Step 4: Plotting the Magnitude Response.
Python3
# Magnitude Response plt.semilogx(w, 20 * np.log10( abs (h))) plt.xscale( "log" ) plt.title( "Butterworth filter frequency response" ) plt.xlabel( "Frequency [Hz]" ) plt.ylabel( "Amplitude [dB]" ) plt.margins( 0 , 0.1 ) plt.grid(which = "both" , axis = "both" ) plt.axvline( 100 , color = "green" ) plt.show() |
Выход:
Step 5: Plotting the Impulse Response.
Python3
# Impulse Response imp = signal.unit_impulse( 40 ) c, d = signal.butter(N, 0.5 ) response = signal.lfilter(c, d, imp) plt.stem(np.arange( 0 , 40 ), imp, use_line_collection = True ) plt.stem(np.arange( 0 , 40 ), response, use_line_collection = True ) plt.margins( 0 , 0.1 ) plt.xlabel( "Time [samples]" ) plt.ylabel( "Amplitude" ) plt.grid( True ) plt.show() |
Выход:
Step 6: Plotting the Phase Response.
Python3
# Phase Response fig, ax1 = plt.subplots() ax1.set_title( "Digital filter frequency response" ) ax1.set_ylabel( "Angle(radians)" , color = "g" ) ax1.set_xlabel( "Frequency [Hz]" ) angles = np.unwrap(np.angle(h)) ax1.plot(w / 2 * np.pi, angles, "g" ) ax1.grid() ax1.axis( "tight" ) plt.show() |
Выход:
Below is the complete program based on the above approach:
Python
# import required modules import numpy as np import matplotlib.pyplot as plt from scipy import signal import math # Specifications of Filter # sampling frequency f_sample = 40000 # pass band frequency f_pass = 4000 # stop band frequency f_stop = 8000 # pass band ripple fs = 0.5 # pass band freq in radian wp = f_pass / (f_sample / 2 ) # stop band freq in radian ws = f_stop / (f_sample / 2 ) # Sampling Time Td = 1 # pass band ripple g_pass = 0.5 # stop band attenuation g_stop = 40 # Conversion to prewrapped analog frequency omega_p = ( 2 / Td) * np.tan(wp / 2 ) omega_s = ( 2 / Td) * np.tan(ws / 2 ) # Design of Filter using signal.buttord function N, Wn = signal.buttord(omega_p, omega_s, g_pass, g_stop, analog = True ) # Printing the values of order & cut-off frequency! print ( "Order of the Filter=" , N) # N is the order # Wn is the cut-off freq of the filter print ( "Cut-off frequency= {:.3f} rad/s " . format (Wn)) # Conversion in Z-domain # b is the numerator of the filter & a is the denominator b, a = signal.butter(N, Wn, "low" , True ) z, p = signal.bilinear(b, a, fs) # w is the freq in z-domain & h is the magnitude in z-domain w, h = signal.freqz(z, p, 512 ) # Magnitude Response plt.semilogx(w, 20 * np.log10( abs (h))) plt.xscale( "log" ) plt.title( "Butterworth filter frequency response" ) plt.xlabel( "Frequency [Hz]" ) plt.ylabel( "Amplitude [dB]" ) plt.margins( 0 , 0.1 ) plt.grid(which = "both" , axis = "both" ) plt.axvline( 100 , color = "green" ) plt.show() # Impulse Response imp = signal.unit_impulse( 40 ) c, d = signal.butter(N, 0.5 ) response = signal.lfilter(c, d, imp) plt.stem(np.arange( 0 , 40 ), imp, use_line_collection = True ) plt.stem(np.arange( 0 , 40 ), response, use_line_collection = True ) plt.margins( 0 , 0.1 ) plt.xlabel( "Time [samples]" ) plt.ylabel( "Amplitude" ) plt.grid( True ) plt.show() # Phase Response fig, ax1 = plt.subplots() ax1.set_title( "Digital filter frequency response" ) ax1.set_ylabel( "Angle(radians)" , color = "g" ) ax1.set_xlabel( "Frequency [Hz]" ) angles = np.unwrap(np.angle(h)) ax1.plot(w / 2 * np.pi, angles, "g" ) ax1.grid() ax1.axis( "tight" ) plt.show() |
Выход:
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.