2011-10-17 61 views
7

我试图从http://www.fftw.org/使用FFT库中的图像,这样我可以在频域中做卷积。但我无法弄清楚如何使它工作。 为了理解如何做到这一点,我试图将FFT图像转换为像素颜色数组,然后向后FFT以获得相同的像素颜色数组。这是我做的:正向FFT的图像和后向FFT图像,以获得相同的结果

fftw_plan planR, planG, planB; 
fftw_complex *inR, *inG, *inB, *outR, *outG, *outB, *resultR, *resultG, *resultB; 

//Allocate arrays. 
inR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
inG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
inB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

outR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
outG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
outB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

resultR = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
resultG = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 
resultB = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * width * width); 

//Fill in arrays with the pixelcolors. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     inR[y * width + x][0] = pixelColors[currentIndex]; 
     inG[y * width + x][0] = pixelColors[currentIndex + 1]; 
     inB[y * width + x][0] = pixelColors[currentIndex + 2]; 
    } 
} 

//Forward plans. 
planR = fftw_plan_dft_2d(width, width, inR, outR, FFTW_FORWARD, FFTW_MEASURE); 
planG = fftw_plan_dft_2d(width, width, inG, outG, FFTW_FORWARD, FFTW_MEASURE); 
planB = fftw_plan_dft_2d(width, width, inB, outB, FFTW_FORWARD, FFTW_MEASURE); 

//Forward FFT. 
fftw_execute(planR); 
fftw_execute(planG); 
fftw_execute(planB); 

//Backward plans. 
planR = fftw_plan_dft_2d(width, width, outR, resultR, FFTW_BACKWARD, FFTW_MEASURE); 
planG = fftw_plan_dft_2d(width, width, outG, resultG, FFTW_BACKWARD, FFTW_MEASURE); 
planB = fftw_plan_dft_2d(width, width, outB, resultB, FFTW_BACKWARD, FFTW_MEASURE); 

//Backward fft 
fftw_execute(planR); 
fftw_execute(planG); 
fftw_execute(planB); 

//Overwrite the pixelcolors with the result. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     pixelColors[currentIndex] = resultR[y * width + x][0]; 
     pixelColors[currentIndex + 1] = resultG[y * width + x][0]; 
     pixelColors[currentIndex + 2] = resultB[y * width + x][0]; 
    } 
} 

可能有人请告诉我如何转发FFT图像,然后向后FFT使用FFTW,以获得相同的结果图像的例子吗?我一直在看很多示例,展示如何使用FFTW进行FFT,但我无法弄清楚它如何适用于我有一系列代表图像的像素颜色的情况。

回答

15

一个重要的一点要注意,当你向前FFT其次是逆FFT的是,这通常会导致N的比例因子被应用到最终的结果,即所产生的图像的像素值需要被N的分以匹配原始像素值。 (N是FFT的大小。)所以你的输出循环应该大概是这个样子:

//Overwrite the pixelcolors with the result. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     pixelColors[currentIndex] = resultR[y * width + x][0]/(width * height); 
     pixelColors[currentIndex + 1] = resultG[y * width + x][0]/(width * height); 
     pixelColors[currentIndex + 2] = resultB[y * width + x][0]/(width * height); 
    } 
} 

另外请注意,你可能想要做一个真正的到复杂的FFT随后复TO-真正的IFFT(在内存和性能方面效率更高)。现在尽管看起来你在两个方向上都是复杂到复杂的,这很好,但是你并没有正确地填充你的输入数组。如果你坚持使用复杂到复杂,那么你可能想你的输入回路改变这样的事情:

//Fill in arrays with the pixelcolors. 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) { 
     int currentIndex = ((y * width) + (x)) * 3; 
     inR[y * width + x][0] = (double)pixelColors[currentIndex]; 
     inR[y * width + x][1] = 0.0; 
     inG[y * width + x][0] = (double)pixelColors[currentIndex + 1]; 
     inG[y * width + x][1] = 0.0; 
     inB[y * width + x][0] = (double)pixelColors[currentIndex + 2]; 
     inB[y * width + x][1] = 0.0; 
    } 
} 

即像素值进入复杂的输入值和的实部虚部需要归零。

还有一点要注意:当你最终得到这个工作,你会发现,性能是可怕的 - 它需要很长的时间来创建相对于采取实际的FFT的时间计划。这个想法是你只需创建一次计划,但是用它来执行许多FFT。所以你需要将计划创建从实际的FFT代码中分离出来,并将其放入初始化例程或构造函数中或其他任何内容中。

2

但是,如果您使用realToComplex或ComplexToRealFunction,请注意图像将存储在维度[高度x(宽度/ 2 +1)]的矩阵中,并且如果您想要在频域,他们会变得有点难...