2017-08-04 5 views
0

J'ai récemment essayé d'implémenter une fonction FFT pour Mat d'Opencv. Je inspiré principalement ma mise en œuvre à partir des exemples de code de FFTW et de: FFTW-OpenCVfftw + opencv sortie incohérente

J'avons payé une attention particulière à adapter la taille de l'image d'entrée afin de fixer le traitement. Il semble que j'ai fait quelque chose de mal parce que la sortie est toujours une image noire.

Voici mon implémentation:

void fft2_32f(const cv::Mat1f& _src, cv::Mat2f& dst) 
    { 

     cv::Mat2f src; 

     const int rows = cv::getOptimalDFTSize(_src.rows); 
     const int cols = cv::getOptimalDFTSize(_src.cols); 

    // const int total = cv::alignSize(rows*cols,steps); 


     if(_src.isContinuous() && _src.rows == rows && _src.cols == cols) 
     { 

      src = cv::Mat2f::zeros(src.size()); 
      dst = cv::Mat2f::zeros(src.size()); 

      // 1) copy the source into a complex matrix (the imaginary component is set to 0). 

      cblas_scopy(src.total(), _src.ptr<float>(), 1, src.ptr<float>(), 2); 

      // 2) prepare and apply the transform. 

      fftwf_complex* ptr_in = reinterpret_cast<fftwf_complex*>(src.ptr<float>()); 
      fftwf_complex* ptr_out = reinterpret_cast<fftwf_complex*>(dst.ptr<float>()); 

    //  fftwf_plan fft = fftwf_plan_dft_1d(src.total(), ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE); 
      fftwf_plan fft = fftwf_plan_dft_2d(src.rows, src.cols, ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE); 

      fftwf_execute(fft); 
      fftwf_destroy_plan(fft); 

      // 3) normalize 

      cblas_saxpy(dst.rows * dst.step1(), 1.f/dst.total(), dst.ptr<float>(), 1, dst.ptr<float>(), 1); 

     } 
     else 
     { 

      src = cv::Mat2f::zeros(rows, cols); 
      dst = cv::Mat2f::zeros(rows, cols); 

      // 1) copy the source into a complex matrix (the imaginary component is set to 0). 

      support::parallel_for(cv::Range(0, _src.rows), [&src, &_src](const cv::Range& range)->void 
      { 

       for(int r=range.start; r<range.end; r++) 
       { 
        int c=0; 

        const float* it_src = _src[r]; 
        float* it_dst = src.ptr<float>(r); 

    #if CV_ENABLE_UNROLLED 
        for(;c<=_src.cols-4; c+=4, it_src+=4, it_dst+=8) 
        { 
         *it_dst = *it_src; 
         *(it_dst+2) = *(it_src+1); 
         *(it_dst+4) = *(it_src+2); 
         *(it_dst+6) = *(it_src+3); 
        } 
    #endif 
        for(; c<_src.cols; c++, it_src++, it_dst+=2) 
         *it_dst = *it_src; 
       } 
      }, 0x80); 

      // 2) prepare and apply the transform. 

      fftwf_complex* ptr_in = reinterpret_cast<fftwf_complex*>(src.ptr<float>()); 
      fftwf_complex* ptr_out = reinterpret_cast<fftwf_complex*>(dst.ptr<float>()); 

      fftwf_plan fft = fftwf_plan_dft_2d(src.rows, src.cols, ptr_in, ptr_out, FFTW_FORWARD, FFTW_ESTIMATE); 

      fftwf_execute(fft); 
      fftwf_destroy_plan(fft); 

      double min(0.); 
      double max(0.); 

      // 3) normalize 

      cblas_saxpy(dst.rows * dst.step1(), 1.f/dst.total(), dst.ptr<float>(), 1, dst.ptr<float>(), 1); 

     }  
    } 

Note:

La mise en œuvre est inspirée par parallel_for: How to use lambda as a parameter to parallel_for_

Merci d'avance pour toute aide.

+0

La version continue fonctionne-t-elle? Cela fonctionne-t-il si vous supprimez la normalisation, ou juste après 'fftw_execute'? Il y a tellement de façons de déboguer cela ... –

+0

En fait le fft est dans les deux cas appliquer sur une donnée continue. Dans le premier cas, si la taille de l'image correspond aux dimensions DFT optimales, il est plus rapide de copier les données dans la matrice complexe. Mais aucun d'entre eux ne fonctionne. –

Répondre

0

Je trouve mon problème. Cette fonction écrite en l'état fonctionne parfaitement (au moins pour le but pour lequel je l'ai fait). Mon problème était que:

cv::Mat dst = cv::Mat::zeros(src.size(), CV_32FC2); 

cv::Mat1f srcw = src; 
cv::Mat1f dstw = dst; 

fft2_32f(srcw, dstw); // realocate dstw to the optimal size for receive the output depending on the size of srcw. ... so the dstw is reallocate but not dst. 

dst.copyTo(_outputVariable); 

Dans ce cas, les informations correctes est en magasin dstw mais pas dans dst en raison de la redistribution à l'intérieur de la fonction. Donc, quand j'essaie de visualiser mes données, j'ai une image noire à cause de cela.

L'utilisation d'appel pour qu'il soit possible:

cv::Mat dst; 

cv::Mat1f srcw = src; 
cv::Mat1f dstw; 

fft2_32f(srcw, dstw); // realocate dstw to the optimal size for receive the output depending on the size of srcw. ... so the dstw is reallocate but not dst. 

dst = dstw; 

dst.copyTo(_outputVariable); // or dstw.copyTo(_outputVariable); 

Avec ce code j'ai eu la bonne sortie. Notez en fonction de l'application un roi (regardez l'opérateur() (const cv :: Rect &) du conteneur Mat d'OpenCV) correspondant à la taille de l'entrée peut être utile afin de préserver les dimensions.

Nous vous remercions de votre aide :).

Quelqu'un peut-il m'aider à souligner ce sujet de près? S'il vous plaît.