2012-08-15 17 views
1

我相信我在尝试将傅里叶幅度谱转换为图像时遇到缩放问题。OpenCV傅立叶幅度 - 似乎不正确

我正在开发自己的视觉测距项目,以确定摄像机输入的摄影帧之间的平移和旋转。我使用傅里叶变换的相位相关性来确定转换的成功,但是确定旋转的部分需要幅度谱被卷积。基本上我产生的数量似乎并不正确,如下所示。

原始图像:
enter image description here

幅度,用 'MAG = 255 *(MAG /最大)' 缩放
enter image description here

幅度,而不缩放
enter image description here

不幸的是我会需要帮助,我正在使用的功能来确定幅度,我相信我的错误是在幅度的缩放,但我不确定。这个问题已经让我有一段时间了,你的意见将不胜感激,谢谢。

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 = cvCloneImage(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); 

    /* Create plans */ 
    plan_f = fftw_plan_dft_2d(w, h, in, dft, FFTW_FORWARD, 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; 
     } 
    } 

    /* Forward & inverse DFT */ 
    fftw_execute(plan_f); 

    /* 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(pow(dft[k][0],2) + pow(dft[k][1],2)); 
      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(pow(dft[k][0],2) + pow(dft[k][1],2)); 
      mag = 255*(mag/max); 
      ((uchar*)(img2->imageData + i * img2->widthStep))[j] = mag; 
     } 
    } 

    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_free(in); 
    fftw_free(dft); 
    cvReleaseImage(&img1); 
    cvReleaseImage(&img2); 
} 

int main(int argc, char** argv) 
{ 
    argv[1] = "image1.jpg"; 

    IplImage *img3 = cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE); 
    iplimage_dft(img3); 
    return 0; 
} 
+0

我认为opencv有一个注册函数,它可以完成你可能需要的功能(但用不同的方式) – Gir 2012-08-15 14:11:47

+0

这个问题似乎比OpenCV更多关于[FFTW](http://www.fftw.org/)。 [这个例子](http://docs.opencv.org/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.html)展示了如何使用OpenCV获取图像的FFT。 – 2012-08-15 14:23:09

+0

嗨,彼得,是的,我的方法基于FFTW。我的推理是,经过研究,它计算出的离散傅立叶变换比内置的OpenCV函数快得多。 – Josh 2012-08-17 00:29:13

回答

0

许多图像的光谱具有这样的特征 - 几个相对较高的峰值,其余的光场的幅度相当小。看起来你正确的正确,只是细节丢失了,因为大部分频谱的幅度非常小。如果你想检查细节,我经常发现它在某些情况下使用log(mag(spectrum))(甚至log(log(mag(spectrum)))来生成图像更有用。