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

OpenCV Discussion :

Difference de resultats entre cvDFT et fft2 (MATLAB ou numpy)


Sujet :

OpenCV

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 50
    Par défaut Difference de resultats entre cvDFT et fft2 (MATLAB ou numpy)
    Bonjour,

    J'ai poste la question sur le forum de calcul scientifique python (http://www.developpez.net/forums/d85...hon-numpy-fft/), mais je me demande maintenant si mon probleme ne vient pas de mon utilisation de cvDFT...

    Voila mon code C :

    Code : 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
     double a[] = {
    	            0, 0, 0, 0, 0,
                    1, 1, 1, 1, 1,
                    2, 2, 2, 2, 2,
                    3, 3, 3, 3, 3,
                    4, 4, 4, 4, 4
                   };
     
      CvMat *Ma = cvCreateMat(5, 5, CV_64FC1);
      Ma->data.db = a;
      cvDFT(Ma, Ma, CV_DXT_FORWARD, 0);
     
      printMatrix(a, 5, 5);
    >>
    [ 50      0 0 0 0 ]
    [ -12.5   0 0 0 0 ]
    [ 17.2048 0 0 0 0 ]
    [ -12.5   0 0 0 0 ]
    [ 4.0615  0 0 0 0 ]
    voila mon code python et son resultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> a = np.mgrid[:5, :5][0]
    >>> a
    array([[0, 0, 0, 0, 0],
           [1, 1, 1, 1, 1],
           [2, 2, 2, 2, 2],
           [3, 3, 3, 3, 3],
           [4, 4, 4, 4, 4]])
    >>> real(np.fft.fft2(a))
    array([[ 50. ,   0. ,   0. ,   0. ,   0. ],
           [-12.5,   0. ,   0. ,   0. ,   0. ],
           [-12.5,   0. ,   0. ,   0. ,   0. ],
           [-12.5,   0. ,   0. ,   0. ,   0. ],
           [-12.5,   0. ,   0. ,   0. ,   0. ]])
    >>>
    Je ne suis pas le seul a avoir eu le probleme : http://sci.tech-archive.net/Archive/.../msg00091.html ici avec un vecteur simple...

    Je me doute que le probleme ne viens pas d'opencv mais de mon utilisation ^^ Quelqu'un sais ou je me trompe ?

    merci d'avance !

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 50
    Par défaut
    Apres avoir cherche un peu plus, je pense que mes differences de resultats viennent de la gestion des nombres d'opencv. Mais je ne la comprends pas trop. Voila mes differents resultats de DFT en fonction du type de donnees precise a CVCreateMat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DFT of a CV_32FC1 Matrix
    [
       [ 0 0 1 ]
    ]
    DFT of a CV_32FC2 Matrix
    [
       [ 1 -0.00390625 -0.00390625 ]
    ]
    DFT of a CV_64FC1 Matrix
    [
       [ 1 -0.5 0.866025 ]
    ]
    je stocke toujours ca dans un tableau de double... C'est de la sorcellerie ce que je fais, en vrai je ne sais pas dans quoi le stocker, je connais juste que le resultats fourni par matlab et celui python-numpy correspondent et donc qu'ils doivent etre les resultats attendus.

    Si ca peut aider quelqu'un a comprendre mon erreur... Merci d'avance !

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418

  4. #4
    Membre confirmé
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    65
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2009
    Messages : 65
    Par défaut
    en effet, CvMat n'est qu'un tableau d'entiers/réels.
    Pour les complexes, on utilise un CvMat à 2 canaux (parties réels + imaginaires correspondantes).

    je te passe un code issu des samples d'opencv (mais avec des simplifications)
    Code : 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
    37
        IplImage * im = cvLoadImage( fileName.toStdString().c_str() , CV_LOAD_IMAGE_GRAYSCALE);
        if (!im)
        {   //std::cout << "Error, image not found or can't be loaded.";
            return -1;
        }
     
     
     
        IplImage * realInput;       // input
        IplImage * imaginaryInput;  //
        CvMat* dft_A;   // dft matrix
        IplImage * image_Re;    // output
        IplImage * image_Im;    //
        double m, M;
     
        realInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
        cvScale(im, realInput, 1.0, 0.0);
     
        imaginaryInput = cvCreateImage( cvGetSize(im), IPL_DEPTH_64F, 1);
        cvZero(imaginaryInput);
     
     
        dft_A = cvCreateMat( im->height, im->width, CV_64FC2 ); // complex matrix
        cvMerge(realInput, imaginaryInput, NULL, NULL, dft_A);
     
        cvDFT( dft_A, dft_A, CV_DXT_FORWARD);  // DFT !
     
        // Split Fourier in real and imaginary parts
        image_Re = cvCreateImage( cvSize(im->width, im->height), IPL_DEPTH_64F, 1);
        image_Im = cvCreateImage( cvSize(im->width, im->height), IPL_DEPTH_64F, 1);
        cvSplit( dft_A, image_Re, image_Im, 0, 0 );
     
        // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2)
        cvPow( image_Re, image_Re, 2.0);
        cvPow( image_Im, image_Im, 2.0);
        cvAdd( image_Re, image_Im, image_Re, NULL);
        cvPow( image_Re, image_Re, 0.5 );
    bref, si on suppose que dft_B = DFT(dft_A),
    => dft_A est la matrice complexe en entré (un tableau à 2 canaux), et dft_B est la matrice complexe résultante.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 50
    Par défaut
    Merci a vous, ca me semble plus clair maintenant !

    Par contre, impossible de tester le resultat avec un cout. Savez vous comment je pourrais obtenir le meme affichage de debug qu'avec mon code python ? Mon code :

    Code : 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
     
    	CvMat *dft_A;
     
            dft_A = cvCreateMat(5, 5, CV_64FC2); // complex matrix
    	double a[] = {
    	        4, 0, 0, 0,
                    0, 4, 0, 0,
                    0, 0, 4, 0,
                    0, 0, 0, 4,
                   };
    	dft_A->data.db = a;
    	std::cout << "before : " << a[0] << std::endl;
    	cvDFT( dft_A, dft_A, CV_DXT_FORWARD);  // DFT !
    	std::cout << "after : " << a[0] << std::endl;
     
     
            >> before : 4
    Merci d'avance !

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 50
    Par défaut
    en gros peut etre que je ne devrais pas stocker mes chiffre dans un double[] mais plutot dans un std::complex<double>[]... mais ca ne compile pas...

    Je ne veux pas partir a l'aveuglette en imaginant que les resultats de cvDFT et de mon code python correspondent, meme si c'est probablement le cas...

  7. #7
    Membre confirmé
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    65
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2009
    Messages : 65
    Par défaut
    Le plus simple reste d'utiliser cvGet2D(CvArr* arr, int idx0, int idx1)
    car dans CvMax, les donnés sont alignés de façon pas très facile à décrire: on commence avec toute les cellules de la première ligne, puis toutes les cellules de la 2ème ligne, puis de la suivante...
    pour chaque cellule, on commence par le 1er canal, puis le 2nd, puis le 3ème et le 4ème (si on a 4 canaux)
    du coup, ta méthode pour initialiser un CvMat est fausse dans ton cas; tu as 2 canaux: a1=[4 0 0 0 ; 0 4 0 0 ; 0 0 4 0 ; 0 0 0 4] et a2=[0 0 0 ; 0 0 0 ; 0 0 0]
    donc, tu dois initialiser la variable a ansi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    double a[] = {
    	        4, 0, 0, 0, 0, 0, 0,
                    0, 0, 4, 0, 0, 0, 0,
                    0, 0, 0, 0, 4, 0, 0
                    0, 0, 0, 0, 0, 0, 4,
                   };
    	dft_A->data.db = a;

    regarde cet exemple qui te montre l'arrangement en mémoire:
    Code : 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
    CvMat *dft_A, *dft_1, *dft_2;
     
        dft_A = cvCreateMat(3, 3, CV_64FC2); // complex matrix
        dft_1 = cvCreateMat(3, 3, CV_64FC1);
        dft_2 = cvCreateMat(3, 3, CV_64FC1);
     
        cvSet(dft_1, cvScalar(4)); // 1er canal,  contient que '4'
        cvSet(dft_2, cvScalar(8)); // 2ème canal, contient que '8'
        cvMerge(dft_1, dft_2, 0, 0, dft_A); // fusione les 2 canaux dans une seule structure
     
     
        double *a = dft_A->data.db;
        for (int i=0; i<18; i++, a++)
            std::cout << *a << ' ';
     
        std::cout << std::endl;
     
        for (int i=0; i<dft_A->rows; i++)
        {
            for (int j=0; j<dft_A->cols; j++)
            {
                CvScalar x = cvGet2D(dft_A, i, j);
                std::cout << x.val[0] << " + "
                          << x.val[1] << "j   ";
            }
            std::cout << std::endl;
        }
    en sortie, tu as:
    4 8 4 8 4 8 4 8 4 8 4 8 4 8 4 8 4 8
    4 + 8j 4 + 8j 4 + 8j
    4 + 8j 4 + 8j 4 + 8j
    4 + 8j 4 + 8j 4 + 8j
    le + avec cvGet2D(), c'est que c'est lui qui s'occupe du type de CvMat (U/S/F sur 8/16/32/64 bit, 1/2/3/4 canaux) mais le moins est qu'il est (très) lent à l'exécution.

    je pense que le mieux pour toi est d'utiliser la syntaxe c++ et sa classe cv::Mat, car il facilite l'accès au donnés (regarde ici et )

  8. #8
    Membre confirmé
    Étudiant
    Inscrit en
    Novembre 2009
    Messages
    65
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2009
    Messages : 65
    Par défaut
    Citation Envoyé par Toutankharton Voir le message
    en gros peut etre que je ne devrais pas stocker mes chiffre dans un double[] mais plutot dans un std::complex<double>[]... mais ca ne compile pas...
    Bien sur que ça ne compile pas! un CvMat ne stock que des ENTIERS ou RéELS,
    comme je l'ai montré dans mon post précèdent et dans mon exemple sur l'application d'un dtf, tu mes la parti réel dans une première matrice, la partie imaginaire dans une seconde, puis tu les fusionne... ou encore, tu initialise les éléments un a un avec cvSet2D(...).

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    50
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 50
    Par défaut
    wow ! Il va me falloir un peu de temps pour analyser tout ca, mais je pense avoir compris dans les grandes lignes.

    Toujours est-il que ca fonctionne ! Merci beaucoup pour ta patience, je met le sujet comme resolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Dates] Difference en mois entre 2 dates
    Par zulot dans le forum Langage
    Réponses: 3
    Dernier message: 19/12/2006, 10h42
  2. DIV : differences de positionnements entre IE et FF
    Par Draganthyr dans le forum Mise en page CSS
    Réponses: 8
    Dernier message: 12/12/2006, 11h13
  3. [CSS] Difference d'allignement entre IE et FX
    Par yoann84 dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 24/09/2006, 11h14
  4. Trie de resultat entre 2 tables
    Par escafr dans le forum Langage SQL
    Réponses: 3
    Dernier message: 02/12/2005, 14h29
  5. Réponses: 1
    Dernier message: 07/10/2005, 23h07

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