Как показать дискретный спектр Фурье (ДПФ) изображения с использованием библиотеки OpenCV и FFTW3?

Я пытаюсь создать спектр Фурье простого изображения. Но то, что я получаю, это только шум. Я пытался перейти по многим ссылкам, которые предлагают уменьшить значения между [0, 255], но я получаю только черное изображение даже после масштабирования, которое я делаю следующим образом:

Код масштабирования:

//Find the maximum value among the magnitudes
        double max=0;
        double mag=0;
        for (i = 0, k = 1; i < h; i++){
            for (j = 0; j < w; j++, k++){
                mag = sqrt(dft[k][0]*dft[k][0] + dft[k][6]*dft[k][7]);
                if (max < mag)
                    max = mag;
            }
        }

Обратите внимание, что я не беру первое значение dftarray, так как оно слишком велико (поскольку это значение DC). То есть я начинаю с k=1 на изображении выше forloop.

Позже я делаю это для масштабирования

mag = 255 * (mag/max) ;  

Код без масштабирования:

#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include "fftw3.h"

/**
 * Sample code to compute the DFTs of IplImage
 */
 
void iplimage_dft(IplImage* img)
{
  IplImage*     img1, * img2;
  fftw_complex* in, * dft, * idft;
  fftw_plan     plan_f, plan_b;
  int           i, j, k, w, h, N;

  /* Copy input image */
  img1 = cvClone(img);

  w = img1->width;
  h = img1->height;
  N = w * h;

  /* Allocate input data for FFTW */
  in   = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
  dft  = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
  idft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);

  /* Create plans */
  plan_f = fftw_plan_dft_2d(w, h, in, dft, FFTW_FORWARD, FFTW_ESTIMATE);
  plan_b = fftw_plan_dft_2d(w, h, dft, idft, FFTW_BACKWARD, FFTW_ESTIMATE);

  /* Populate input data in row-major order */
  for (i = 0, k = 0; i < h; i++)
  {
    for (j = 0; j < w; j++, k++)
    {
      in[k][0] = ((uchar *)(img1->imageData + i * img1->widthStep))[j];
      in[k][1] = 0.0;
        //printf( "%f\n" , in[k][0] ); 
    }
  }

  /* Forward & inverse DFT */
  fftw_execute(plan_f);
  fftw_execute(plan_b);
  
  double max, min = 0;
  
  /* Create output image */
  img2 = cvCreateImage(cvSize(w, h), 8, 1);
   
  /* Convert DFT result to output image */
  for (i = 0, k = 0; i < h; i++)
  {
    for (j = 0; j < w; j++, k++){
         
        double mag = sqrt(dft[k][0]*dft[k][0] + dft[k][2]*dft[k][3]);
        
      ((uchar*)(img2->imageData + i * img2->widthStep))[j] = mag;
    }
  }

    //printf("max : %f min : %f \n ", max, min );

  cvShowImage("iplimage_dft(): original", img1);
  cvShowImage("iplimage_dft(): result", img2);
  cvWaitKey(0);

  /* Free memory */
  fftw_destroy_plan(plan_f);
  fftw_destroy_plan(plan_b);
  fftw_free(in);
  fftw_free(dft);
  fftw_free(idft);
  cvReleaseImage(&img1);
  cvReleaseImage(&img2);
}

int main( int argc, char** argv )
{
    IplImage *img3 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
    iplimage_dft(img3);
    return 0;
}

Вывод: Я получаю только шум, используя приведенный выше код

Но если я введу масштабирование следующим образом: Код после масштабирования

#include <stdio.h>
#include "cv.h"
#include "highgui.h"
#include "fftw3.h"

/**
 * Sample code to compute the DFTs of IplImage
 */
 
void iplimage_dft(IplImage* img)
{
  IplImage*     img1, * img2;
  fftw_complex* in, * dft, * idft;
  fftw_plan     plan_f, plan_b;
  int           i, j, k, w, h, N;

  /* Copy input image */
  img1 = cvClone(img);

  w = img1->width;
  h = img1->height;
  N = w * h;

  /* Allocate input data for FFTW */
  in   = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
  dft  = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
  idft = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);

  /* Create plans */
  plan_f = fftw_plan_dft_2d(w, h, in, dft, FFTW_FORWARD, FFTW_ESTIMATE);
  plan_b = fftw_plan_dft_2d(w, h, dft, idft, FFTW_BACKWARD, FFTW_ESTIMATE);

  /* Populate input data in row-major order */
  for (i = 0, k = 0; i < h; i++)
  {
    for (j = 0; j < w; j++, k++)
    {
      in[k][0] = ((uchar *)(img1->imageData + i * img1->widthStep))[j];
      in[k][5] = 0.0;
        //printf( "%f\n" , in[k][0] ); 
    }
  }

  /* Forward & inverse DFT */
  fftw_execute(plan_f);
  fftw_execute(plan_b);
  
  
  /* Create output image */
  img2 = cvCreateImage(cvSize(w, h), 8, 1);
    
    //Find the maximum value among the magnitudes
    double max=0;
    double mag=0;
    for (i = 0, k = 1; i < h; i++){
        for (j = 0; j < w; j++, k++){
            mag = sqrt(dft[k][0]*dft[k][0] + dft[k][6]*dft[k][7]);
            if (max < mag)
                max = mag;
        }
    }
   
  /* Convert DFT result to output image */
  for (i = 0, k = 0; i < h; i++)
  {
    for (j = 0; j < w; j++, k++){
         
        double mag = sqrt(dft[k][0]*dft[k][0] + dft[k][8]*dft[k][9]);
        
        //Scaling
        mag = 255 * (mag/max);
        
      ((uchar*)(img2->imageData + i * img2->widthStep))[j] = mag;
    }
  }

    //printf("max : %f min : %f \n ", max, min );

  cvShowImage("iplimage_dft(): original", img1);
  cvShowImage("iplimage_dft(): result", img2);
    cvSaveImage("iplimage_dft.png", img2,0 );
  cvWaitKey(0);

  /* Free memory */
  fftw_destroy_plan(plan_f);
  fftw_destroy_plan(plan_b);
  fftw_free(in);
  fftw_free(dft);
  fftw_free(idft);
  cvReleaseImage(&img1);
  cvReleaseImage(&img2);
}

int main( int argc, char** argv )
{
    IplImage *img3 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
    iplimage_dft(img3);
    return 0;
}

Вывод после масштабирования После масштабирования

Пожалуйста, скажите мне, что я делаю неправильно? И как мне сделать масштабирование, чтобы получить правильный спектр изображения.


person sinner    schedule 27.02.2012    source источник
comment
Есть ли кто-нибудь, кто знает, как решить эту проблему? Спасибо!   -  person sinner    schedule 01.03.2012


Ответы (2)


Я нашел решение по этой ссылке: http://www.admindojo.com/discrete-fourier-transform-in-c-with-fftw/

Я реализую то же самое, используя OpenCV, и он частично работает. Я поставлю свое решение, которое я сделаю.

Ваше здоровье!

РЕДАКТИРОВАНИЕ от 4 апреля 2013 г.:

Я использовал OpenCV только для отображения изображений, но для вычисления БПФ я использовал библиотеку FFTW. Это очень легко и просто.

person sinner    schedule 21.03.2012

Все остальное вы сделали правильно, но вам нужна логарифмическая шкала, чтобы увидеть влияние обычно небольших изменений значений коэффициентов Фурье (как и в вашем решении, на выходе есть небольшие белые домены). Тогда большие значения будут белыми, а маленькие изменения окажутся тем, что вы ищете. Даже если вы не используете OpenCV (здесь v. 2.4.2), здесь вы можете найти полное руководство, в котором помимо теории довольно круто описывается: http://docs.opencv.org/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.html

Я только что увидел ваш вопрос. Возможно, ответ приходит слишком поздно, но он может помочь другим в будущем. Не могли бы вы проголосовать за этот ответ как за правильный на ваш вопрос? Я новичок в stackoverflow, и мне нужна репутация для полноценного участия ^^

person Rob    schedule 19.10.2012
comment
да тоже хорошее решение. Но лучше, если нам не нужно использовать для этого какие-либо внешние библиотеки, такие как opencv (кроме FFTW). FFTW отлично работает для получения требуемого результата, а затем результаты могут быть сгенерированы в файле bmp или файле png. - person sinner; 31.10.2012