Est-il correct de soustraire un signal filtré passe-bas du signal d'origine et d'utiliser le résultat comme un «passe-haut»?

8

J'ai du mal à trouver de la documentation pour implémenter un filtre passe-bande ou passe-haut avec python / scipy / numpy.

Je peux facilement créer et appliquer un filtre passe-bas, donc je demande:

Serait-il conceptuellement correct de filtrer passe-bas un signal, puis de soustraire le résultat du signal d'origine, afin d'obtenir uniquement les hautes fréquences?

De plus, si quelqu'un a un exemple simple d'un filtre passe-bande naïf en Python (utilisant de préférence les bibliothèques numpy et scipy), je serais très reconnaissant.

Ce que je recherche, c'est quelque chose comme:

filtered_signal = band_pass(original_signal, rate, low=20, high=500)

Merci pour toute aide!

EDIT: avec scipy, je l'utilise comme passe-bas, avec de bons résultats:

import numpy, scipy.signal

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)
    ## second pass to compensate phase delay
    secondpass = scipy.signal.lfilter(b, a, firstpass[::-1])[::-1]
    return secondpass
heltonbiker
la source
La documentation de scipy.signal.firwinexplique comment créer des filtres passe-bas, passe-haut, passe-bande, coupe-bande et multi-bandes. As-tu essayé firwin(taps, cutoff=nfreq, pass_zero=False)?
endolith
Voir sound.whsites.net/articles/derived-xovers.htm pour l'utilisation de cette technique dans les haut
endolith

Réponses:

7

En théorie, vous pouvez le faire, mais en pratique, c'est difficile à faire car l'alignement de temps et de phase doit être assez bon pour que cela fonctionne. Si l'alignement est bon, vous obtiendrez l' interférence destructrice que vous recherchez. S'ils ne le sont pas, vous obtiendrez une interférence constructive. Pire encore, qu'elles interfèrent de manière destructrice ou constructive, cela dépendra de la fréquence, c'est-à-dire que vous pouvez obtenir à la fois des interférences constructives et destructives. Cela peut fonctionner, cependant, si vous ne filtrez que des fréquences assez basses, car leurs exigences de synchronisation sont les plus lâches car elles changent si lentement.

Petite histoire - il est possible de le faire mais est suffisamment difficile pour qu'il soit généralement logique de simplement faire un filtre passe-haut.

Un moyen relativement simple de créer un filtre passe-bande consiste à créer un filtre passe-bas, puis à le moduler à la fréquence centrale souhaitée en le multipliant par une sinusoïde de cette fréquence.

Jim Clay
la source
J'ai tendance à passer deux fois le filtre, l'un en sens inverse, pour compenser le déphasage.
heltonbiker
@heltonbiker Ensuite, vous devriez être en mesure de le faire de cette manière, à condition que le timing soit aligné correctement et que le gain du filtre passe-bas soit de 1.
Jim Clay
4

Vous pouvez concevoir les différents types de filtres directement avec les fonctions scipy.signal. Il existe trois fonctions principales pour créer des filtres à réponse impulsionnelle finie avec le package scipy.signal.

  1. signal.remez
  2. signal.firwin
  3. signal.firwin2

La fonction remez , comme arguments, prend le nombre de taps (ordre + 1), les "bandes" et le gain "souhaité". Les "bandes" sont en Hz. Cette fonction est un peu étrange que le paramètre "Hz" définit la fréquence d'échantillonnage en Hz. Un exemple serait:

from scipy import signal
b = signal.remez(64, [0, 80, 100, 200, 220, 500], [0, 1, 0], Hz=1000)
plot(20*log10(abs(fft.fft(b, 4096).)))

Fréquence de réponse

Remarque: J'ai triché un peu et utilisé une FFT d'ordre supérieur pour rendre l'intrigue un peu plus agréable (interpolé les points pour la visualisation uniquement).

Exemples passe-bas et passe-haut:

bl = signal.remez(64, [0, 248, 252, 500], [1, 0], Hz=1000) #lowpass
bh = signal.remez(64, [0, 248, 252, 500], [0, 1], Hz=1000) #highpass

La fonction firwin prend à nouveau le nombre de taps et la coupure comme arguments. La coupure peut être constituée de plusieurs valeurs sous forme de liste pour définir les filtres passe-bande et bande d'arrêt. Les unités par défaut pour la coupure sont la fréquence normalisée où la coupure nyquist est 1 et la fréquence d'échantillonnage serait 2. Cela peut être modifié en définissant / nyq /. En utilisant les exemples ci-dessus, le firwin serait appelé comme:

b = signal.firwin(64, [100, 200], pass_zero=False, nyq=500)

Le firwin2 est plus proche de la fonction remez. Mais au lieu de passer des gains pour les bandes, vous passez des gains aux seuils.

b = signal.firwin2(64, [0, 100, 200, 500], [0, 1, 1, 0], nyq=500)

Plus d'exemples disponibles ici

Christopher Felton
la source
firwinet son enveloppe buttersont ce que j'utilise maintenant. Merci!
heltonbiker
2
le beurre n'est pas un emballage pour firwin. Le beurre est une méthode de conception de filtre IIR. La fonction iirdesign est un outil de conception de filtre IIR à usage général. Où le beurre, le cheby, etc. sont des fonctions matlab'ish. Plus d'informations sur les fonctions du filtre IIR ici, bit.ly/JPS4Zs
Christopher Felton
Je suppose que j'ai mal compris ce que je faisais. Je vais le vérifier, merci (car je veux vraiment un filtre FIR).
heltonbiker
3

Vous avez indiqué que vous rencontrez des difficultés à déterminer comment concevoir un filtre passe-haut approprié. Une méthode consiste à concevoir d'abord un prototype de filtre passe-bas, puis à appliquer une transformation qui déforme la réponse du filtre en un filtre d'un autre type (tel qu'un filtre passe-haut ou passe-bande). Cela se fait en substituant une expression àz1dans la fonction de transfert du prototype de filtre passe-bas. Voici quelques liens vers des informations sur le sujet:

Plus précisément, pour une transformation passe-bas en passe-haut, vous pouvez appliquer la substitution suivante:

z1=α+z11+αz1,
α=cos(12(ωcωc))cos(12(ωc+ωc))

ωc est la fréquence de coupure du prototype de filtre passe-bas et ωcest la fréquence de coupure résultante dans le filtre passe-haut transformé. Il y a quelques exemples donnés dans la documentation MATLAB montrée dans le premier lien; des fonctions similaires peuvent être disponibles dans SciPy. Cela dit, la plupart des fonctions de conception de filtres dans cette bibliothèque suivent de près l'exemple de MATLAB, et elles sont capables de concevoir des filtres de tous les principaux types (passe-bas, passe-haut, etc.) avec très peu d'effort.

Jason R
la source
Merci pour votre attention, mais je dois admettre que je n'ai pas assez de connaissances pour digérer les informations trop techniques / mathématiques que vous avez publiées, je suis du domaine des sciences biologiques et j'attendais une réponse plus simple. Si l'effort pour créer un passe-haut est relativement faible, serait-il possible de publier un petit code de travail ou un lien vers un exemple?
heltonbiker
Quels types de filtres avez-vous utilisés? Les avez-vous conçus à l'aide d'une fonction de bibliothèque SciPy?
Jason R
Je vais modifier la question avec le passe-bas que j'utilise
heltonbiker
1
Voir le commentaire d'endolith ci-dessus sur votre question. Comme il l'a indiqué, la fonction que vous utilisez pour créer votre filtre semble également capable de concevoir des filtres passe-haut.
Jason R