IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Traitement du signal Discussion :

[Signal] Implémentation filtres Passe-Bas en C


Sujet :

Traitement du signal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 56
    Par défaut [Signal] Implémentation filtres Passe-Bas en C
    Bonjour à tous,

    Pour des besoins professionnel, je dois filtrer un signal issue de capteurs à l'aide d'un filtre passe-bas. Malheureusement, j'ai un peu de mal à mettre ça en place, malgré toutes les explications que j'ai trouvé sur le net.

    Voici en gros, mon programme. Y'a un truc que j'ai pas dû comprendre:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    // Creation des buffers
    double* hsupp = new double[L];
    double* filter = new double[L];
    double* result = new double[M];
    double* fft_signal = new double[L];
    double* fft_filter = new double[L];
    double* fft_result = new double[M];
     
    // Creation du filtre passe-bas (avec un algo trouvé sur le net)
    for (int i=-(L-1.0)/2.0; i<=(L-1.0)/2.0; i++, j++)
    	hsupp[j] = i;
    for (int i=0; i<L; i++)
    	filter[i] = (2.0*fc/Fs)*sinc(2.0*fc*hsupp[i]/Fs);
     
    // Calcul des FFT signal et filtre
    memcpy(fft_signal, x, M*sizeof(double));
    LabCore::rsrfft(fft_signal, OFFSET);
     
    memcpy(fft_filter, filter, L*sizeof(double));
    LabCore::rsrfft(fft_filter, OFFSET);
     
    // Convolution des 2 FFT (à mon avis, c'est ici qu'il y a un problème !)
    for (int i=0; i<M; i++)
    	fft_result[i] = fft_filter[i] * fft_signal[i];
     
    // Calcul de la transformé inverse
    memcpy(result, fft_result, M*sizeof(double));
    LabCore::irsrfft(result, OFFSET);
     
    // Normalisation de FFT (juste pour l'affichage)
    fft_signal = normalize(fft_signal, L);
    fft_filter = normalize(fft_filter, L);
    fft_result = normalize(fft_result, L);
    for (int i=0; i<L; i++)
    	printf("\"%.09f\";\"%.09f\";\"%.09f\";\"%.09f\";\"%.09f\";\"%.09f\"\n", x[i], hideal[i], result[i], fft_signal[i], fft_filter[i], fft_result[i]);

    Au final, j'ai un truc qui n'a rien à voir avec mon signal, et qui, en plus, est devenu symétrique par le centre (ce qui n'est pas du tout le cas de mon signal d'origine). Si on pouvait me dire là où ça cloche

    Merci beaucoup.
    Snark.

    PS: oui, le code est un peu dégueux, mais c'est juste du test...

  2. #2
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Par défaut
    Citation Envoyé par Snark Voir le message
    // Convolution des 2 FFT (à mon avis, c'est ici qu'il y a un problème !)
    Non, ça c'est bon. Le produit de convolution dans le domaine temporel se traduit en une multiplication dans le domaine fréquentiel.

    Au final, j'ai un truc qui n'a rien à voir avec mon signal, et qui, en plus, est devenu symétrique par le centre (ce qui n'est pas du tout le cas de mon signal d'origine). Si on pouvait me dire là où ça cloche
    Vu ton résultat, je dirais que tu n'as pas fait de zéro-padding (=rajouter des zéros dans tes 2 tableaux pour avoir une taille qui est une puissance de 2)
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  3. #3
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 56
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    Non, ça c'est bon. Le produit de convolution dans le domaine temporel se traduit en une multiplication dans le domaine fréquentiel.
    Ok, mais j'avais quand même un doute

    Vu ton résultat, je dirais que tu n'as pas fait de zéro-padding (=rajouter des zéros dans tes 2 tableaux pour avoir une taille qui est une puissance de 2)
    J'utilise directement des tableaux en puissances de 2, pour le moment. Histoire de pas me compliquer la vie.

    pour le zero padding je ne suis pas convaincu, la lib que tu utilises doit le gérer non ?
    Je n'utilise aucune libs externe. La FFT est directement incluse dans mon prog.

    - combien valent L et M ? il devraient être égaux logiquement
    Exacte, juste un reste d'essais

    - essaye un (vrai) filtre passe bas de ce type:
    La FFT de mon filtre et bonne, donc je ne pense pas que ça change grand chose.


    Bon, étant donnée que je ne m'en sort pas, je fourni directement mes sources, avec un peu de chances, l'un de vous pourra me débloquer... Ce doit être un truc tout con :
    http://blary.jason.free.fr/download/ffttest.tar.bz2

    C'est compilable directement sans aucune dépendances externe. Si vous être sous nux, il suffit de taper "make".
    Ça renvoie sur la sortie standard un fichier CSV. On peut l'ouvrir avec un tableur pour pouvoir tracer les courbes.

    Merci beaucoup, car, là, je sèche vraiment Et j'en ai besoin.
    Snark

  4. #4
    Membre très actif

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Par défaut
    salut

    j'ai trouvé le problème

    rajoute cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void fftconvolution(double *a, double *b, double *c, int n)
    {
        a[0] = b[0]*c[0];
        a[n/2] = b[n/2]*c[n/2];
        for (int i = 1; i < n/2; i++)
        {
            // multiplication complexe
            a[i] = b[i]*c[i] - b[n-i]*c[n-i];
            a[n-i] = b[i]*c[n-i] + b[n-i]*c[i];
        }
    }
    et dans ton main:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Convolution
    fftconvolution(fft_result,fft_signal,fft_filter,M);
    au fait ton normalize il n'a pas trop lieu d'être là, en plus il y a un dépassement de tableau dans cette fonction

  5. #5
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 56
    Par défaut
    Yop,

    Je répond un peu tard, désolé. Merci beaucoup pour ton aide.
    En effet, c'était une erreur con, j'avais oublié comment on multipliais deux complexe.

    Par contre, pour x[0], je suis d'accord pour la multiplication, car ça correspond à l'offset global du signal, mais pour x[n/2], je ne comprend pas vraiment à quoi il correspond.

    Bon, avec une convolution correct, ça fonctionne un poil mieux, mais c'est toujours étrange. Après la transformé inverse, j'ai la première moitié du signal à la fin, et la seconde moitié au début.

    Il retrouve son sens correct si je corrige la convolution comme cela (c'est pas propre du tout, je sais....) :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    void fftconvolution(double *a, double *b, double *c, int n)
    {
    	a[0] = b[0]*c[0];
    	a[n/2] = b[n/2]*c[n/2];
    	for (int i=1; i<n/2; i++)
    	{
    		// multiplication complex
    		a[i] = b[i]*c[i] - b[n-i]*c[n-i];
    		a[n-i] = b[i]*c[n-i] + b[n-i]*c[i];
    	}
     
    	// Correction pour avoir le sens correct
    	for (int i=1; i<n; i+=2)
    		a[i] = -a[i];
    }

    Mais du coup, j'obtiens des harmoniques supplémentaires sur la fin et le début du signal (voir images). Ça ne m'arrange pas vraiment.

    Avant filtrage:


    Après filtrage:


    Si quelqu'un à une idée de l'origine de mon problème (bon, le soucis d'harmoniques, je pense savoir que ça vient de ma correction... vue que j'ai juste mis un offset sur le signal), je le remercierai beaucoup, voilà 15jrs que je suis là dessus, et j'avance pas.

    Je fourni toujours mon programme (version corrigé) si ça peut aider quelqu'un (enfin, surtout moi )
    http://blary.jason.free.fr/download/ffttest.tar.bz2

    Snark.

  6. #6
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    56
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2005
    Messages : 56
    Par défaut
    Hello,

    C'est encore moi avec mon problème que je profite pour faire un up.
    Bon, j'ai changé un peu la technique de convolution, et ça met un peu plus en évidence mon problème. En faîte, c'est dû à un « effet de bord » à cause du zero padding lors de la convolution:


    Y aurait-t-il un moyen pour l'atténuer au maximum ?

  7. #7
    Membre très actif

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Par défaut
    salut


    - combien vaut fc dans ton exemple, et Fs ?

    pour le zero padding je ne suis pas convaincu, la lib que tu utilises doit le gérer non ?
    - combien valent L et M ? il devraient être égaux logiquement

    - essaye un (vrai) filtre passe bas de ce type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (int i=0; i<L; i++) fft_filter[i] = 0;
    for (int i=0; i<L*0.1; i++)
    	fft_filter[i] = fft_filter[L-1-i] = 1;
    (0.1 <--> fc = Pi/5)

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/10/2013, 13h47
  2. signal modulé dans un filtre passe bas
    Par nono73000 dans le forum Simulink
    Réponses: 3
    Dernier message: 02/06/2009, 16h32
  3. Filtre passe bas et filtre de peigne
    Par jena dans le forum Signal
    Réponses: 8
    Dernier message: 04/02/2007, 15h53
  4. Classe filtre passe-bas
    Par nostub dans le forum Multimédia
    Réponses: 1
    Dernier message: 24/12/2006, 17h20
  5. Lire un son WAVE + filtre passe BAS/HAUT
    Par selmak7 dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/08/2006, 13h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo