10. Filtros

En este cap铆tulo aprendemos sobre los filtros digitales usando Python. Cubrimos los tipos de filtros (FIR/IIR y paso bajo/paso alto/paso de banda/parada de banda), c贸mo se representan los filtros digitalmente y c贸mo se dise帽an. Terminamos con una introducci贸n al pulse shaping, que exploraremos m谩s a fondo en el capitulo Formador de Pulso .

Filtros B谩sicos

Los filtros se utilizan en muchas disciplinas. Por ejemplo, el procesamiento de im谩genes se hace uso intensivo de filtros 2D, donde la entrada y la salida son im谩genes. Puedes usar un filtro todas las ma帽anas para preparar tu caf茅, que filtra los s贸lidos del l铆quido. En DSP, los filtros se utilizan principalmente para:

  1. Separaci贸n de se帽ales que se han combinado (por ejemplo, extraer la se帽al que desea)

  2. Eliminaci贸n del exceso de ruido despu茅s de recibir una se帽al.

  3. Restauraci贸n de se帽ales que han sido distorsionadas de alguna manera (por ejemplo, un ecualizador de audio es un filtro)

Ciertamente, existen otros usos para los filtros, pero este cap铆tulo est谩 destinado a presentar el concepto en lugar de explicar todas las formas en que se puede realizar el filtrado.

Quiz谩s pienses que s贸lo nos importan los filtros digitales; despu茅s de todo, este libro de texto explora DSP. Sin embargo, es importante saber que muchos filtros ser谩n anal贸gicos, como los de nuestros SDR colocados antes del convertidor anal贸gico a digital (ADC) en el lado de recepci贸n. La siguiente imagen yuxtapone un esquema de un circuito de filtro anal贸gico con una representaci贸n de diagrama de flujo de un algoritmo de filtrado digital.

Analog vs digital filters

En DSP, donde la entrada y la salida son se帽ales, un filtro tiene una se帽al de entrada y una se帽al de salida:

Figure made with TikZ

No se pueden introducir dos se帽ales diferentes en un solo filtro sin sumarlas primero o realizar alguna otra operaci贸n. Del mismo modo, la salida siempre ser谩 una se帽al, es decir, una matriz 1D de n煤meros.

Hay cuatro tipos b谩sicos de filtros: paso bajo, paso alto, paso banda y supresi贸n de banda. Cada tipo modifica las se帽ales para centrarse en diferentes rangos de frecuencias dentro de ellas. Los gr谩ficos a continuaci贸n demuestran c贸mo se filtran las frecuencias en las se帽ales para cada tipo, present谩ndose primero solo con frecuencias positivas (m谩s f谩ciles de entender) y luego incluyendo tambi茅n las negativas.

Filter types, including low-pass, high-pass, band-pass, and band-stop filtering in the frequency domain

Figure made with TikZ

Figure made with TikZ

Figure made with TikZ

Figure made with TikZ

Cada filtro permite que ciertas frecuencias permanezcan en una se帽al mientras bloquea otras frecuencias. El rango de frecuencias que deja pasar un filtro se conoce como 鈥渂anda de paso鈥 y 鈥渂anda de parada鈥 se refiere a lo que est谩 bloqueado. En el caso del filtro de paso bajo, deja pasar las frecuencias bajas y detiene las altas, por lo que 0 Hz siempre estar谩 en la banda de paso. Para un filtro de paso alto y de paso de banda, 0 Hz siempre estar谩 en la banda de parada.

No confunda estos tipos de filtrado con la implementaci贸n algor铆tmica de filtrado (por ejemplo, IIR vs FIR). El tipo m谩s com煤n, con diferencia, es el filtro de paso bajo (LPF), porque a menudo representamos se帽ales en banda base. LPF nos permite filtrar todo lo que est谩 鈥渁lrededor鈥 de nuestra se帽al, eliminando el exceso de ruido y otras se帽ales.

Representaci贸n del Filtro

Para la mayor铆a de los filtros que veremos (conocidos como filtros de tipo FIR, o respuesta de impulso finito), podemos representar el filtro en s铆 con una 煤nica matriz con datos tipo float. Para filtros sim茅tricos en el dominio de la frecuencia, estos datos float ser谩n reales (en lugar de complejos) y tiende a haber un n煤mero impar de ellos. A este conjunto de float lo llamamos 鈥淔ilter Taps鈥. A menudo utilizamos h como s铆mbolo para los filter taps. A continuaci贸n se muestra un ejemplo de un conjunto de filter taps, que definen un filtro:

h =  [ 9.92977939e-04  1.08410297e-03  8.51595307e-04  1.64604862e-04
 -1.01714338e-03 -2.46268845e-03 -3.58236429e-03 -3.55412543e-03
 -1.68583512e-03  2.10562324e-03  6.93100252e-03  1.09302641e-02
  1.17766532e-02  7.60955496e-03 -1.90555639e-03 -1.48306750e-02
 -2.69313236e-02 -3.25659606e-02 -2.63400086e-02 -5.04184562e-03
  3.08099470e-02  7.64264738e-02  1.23536693e-01  1.62377258e-01
  1.84320776e-01  1.84320776e-01  1.62377258e-01  1.23536693e-01
  7.64264738e-02  3.08099470e-02 -5.04184562e-03 -2.63400086e-02
 -3.25659606e-02 -2.69313236e-02 -1.48306750e-02 -1.90555639e-03
  7.60955496e-03  1.17766532e-02  1.09302641e-02  6.93100252e-03
  2.10562324e-03 -1.68583512e-03 -3.55412543e-03 -3.58236429e-03
 -2.46268845e-03 -1.01714338e-03  1.64604862e-04  8.51595307e-04
  1.08410297e-03  9.92977939e-04]

Ejemplo de caso de uso

Para aprender c贸mo se usan los filtros, veamos un ejemplo en el que sintonizamos nuestro SDR a la frecuencia de una se帽al existente que queremos aislarlo de otras se帽ales. Recuerde que le decimos a nuestro SDR qu茅 frecuencia sintonizar, pero las muestras que captura el SDR est谩n en banda base, lo que significa que la se帽al se mostrar谩 centrada alrededor de 0 Hz. Tendremos que realizar un seguimiento de qu茅 frecuencia le indicamos al SDR que sintonice. Esto es lo que podr铆amos recibir:

GNU Radio frequency domain plot of signal of interest and an interfering signal and noise floor

Como nuestra se帽al ya est谩 centrada en DC (0 Hz), sabemos que queremos un filtro paso bajo. Debemos elegir una 鈥渇recuencia de corte鈥 (tambi茅n conocida como frecuencia de esquina), que determinar谩 cu谩ndo la banda de paso pasa a banda de parada. La frecuencia de corte siempre estar谩 en unidades de Hz. En este ejemplo, 3 kHz parece un buen valor:

../_images/filter_use_case2.png

Sin embargo, tal como funcionan la mayor铆a de los filtros paso bajo, el l铆mite de frecuencia negativo tambi茅n ser谩 -3 kHz. Es decir, es sim茅trico alrededor de DC (m谩s adelante ver谩s por qu茅). Nuestras frecuencias de corte se ver谩n as铆 (la banda de paso es el 谩rea intermedia):

../_images/filter_use_case3.png

Despu茅s de crear y aplicar el filtro con una frecuencia de corte de 3 kHz, ahora tenemos:

GNU Radio frequency domain plot of signal of interest and an interfering signal and noise floor, with interference filtered out

Esta se帽al filtrada parecer谩 confusa hasta que recuerdes que nuestro nivel de ruido estaba en la l铆nea verde alrededor de -65 dB. Aunque todav铆a podemos ver la se帽al de interferencia centrada en 10 kHz, hemos disminuido severamente la potencia de esa se帽al. 隆Ahora est谩 debajo de donde estaba el piso de ruido! Tambi茅n eliminamos la mayor parte del ruido que exist铆a en la banda de parada.

Adem谩s de la frecuencia de corte, el otro par谩metro principal de nuestro filtro de paso bajo se llama 鈥渁ncho de transici贸n鈥. El ancho de transici贸n, tambi茅n medido en Hz, indica al filtro qu茅 tan r谩pido debe pasar entre la banda de paso y la banda de parada, ya que una transici贸n instant谩nea es imposible.

Visualicemos el ancho de la transici贸n. En el siguiente diagrama, la l铆nea verde representa la respuesta ideal para la transici贸n entre una banda de paso y una banda de parada, que esencialmente tiene un ancho de transici贸n de cero. La l铆nea Rojo muestra el resultado de un filtro realista, que tiene cierta ondulaci贸n y un cierto ancho de transici贸n.

Frequency response of a low-pass filter, showing ripple and transition width

Quiz谩s se pregunte por qu茅 no establecemos el ancho de transici贸n lo m谩s peque帽o posible. La raz贸n es principalmente que un ancho de transici贸n m谩s peque帽o da como resultado m谩s taps, y m谩s taps significa m谩s c谩lculos; veremos por qu茅 en breve. Un filtro de 50 taps puede funcionar durante todo el d铆a utilizando el 1% de la CPU en una Raspberry Pi. Mientras tanto, 隆un filtro de 50.000 taps har谩 que tu CPU explote! Normalmente utilizamos una herramienta de dise帽o de filtros, luego vemos cu谩ntas pulsaciones genera y, si son demasiadas (por ejemplo, m谩s de 100), aumentamos el ancho de la transici贸n. Por supuesto, todo depende de la aplicaci贸n y del hardware que ejecuta el filtro.

En el ejemplo de filtrado anterior, utilizamos un l铆mite de 3 kHz y un ancho de transici贸n de 1 kHz (es dif铆cil ver el ancho de transici贸n con solo mirar estas capturas de pantalla). El filtro resultante ten铆a 77 taps.

Volvamos a la representaci贸n del filtro. Aunque podemos mostrar la lista de taps para un filtro, normalmente representamos los filtros visualmente en el dominio de la frecuencia. A esto lo llamamos 鈥渞espuesta de frecuencia鈥 del filtro y nos muestra el comportamiento del filtro en frecuencia. Aqu铆 est谩 la respuesta de frecuencia del filtro que est谩bamos usando:

../_images/filter_use_case5.png

Tenga en cuenta que lo que estoy mostrando aqu铆 no es una se帽al, es solo la representaci贸n del dominio de frecuencia del filtro. Esto puede ser un poco dif铆cil de entender al principio, pero a medida que miramos los ejemplos y el c贸digo, encajar谩.

Un filtro determinado tambi茅n tiene una representaci贸n en el dominio del tiempo; se llama 鈥渞espuesta al impulso鈥 del filtro porque es lo que ves en el dominio del tiempo si tomas un impulso y lo pasas por el filtro. (Google 鈥淔unci贸n delta de Dirac鈥 para obtener m谩s informaci贸n sobre qu茅 es un impulso). Para un filtro tipo FIR, la respuesta al impulso es simplemente los propios taps. Para ese filtro de 77 taps que usamos antes, los taps son:

h =  [-0.00025604525581002235, 0.00013669139298144728, 0.0005385575350373983,
0.0008378280326724052, 0.000906112720258534, 0.0006353431381285191,
-9.884083502996931e-19, -0.0008822851814329624, -0.0017323142383247614,
-0.0021665366366505623, -0.0018335371278226376, -0.0005912294145673513,
0.001349081052467227, 0.0033936649560928345, 0.004703888203948736,
0.004488115198910236, 0.0023609865456819534, -0.0013707970501855016,
-0.00564080523326993, -0.008859002031385899, -0.009428252466022968,
-0.006394983734935522, 4.76480351940553e-18, 0.008114570751786232,
0.015200719237327576, 0.018197273835539818, 0.01482443418353796,
0.004636279307305813, -0.010356673039495945, -0.025791890919208527,
-0.03587324544787407, -0.034922562539577484, -0.019146423786878586,
0.011919975280761719, 0.05478153005242348, 0.10243935883045197,
0.1458890736103058, 0.1762896478176117, 0.18720689415931702,
0.1762896478176117, 0.1458890736103058, 0.10243935883045197,
0.05478153005242348, 0.011919975280761719, -0.019146423786878586,
-0.034922562539577484, -0.03587324544787407, -0.025791890919208527,
-0.010356673039495945, 0.004636279307305813, 0.01482443418353796,
0.018197273835539818, 0.015200719237327576, 0.008114570751786232,
4.76480351940553e-18, -0.006394983734935522, -0.009428252466022968,
-0.008859002031385899, -0.00564080523326993, -0.0013707970501855016,
0.0023609865456819534, 0.004488115198910236, 0.004703888203948736,
0.0033936649560928345, 0.001349081052467227, -0.0005912294145673513,
-0.0018335371278226376, -0.0021665366366505623, -0.0017323142383247614,
-0.0008822851814329624, -9.884083502996931e-19, 0.0006353431381285191,
0.000906112720258534, 0.0008378280326724052, 0.0005385575350373983,
0.00013669139298144728, -0.00025604525581002235]

Y aunque todav铆a no hemos entrado en el dise帽o del filtro, aqu铆 est谩 el c贸digo Python que gener贸 ese filtro:

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

num_taps = 51 # it helps to use an odd number of taps
cut_off = 3000 # Hz
sample_rate = 32000 # Hz

# create our low pass filter
h = signal.firwin(num_taps, cut_off, nyq=sample_rate/2)

# plot the impulse response
plt.plot(h, '.-')
plt.show()

Simplemente trazar esta serie de floats nos da la respuesta al impulso del filtro:

Example of impulse response of a filter, plotting the taps in the time domain

Y aqu铆 est谩 el c贸digo que se us贸 para producir la respuesta de frecuencia, mostrado anteriormente. Es un poco m谩s complicado porque tenemos que crear el conjunto de frecuencias del eje x.

# plot the frequency response
H = np.abs(np.fft.fft(h, 1024)) # take the 1024-point FFT and magnitude
H = np.fft.fftshift(H) # make 0 Hz in the center
w = np.linspace(-sample_rate/2, sample_rate/2, len(H)) # x axis
plt.plot(w, H, '.-')
plt.show()

Filtros Reales vs. Complejos

El filtro que les mostr茅 ten铆a taps reales, pero los taps tambi茅n pueden ser complejos. Si los taps son reales o complejas, no tiene por qu茅 coincidir con la se帽al de entrada, es decir, puede pasar una se帽al compleja a trav茅s de un filtro con taps reales y viceversa. Cuando los taps son reales, la respuesta de frecuencia del filtro ser谩 sim茅trica alrededor de DC (0 Hz). Normalmente utilizamos taps complejos cuando necesitamos asimetr铆a, lo que no ocurre con demasiada frecuencia.

Figure made with TikZ

Como ejemplo de taps complejas, volvamos al caso de uso del filtrado, excepto que esta vez queremos recibir la otra se帽al de interferencia (sin tener que volver a sintonizar la radio). Eso significa que queremos un filtro de paso de banda, pero no sim茅trico. Solo queremos mantener (tambi茅n conocidas como 鈥減ass鈥) frecuencias entre 7 kHz y 13 kHz (no queremos pasar tambi茅n de -13 kHz a -7 kHz)

../_images/filter_use_case6.png

Una forma de dise帽ar este tipo de filtro es crear un filtro paso bajo con un corte de 3 kHz y luego cambiarlo de frecuencia. Recuerde que podemos desplazar la frecuencia x(t) (dominio del tiempo) multiplic谩ndola por e^{j2\pi f_0t}. En este caso f_0 deber铆a ser 10 kHz, lo que eleva nuestro filtro 10 kHz. Recuerde que en nuestro c贸digo Python de arriba, h eran los taps del filtro del filtro paso bajo. Para crear nuestro filtro paso banda solo tenemos que multiplicar esos taps por e^{j2\pi f_0t}, aunque implicar铆a crear un vector para representar el tiempo en funci贸n de nuestro per铆odo de muestreo (inverso de la frecuencia de muestreo):

# (h was found using the first code snippet)

# Shift the filter in frequency by multiplying by exp(j*2*pi*f0*t)
f0 = 10e3 # amount we will shift
Ts = 1.0/sample_rate # sample period
t = np.arange(0.0, Ts*len(h), Ts) # time vector. args are (start, stop, step)
exponential = np.exp(2j*np.pi*f0*t) # this is essentially a complex sine wave

h_band_pass = h * exponential # do the shift

# plot impulse response
plt.figure('impulse')
plt.plot(np.real(h_band_pass), '.-')
plt.plot(np.imag(h_band_pass), '.-')
plt.legend(['real', 'imag'], loc=1)

# plot the frequency response
H = np.abs(np.fft.fft(h_band_pass, 1024)) # take the 1024-point FFT and magnitude
H = np.fft.fftshift(H) # make 0 Hz in the center
w = np.linspace(-sample_rate/2, sample_rate/2, len(H)) # x axis
plt.figure('freq')
plt.plot(w, H, '.-')
plt.xlabel('Frequency [Hz]')
plt.show()

Los gr谩ficos de la respuesta al impulso y la respuesta en frecuencia se muestran a continuaci贸n:

../_images/shifted_filter.png

Debido a que nuestro filtro no es sim茅trico alrededor de 0 Hz, tiene que utilizar taps complejos. Por lo tanto, necesitamos dos l铆neas para trazar esos taps complejos. Lo que vemos en el gr谩fico de la izquierda de arriba sigue siendo la respuesta al impulso. Nuestro gr谩fico de respuesta de frecuencia es lo que realmente valida que creamos el tipo de filtro que esper谩bamos, donde filtrar谩 todo excepto la se帽al centrada alrededor de 10 kHz. Una vez m谩s, recuerde que el gr谩fico anterior no es una se帽al real: es solo una representaci贸n del filtro. Puede ser muy confuso de entender porque cuando aplicas el filtro a la se帽al y trazas la salida en el dominio de la frecuencia, en muchos casos se ver谩 m谩s o menos igual que la respuesta de frecuencia del filtro.

Si esta subsecci贸n aument贸 la confusi贸n, no se preocupe, el 99% de las veces tendr谩 que lidiar con filtros paso bajo simples con taps reales de todos modos.

Implementaci贸n de Filtros

No vamos a profundizar demasiado en la implementaci贸n de filtros. M谩s bien, me concentro en el dise帽o de filtros (de todos modos, puede encontrar implementaciones listas para usar en cualquier lenguaje de programaci贸n). Por ahora, aqu铆 hay una conclusi贸n: para filtrar una se帽al con un filtro FIR, simplemente convoluciona la respuesta al impulso (el conjunto de taps) con la se帽al de entrada. (No se preocupe, una secci贸n posterior explica la convoluci贸n). En el mundo discreto usamos una convoluci贸n discreta (ejemplo a continuaci贸n). Los tri谩ngulos etiquetados como b son los taps. En el diagrama de flujo, los cuadrados etiquetados z^{-1} encima de los tri谩ngulos significan un retraso de un paso de tiempo.

Implementation of a finite impulse response (FIR) filter with delays and taps and summations

Es posible que pueda ver por qu茅 ahora los llamamos 鈥渢aps鈥 del filtro, seg煤n la forma en que se implementa el filtro.

FIR vs IIR

Hay dos clases principales de filtros digitales: FIR y IIR.

  1. Finite impulse response (FIR)

  2. Infinite impulse response (IIR)

No profundizaremos demasiado en la teor铆a, pero por ahora recuerde: los filtros FIR son m谩s f谩ciles de dise帽ar y pueden hacer lo que quiera si usa suficientes taps. Los filtros IIR son m谩s complicados y pueden ser inestables, pero son m谩s eficientes (utilizan menos CPU y memoria para el filtro determinado). Si alguien simplemente le da una lista de taps, se supone que son taps para un filtro FIR. Si empiezan a hablar de 鈥減olos鈥, est谩n hablando de filtros IIR. Nos quedaremos con los filtros FIR en este libro de texto.

A continuaci贸n se muestra un ejemplo de respuesta de frecuencia, comparando un filtro FIR e IIR que realizan casi exactamente el mismo filtrado; tienen un ancho de transici贸n similar, que, como aprendimos, determinar谩 cu谩ntos taps se requieren. El filtro FIR tiene 50 taps y el filtro IIR tiene 12 polos, lo que es como tener 12 taps en t茅rminos de c谩lculos necesarios.

Comparing finite impulse response (FIR) and infinite impulse response (IIR) filters by observing frequency response

La lecci贸n es que el filtro FIR requiere muchos m谩s recursos computacionales que el IIR para realizar aproximadamente la misma operaci贸n de filtrado.

A continuaci贸n se muestran algunos ejemplos del mundo real de filtros FIR e IIR que quiz谩s haya utilizado antes.

Si realiza una 鈥渕edia m贸vil鈥 en una lista de n煤meros, eso es solo un filtro FIR con taps de unos: - h = [1 1 1 1 1 1 1 1 1 1] para un filtro de media m贸vil con un tama帽o de ventana de 10. Tambi茅n resulta ser un filtro de tipo paso bajo; 驴porqu茅 es eso? 驴Cu谩l es la diferencia entre usar 1 y usar grifos que decaen a cero?

Answers

Un filtro de media m贸vil es un filtro paso bajo porque suaviza los cambios de 鈥渁lta frecuencia鈥, raz贸n por la cual la gente lo suele utilizar. La raz贸n para usar taps que decaen a cero en ambos extremos es para evitar un cambio repentino en la salida, como si la se帽al que se filtra fuera cero por un tiempo y luego de repente saltara.

Ahora veamos un ejemplo de IIR. 驴Alguno de ustedes ha hecho esto alguna vez?

x = x*0.99 + new_value*0.01

donde 0,99 y 0,01 representan la velocidad con la que se actualiza el valor (o la tasa de ca铆da, lo mismo). Es una forma conveniente de actualizar lentamente alguna variable sin tener que recordar los 煤ltimos valores. En realidad, se trata de una forma de filtro IIR de paso bajo. Con suerte, podr谩 ver por qu茅 los filtros IIR tienen menos estabilidad que los FIR. 隆Los valores nunca desaparecen por completo!

Herramientas de dise帽o de filtros

En la pr谩ctica, la mayor铆a de la gente utilizar谩 una herramienta de dise帽o de filtros o una funci贸n en el c贸digo que dise帽e el filtro. Hay muchas herramientas diferentes, pero a los estudiantes les recomiendo esta aplicaci贸n web f谩cil de usar de Peter Isza que les mostrar谩 la respuesta de impulso y frecuencia: http://t-filter.engineerjs.com. Usando los valores predeterminados, al menos al momento de escribir esto, est谩 configurado para dise帽ar un filtro paso bajo con una banda de paso de 0 a 400 Hz y una banda de parada de 500 Hz en adelante. La frecuencia de muestreo es de 2 kHz, por lo que la frecuencia m谩xima que podemos 鈥渧er鈥 es 1 kHz.

../_images/filter_designer1.png

Haga clic en el bot贸n 鈥淔iltro de dise帽o鈥 para crear los taps y trazar la respuesta de frecuencia.

../_images/filter_designer2.png

Haga clic en el texto 鈥淩espuesta al impulso鈥 encima del gr谩fico para ver la respuesta al impulso, que es un gr谩fico de los taps, ya que se trata de un filtro FIR.

../_images/filter_designer3.png

Esta aplicaci贸n incluso incluye el c贸digo fuente C++ para implementar y utilizar este filtro. La aplicaci贸n web no incluye ninguna forma de dise帽ar filtros IIR, que en general son mucho m谩s dif铆ciles de dise帽ar.

Convoluci贸n

Nos desviaremos brevemente para presentar el operador de convoluci贸n. No dudes en saltarte esta secci贸n si ya est谩s familiarizado con ella.

Sumar dos se帽ales es una forma de combinar dos se帽ales en una. En el capitulo Dominio de la Frecuencia exploramos c贸mo se aplica la propiedad de linealidad al sumar dos se帽ales. La convoluci贸n es otra forma de combinar dos se帽ales en una, pero es muy diferente a simplemente sumarlas. La convoluci贸n de dos se帽ales es como deslizar una sobre la otra e integrarla. Es muy similar a una correlaci贸n cruzada, si est谩 familiarizado con esa operaci贸n. De hecho, en muchos casos equivale a una correlaci贸n cruzada. Normalmente utilizamos el s铆mbolo ::code::* para referirse a una convoluci贸n, especialmente en ecuaciones matem谩ticas.

Creo que la operaci贸n de convoluci贸n se aprende mejor a trav茅s de ejemplos. En este primer ejemplo, convolucionamos dos pulsos cuadrados juntos:

../_images/rect_rect_conv.gif

Tenemos dos se帽ales de entrada (una roja y otra azul) y luego la salida de la convoluci贸n se muestra en negro. Puede ver que la salida es la integraci贸n de las dos se帽ales cuando una se desliza sobre la otra. Debido a que es solo una integraci贸n deslizante, el resultado es un tri谩ngulo con un m谩ximo en el punto donde ambos pulsos cuadrados se alinearon perfectamente.

Veamos algunas convoluciones m谩s:

../_images/rect_fat_rect_conv.gif

../_images/rect_exp_conv.gif

../_images/gaussian_gaussian_conv.gif

Observe c贸mo una gaussiana convolucionada con otra gaussiana es otra gaussiana, pero con un pulso m谩s amplio y una amplitud menor.

Debido a esta naturaleza 鈥渄eslizante鈥, la longitud de la salida es en realidad m谩s larga que la de la entrada. Si una se帽al tiene M muestras y la otra se帽al es N muestras, La convoluci贸n de los dos puede producir N+M-1 muestras. Sin embargo, funciones como numpy.convolve() tiene una manera de especificar si desea la salida completa (max(M, N) muestras) o simplemente las muestras donde las se帽ales se superpusieron completamente (max(M, N) - min(M, N) + 1 si eres curioso). No hay necesidad de quedar atrapado en este detalle. Solo sepa que la longitud de la salida de una convoluci贸n no es solo la longitud de las entradas.

Entonces, 驴por qu茅 es importante la convoluci贸n en DSP? Bueno, para empezar, para filtrar una se帽al, simplemente podemos tomar la respuesta al impulso de ese filtro y convolucionarla con la se帽al. El filtrado FIR es simplemente una operaci贸n de convoluci贸n.

../_images/filter_convolve.png

Puede resultar confuso porque antes mencionamos que la convoluci贸n recibe dos se帽ales y genera una. Podemos tratar la respuesta al impulso como una se帽al y, despu茅s de todo, la convoluci贸n es un operador matem谩tico que opera en dos matrices 1D. Si una de esas matrices 1D es la respuesta de impulso del filtro, la otra matriz 1D puede ser una parte de la se帽al de entrada y la salida ser谩 una versi贸n filtrada de la entrada.

Veamos otro ejemplo para ayudar a este clic. En el siguiente ejemplo, el tri谩ngulo representar谩 la respuesta al impulso de nuestro filtro, y la se帽al en verde es nuestra se帽al que est谩 siendo filtrada.

../_images/convolution.gif

La salida en rojo es la se帽al filtrada.

Pregunta: 驴Qu茅 tipo de filtro era el tri谩ngulo?

Answers

Suaviz贸 los componentes de alta frecuencia de la se帽al verde (es decir, las transiciones bruscas del cuadrado) para que act煤e como un filtro de paso bajo.

Ahora que estamos empezando a comprender la convoluci贸n, presentar茅 la ecuaci贸n matem谩tica. El asterisco (*) se utiliza normalmente como s铆mbolo de convoluci贸n:

(f * g)(t) = \int f(\tau) g(t - \tau) d\tau

En la siguiente expresi贸n, g(t) es la se帽al o la entrada que se refleja sobre y y se desliza a lo largo de x f(t), pero g(t) y f(t) se puede intercambiar y sigue siendo la misma expresi贸n. Normalmente, la matriz m谩s corta se utilizar谩 como g(t). La convoluci贸n es igual a una correlaci贸n cruzada, definida como \int f(\tau) g(t+\tau), cuando g(t) es sim茅trica, es decir, no cambia cuando se le da la vuelta sobre el origen.

Dise帽o de filtros en Python

Ahora consideraremos una forma de dise帽ar nosotros mismos un filtro FIR en Python. Si bien existen muchos enfoques para dise帽ar filtros, usaremos el m茅todo de comenzar en el dominio de la frecuencia y trabajar hacia atr谩s para encontrar la respuesta al impulso. En 煤ltima instancia, as铆 es como se representa nuestro filtro (por sus taps).

Empiece por crear un vector de la respuesta de frecuencia deseada. Dise帽emos un filtro de paso bajo de forma arbitraria que se muestra a continuaci贸n:

../_images/filter_design1.png

El c贸digo utilizado para crear este filtro es bastante simple:

import numpy as np
import matplotlib.pyplot as plt
H = np.hstack((np.zeros(20), np.arange(10)/10, np.zeros(20)))
w = np.linspace(-0.5, 0.5, 50)
plt.plot(w, H, '.-')
plt.show()

hstack() es una forma de concatenar matrices en numpy. Sabemos que conducir谩 a un filtro con taps complejos. 驴Por qu茅?

Answer

No es sim茅trico alrededor de 0 Hz.

Nuestro objetivo final es encontrar los taps de este filtro para que podamos usarlo. 驴C贸mo obtenemos los taps, dada la respuesta de frecuencia? Bueno, 驴c贸mo convertimos del dominio de la frecuencia al dominio del tiempo? 隆FFT inversa (IFFT)! Recuerde que la funci贸n IFFT es casi exactamente igual que la funci贸n FFT. Tambi茅n necesitamos cambiar IFFT nuestra respuesta de frecuencia deseada antes de IFFT, y luego necesitamos otro cambio IFF despu茅s de IFFT (no, no se cancelan solos, puedes intentarlo). Este proceso puede parecer confuso. S贸lo recuerda que siempre debes tener la FFTshift despu茅s de una FFT y IFFshift despu茅s de una IFFT.

h = np.fft.ifftshift(np.fft.ifft(np.fft.ifftshift(H)))
plt.plot(np.real(h))
plt.plot(np.imag(h))
plt.legend(['real','imag'], loc=1)
plt.show()
../_images/filter_design2.png

Usaremos estos taps que se muestran arriba como nuestro filtro. Sabemos que la respuesta al impulso est谩 trazando los taps, por lo que lo que vemos arriba es nuestra respuesta al impulso. Tomemos la FFT de nuestros taps para ver c贸mo se ve realmente el dominio de la frecuencia. Haremos una FFT de 1.024 puntos para conseguir una alta resoluci贸n:

H_fft = np.fft.fftshift(np.abs(np.fft.fft(h, 1024)))
plt.plot(H_fft)
plt.show()
../_images/filter_design3.png

Vea c贸mo la respuesta de frecuencia no es muy recta鈥 no coincide muy bien con nuestro original, si recuerda la forma para la que inicialmente quer铆amos hacer un filtro. Una raz贸n importante es que nuestra respuesta al impulso no ha terminado de decaer, es decir, los lados izquierdo y derecho no llegan a cero. Tenemos dos opciones que le permitir谩n decaer a cero:

Opci贸n 1: Creamos una ventana en nuestra respuesta de impulso actual para que descienda a 0 en ambos lados. Implica multiplicar nuestra respuesta al impulso con una 鈥渇unci贸n de ventana鈥 que comienza y termina en cero.

# After creating h using the previous code, create and apply the window
window = np.hamming(len(h))
h = h * window
../_images/filter_design4.png

Opci贸n 2: Regeneramos nuestra respuesta impulso usando m谩s puntos para que tenga tiempo de decaer. Necesitamos agregar resoluci贸n a nuestra matriz de dominio de frecuencia original (lo que se llama interpolaci贸n).

H = np.hstack((np.zeros(200), np.arange(100)/100, np.zeros(200)))
w = np.linspace(-0.5, 0.5, 500)
plt.plot(w, H, '.-')
plt.show()
# (the rest of the code is the same)
../_images/filter_design5.png ../_images/filter_design6.png ../_images/filter_design7.png

Ambas opciones funcionaron. 驴Cu谩l elegir铆as? El segundo m茅todo result贸 en m谩s pulsaciones, pero el primer m茅todo result贸 en una respuesta de frecuencia que no era muy n铆tida y ten铆a un flanco descendente que no era muy pronunciado. Existen numerosas formas de dise帽ar un filtro, cada una con sus propias compensaciones a lo largo del camino. Muchos consideran que el dise帽o de filtros es un arte.

Introducci贸n al formador de pulsos

Introduciremos brevemente un tema muy interesante dentro del DSP, el modelado de pulsos. Consideraremos el tema en profundidad en su propio cap铆tulo m谩s adelante, ver Formador de Pulso. Vale la pena mencionarlo junto con el filtrado porque la conformaci贸n de pulsos es, en 煤ltima instancia, un tipo de filtro, utilizado para un prop贸sito espec铆fico, con propiedades especiales.

Como aprendimos, las se帽ales digitales utilizan s铆mbolos para representar uno o m谩s bits de informaci贸n. Utilizamos un esquema de modulaci贸n digital como ASK, PSK, QAM, FSK, etc., para modular una portadora de modo que la informaci贸n pueda enviarse de forma inal谩mbrica. Cuando simulamos QPSK en el cap铆tulo Modulaci贸n Digital, solo simulamos una muestra por s铆mbolo, es decir, cada n煤mero complejo que creamos era uno de los puntos de la constelaci贸n: era un s铆mbolo. En la pr谩ctica, normalmente generamos varias muestras por s铆mbolo y el motivo tiene que ver con el filtrado.

Usamos filtros para crear la 鈥渇orma鈥 de nuestros s铆mbolos porque la forma en el dominio del tiempo cambia la forma en el dominio de la frecuencia. El dominio de la frecuencia nos informa cu谩nto espectro/ancho de banda utilizar谩 nuestra se帽al y, por lo general, queremos minimizarlo. Lo que es importante entender es que las caracter铆sticas espectrales (dominio de frecuencia) de los s铆mbolos de banda base no cambian cuando modulamos una portadora; simplemente aumenta la frecuencia de la banda base mientras la forma permanece igual, lo que significa que la cantidad de ancho de banda que utiliza permanece igual. Cuando usamos 1 muestra por s铆mbolo, es como transmitir pulsos cuadrados. De hecho, BPSK que usa 1 muestra por s铆mbolo es solo una onda cuadrada de 1鈥檚 y -1鈥檚 aleatorios:

../_images/bpsk.svg

Y como hemos aprendido, los pulsos cuadrados no son eficientes porque utilizan una cantidad excesiva de espectro:

../_images/square-wave.svg

Entonces, lo que hacemos es 鈥渄ar forma a pulsos鈥 a estos s铆mbolos que parecen bloques para que ocupen menos ancho de banda en el dominio de la frecuencia. La 鈥渇orma del pulso鈥 se logra mediante el uso de un filtro de paso bajo porque descarta los componentes de frecuencia m谩s alta de nuestros s铆mbolos. A continuaci贸n se muestra un ejemplo de s铆mbolos en el dominio del tiempo (arriba) y de la frecuencia (abajo), antes y despu茅s de que se haya aplicado un filtro de conformaci贸n de pulsos:

../_images/pulse_shaping.png

Demonstration of pulse shaping of an RF signal to reduce occupied bandwidth

Observe cu谩nto m谩s r谩pido cae la frecuencia de la se帽al. Los l贸bulos laterales son ~30 dB m谩s bajos despu茅s de la configuraci贸n del pulso; 隆Eso es 1000 veces menos! Y lo que es m谩s importante, el l贸bulo principal es m谩s estrecho, por lo que se utiliza menos espectro para la misma cantidad de bits por segundo.

Por ahora, tenga en cuenta que los filtros de formaci贸n de pulso m谩s comunes incluyen:

  1. Raised-cosine filter

  2. Root raised-cosine filter

  3. Sinc filter

  4. Gaussian filter

Estos filtros generalmente tienen un par谩metro que puede ajustar para disminuir el ancho de banda utilizado. A continuaci贸n se muestra el dominio de tiempo y frecuencia de un filtro de coseno elevado con diferentes valores de \beta, el par谩metro que define qu茅 tan pronunciada es la ca铆da.

../_images/pulse_shaping_rolloff.png

Puede ver que un valor m谩s bajo de \beta reduce el espectro utilizado (para la misma cantidad de datos). Sin embargo, si el valor es demasiado bajo, los s铆mbolos en el dominio del tiempo tardar谩n m谩s en decaer hasta cero. En realidad, cuando \beta=0 los s铆mbolos nunca decaen completamente a cero, lo que significa que no podemos transmitir dichos s铆mbolos en la pr谩ctica. Un valor \beta de alrededor de 0,35 es com煤n.

Aprender谩 mucho m谩s sobre la formaci贸n de pulsos, incluidas algunas propiedades especiales que deben satisfacer los filtros formadores de pulsos, en el capitulo Formador de Pulso .