Implementación de Python del filtro Butterworth y el filtro de muesca (basado en Scipy)

Los filtros Butterworth y los filtros de muesca son muy comunes en el procesamiento de señales y estarán involucrados en muchos artículos. El primero puede filtrar señales de alta frecuencia, baja frecuencia o señales que pasan una cierta frecuencia, y el segundo puede usarse para filtrar señales específicas. Para las señales de frecuencia, no soy un estudiante de comunicación y carezco relativamente de conocimientos teóricos sobre las señales, por lo que este artículo se centra principalmente en la implementación del código.

En el proceso de búsqueda de información, descubrí que muchos blogs solo presentan funciones brevemente y rara vez las explican. Por lo tanto, este artículo explicará en detalle los métodos de uso de cada función y el efecto de realización del resultado final, solo como un registro.

generación de datos

Para la demostración de seguimiento, generé una imagen con tres funciones trigonométricas superpuestas como la señal de entrada filtrada más tarde.

plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
plt.rcParams['axes.unicode_minus'] = False
fs = 300.0  # 采样频率
T = 5.0  # 周期5s
n = int(T * fs)  # 总样本数
t = np.linspace(0, T, n, endpoint=False)
y_1 = np.sin(2.4 * 2 * np.pi * t)  
y_2 = np.sin(9 * 2 * np.pi * t) 
y_3 = np.sin(12 * 2 * np.pi * t) 
data = y_1 + y_2 + y_3  # 生成一个三个函数叠加的图像
plt.plot(t, data)
plt.title('原始图像')
plt.show()

Las fórmulas de cálculo de frecuencia de las funciones trigonométricas sen y cos son w/(2*pi), por lo que las frecuencias de las tres funciones son 2,4, 9 y 12, respectivamente.

La imagen de la imagen original es la siguiente.

Filtro Butterworth

El primero es el filtro Butterworth. La biblioteca implementada es signal.butter. Las funciones que se pueden implementar en la biblioteca son paso alto, paso bajo, paso de banda y parada de banda . Entre ellas, el paso bajo es más comúnmente y generalmente se usa para extraer información de la señal. También es la biblioteca. El método de filtrado predeterminado, el paso alto se usa para agudizar la señal, el paso de banda pasa a través de la frecuencia dentro de la frecuencia especificada y el paso de banda evita que pase la señal dentro de una cierta frecuencia, que es un poco como el método de filtro de muesca.

La función que implementa butterworth es la siguiente:

b, a = butter(N=order, Wn=normal_f, btype='lowpass', analog=False)

en:

N representa el pedido;

Wn representa la frecuencia normalizada y la fórmula de cálculo es 2*frecuencia de corte/frecuencia de muestreo;

El parámetro de btype puede ser {'lowpass', 'highpass', 'bandpass', 'bandstop'}, que son paso bajo, paso alto, paso banda y paso banda respectivamente. El valor predeterminado es paso bajo Si es paso de banda, el rango es un binario La lista de metales , porque es un rango, es el límite superior y el límite inferior de frecuencia, analógico es Falso, lo que significa que devuelve una señal digital, de lo contrario es una señal analógica ( No sé mucho sobre esto).

El siguiente es el código, que implementa el filtrado de paso bajo:

def butter_filter(data, fs, cutoff, order=5):
    normal_f = 2*np.array(cutoff)/fs
    b, a = butter(N=order, Wn=normal_f, btype='lowpass', analog=False)
    # 根据阶数n和归一化截止频率Wn计算ButterWorth滤波器分子分母系数(b为分子系数的矢量形式,a为分母系数的矢量形式)
    return np.array(filtfilt(b, a, data)),b,a  

# 滤波参数并绘制频率响应图
cutoff = 3.667  # 设定截止频率,频率为截止频率时信号是输入信号的0.707倍
order = 5 # 设定滤波器阶数,阶数越高那么越能够有效地抑制不需要的频率成分
y,b,a = butter_lowpass_filter(data, fs, cutoff, order)  # 小数据集
w, h = freqz(b, a, worN=800)  # 计算滤波器的频率响应(Response),也就是对不同频段的放大倍数,0.707倍的是截止频率
plt.subplot(2, 1, 1)
plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
plt.plot(cutoff, 0.5 * np.sqrt(2), 'ko')
plt.axvline(cutoff, color='k')
plt.xlim(0, 10)
plt.title("频率响应图")
plt.xlabel('频率')
plt.grid()  # 画线
plt.subplot(2, 1, 2)
plt.plot(t, data, 'b-', label='滤波前')
plt.plot(t, y, 'g-', linewidth=2, label='滤波后')
plt.xlabel('时间')
plt.grid()
plt.legend()
plt.subplots_adjust(hspace=0.35)
plt.show()

Ejecute la imagen y observe la primera imagen, que es el diagrama de respuesta de frecuencia . Puede ver que el factor de aumento de la señal en la frecuencia de corte de 3,6 es de aproximadamente 0,7, y es casi 0 después de que la frecuencia es 8; mire el segunda imagen, que es la señal de frecuencia filtrada Se muestra , se puede ver que la señal se acerca a una función trigonométrica, esta es la curva con una frecuencia de 2.4, porque la señal en la banda de alta frecuencia (f=9&f=12) ha sido filtrado.

 Al mismo tiempo, se dibujan la imagen con una frecuencia de 2,4 y la imagen filtrada, y se encuentra que se superponen casi por completo.

plt.plot(t,y,'b-', label='滤波后图像')
plt.plot(t,y_1,'y',label='f=2.4图像')
plt.legend()
plt.xlabel('频率')
plt.title('函数对比')
plt.show()

Código completo para esta parte

import numpy as np
from matplotlib import pyplot as plt
from scipy import signal
from scipy.signal import lfilter, butter, filtfilt, freqz


def butter_filter(data, fs, cutoff, order=5):
    normal_f = 2*np.array(cutoff)/fs
    b, a = butter(N=order, Wn=normal_f, btype='lowpass', analog=False)
    # 根据阶数n和归一化截止频率Wn计算ButterWorth滤波器分子分母系数(b为分子系数的矢量形式,a为分母系数的矢量形式)
    return np.array(filtfilt(b, a, data)),b,a  


if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
    plt.rcParams['axes.unicode_minus'] = False
    fs = 300.0  # 采样频率
    T = 5.0  # 周期5s
    n = int(T * fs)  # 总样本数
    t = np.linspace(0, T, n, endpoint=False)
    y_1 = np.sin(2.4 * 2 * np.pi * t) 
    y_2 = np.sin(9 * 2 * np.pi * t)  
    y_3 = np.sin(12 * 2 * np.pi * t)  
    data = y_1 + y_2 + y_3  # 生成一个三个函数叠加的图像
    plt.plot(t, data)
    plt.title('原始图像')
    plt.show()

    # 滤波参数并绘制频率响应图
    cutoff = 3.667  # 设定截止频率,频率为截止频率时信号是输入信号的0.707倍
    order = 5 # 设定滤波器阶数,阶数越高那么越能够有效地抑制不需要的频率成分
    y,b,a = butter_filter(data, fs, cutoff, order)  # 小数据集
    w, h = freqz(b, a, worN=800)  # 计算滤波器的频率响应(Response),也就是对不同频段的放大倍数,0.707倍的是截止频率
    plt.subplot(2, 1, 1)
    plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
    plt.plot(cutoff, 0.5 * np.sqrt(2), 'ko')
    plt.axvline(cutoff, color='k')
    plt.xlim(0, 10)
    plt.title("频率响应图")
    plt.xlabel('频率')
    plt.grid()  # 画线
    plt.subplot(2, 1, 2)
    plt.plot(t, data, 'b-', label='滤波前')
    plt.plot(t, y, 'g-', linewidth=2, label='滤波后')
    plt.xlabel('时间')
    plt.grid()
    plt.legend()
    plt.subplots_adjust(hspace=0.35)
    plt.show()
    
    # 绘制对比图像 
    plt.plot(t,y,'b-', label='滤波后图像')
    plt.plot(t,y_1,'y',label='f=2.4图像')
    plt.legend()
    plt.xlabel('频率')
    plt.title('函数对比')
    plt.show()

 Filtro de muesca

El filtro de muesca se utiliza principalmente para filtrar señales de una frecuencia específica. Por ejemplo, una señal de 50 Hz es una señal de CA y se filtrará en muchos casos.

Para implementar el filtro, también es necesario calcular dos parámetros a y b, la función es la siguiente:

b,a = signal.iirnotch(w0, Q)

en:

w0 representa la frecuencia estandarizada, y el método de cálculo es el mismo que el de Butterworth arriba;

Q representa el factor de calidad, y cuanto más grande parece, más estrecho es el rango de filtrado.

La siguiente es la implementación del código. La imagen original aún es consistente con la Butterworth anterior, y la escribí juntas directamente.

def notch_filter(data,fs,Q,f_remove):
    w0 = 2*f_remove / fs
    b, a = signal.iirnotch(w0, Q)
    return np.array(filtfilt(b, a, data)),b,a

# 滤波参数并绘制频率响应图
f_remove = 9  # 设定截止频率,频率为截止频率时信号是输入信号的0.707倍
Q = 300 # Q表示质量因数,越大滤波的范围越窄(目标频率周围的)
y,b,a = notch_filter(data, fs, Q,f_remove)  # 小数据集
w, h = freqz(b, a, worN=800)  # 计算滤波器的频率响应(Response),也就是对不同频段的放大倍数,0.707倍的是截止频率
plt.subplot(2, 1, 1)
plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
plt.plot(f_remove, 0.5 * np.sqrt(2), 'ko')
plt.axvline(f_remove, color='k')
plt.xlim(0, 10)
plt.title("频率响应图")
plt.xlabel('频率')
plt.grid()  # 画线
plt.subplot(2, 1, 2)
plt.plot(t, data, 'b-', label='滤波前')
plt.plot(t, y, 'g-', linewidth=2, label='滤波后')
plt.xlabel('时间')
plt.grid()
plt.legend()
plt.subplots_adjust(hspace=0.35)
plt.show()

plt.plot(t,y,'b-', label='滤波后图像')
plt.plot(t,y_1+y_3,'y',label='f=2.4图像')
plt.legend()
plt.xlabel('频率')
plt.title('函数对比')
plt.show()

 Configuré la frecuencia de filtrado como f = 9, y puede ver que 9 puntos en el gráfico de respuesta de frecuencia ya son 0. Mirando el segundo gráfico, debería haber dos funciones trigonométricas en la imagen filtrada. 

Dibuje una comparación de las imágenes superpuestas y filtradas de las dos funciones trigonométricas, y se encuentra que se superponen casi por completo, lo que indica que la imagen con una frecuencia de 9 ha sido filtrada.

Código completo para esta parte

import numpy as np
from matplotlib import pyplot as plt
from scipy import signal
from scipy.signal import lfilter, butter, filtfilt, freqz


def notch_filter(data,fs,Q,f_remove):
    w0 = 2*f_remove / fs
    b, a = signal.iirnotch(w0, Q)
    return np.array(filtfilt(b, a, data)),b,a

if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文
    plt.rcParams['axes.unicode_minus'] = False
    fs = 300.0  # 采样频率
    T = 5.0  # 周期5s
    n = int(T * fs)  # 总样本数
    t = np.linspace(0, T, n, endpoint=False)
    y_1 = np.sin(2.4 * 2 * np.pi * t)
    y_2 = np.sin(9 * 2 * np.pi * t)
    y_3 = np.sin(12 * 2 * np.pi * t)
    data = y_1 + y_2 + y_3  # 生成一个三个函数叠加的图像
    plt.plot(t, data)
    plt.title('原始图像')
    plt.show()

    # 滤波参数并绘制频率响应图
    f_remove = 9  # 设定截止频率,频率为截止频率时信号是输入信号的0.707倍
    Q = 30 # Q表示质量因数,越大滤波的范围越窄(目标频率周围的)
    y,b,a = notch_filter(data, fs, Q,f_remove)  # 小数据集
    w, h = freqz(b, a, worN=800)  # 计算滤波器的频率响应(Response),也就是对不同频段的放大倍数,0.707倍的是截止频率
    plt.subplot(2, 1, 1)
    plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
    plt.plot(f_remove, 0.5 * np.sqrt(2), 'ko')
    plt.axvline(f_remove, color='k')
    plt.xlim(0, 10)
    plt.title("频率响应图")
    plt.xlabel('频率')
    plt.grid()  # 画线
    plt.subplot(2, 1, 2)
    plt.plot(t, data, 'b-', label='滤波前')
    plt.plot(t, y, 'g-', linewidth=2, label='滤波后')
    plt.xlabel('时间')
    plt.grid()
    plt.legend()
    plt.subplots_adjust(hspace=0.35)
    plt.show()

    plt.plot(t,y,'b-', label='滤波后图像')
    plt.plot(t,y_1+y_3,'y',label='f=2.4+f=12图像')
    plt.legend()
    plt.xlabel('频率')
    plt.title('函数对比')
    plt.show()

Eso es todo por ahora, agregaré algunos más cuando tenga la oportunidad.

Supongo que te gusta

Origin blog.csdn.net/weixin_60360239/article/details/131827400
Recomendado
Clasificación