前向FFT图像和后向FFT图像以获得相同的结果 [英] Forward FFT an image and backward FFT an image to get the same result

查看:504
本文介绍了前向FFT图像和后向FFT图像以获得相同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 http://www.fftw.org/ 的图片进行FFT图片,以便我可以在频域中的卷积。但我不知道如何使它的工作。
要了解如何做到这一点,我试图将FFT图像作为一个像素的数组,然后反向FFT它获得相同的像素数组的阵列。这是我做的:

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

//分配数组。
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);

//使用pixelcolors填充数组。
for(int y = 0; y< height; y ++){
for(int x = 0; x int currentIndex =( )+(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];
}
}

//转发计划。
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);

//正向FFT。
fftw_execute(planR);
fftw_execute(planG);
fftw_execute(planB);

//向后计划。
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);

//向后fft
fftw_execute(planR);
fftw_execute(planG);
fftw_execute(planB);

//用结果覆盖pixelcolors。
for(int y = 0; y< height; y ++){
for(int x = 0; x int currentIndex = )+(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图像,然后使用FFTW反向FFT图像以获得相同的结果?我一直在看许多例子显示如何使用FFTW FFT,但我不知道它是如何适用于我的情况,我有一个像素颜色的数组表示一个图像。


<当进行FFT后进行逆FFT时,要注意的一个重要的事情是,这通常导致将缩放因子N应用于最终结果,即,所得到的图像像素值将需要除以N以便匹配原始像素值。 (N是FFT的大小。)所以你的输出循环应该看起来像这样:

  //覆盖pixelcolors结果。 
for(int y = 0; y< height; y ++){
for(int x = 0; x int currentIndex = )+(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,随后是复数到实数IFFT(在存储器和性能方面更高效)。现在虽然看起来你在两个方向上都复杂到复杂,这是好的,但你不是正确填充你的输入数组。如果你打算复杂到复杂,那么你可能想改变你的输入循环,像这样:

  //使用pixelcolors填充数组。 
for(int y = 0; y< height; y ++){
for(int x = 0; x int currentIndex =( )+(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代码分离开来,并将其放在初始化例程或构造函数中。


I am trying to FFT an image using the library from http://www.fftw.org/ so that I can do a convolution in the frequency domain. But I can't figure out how to make it work. To understand how to do this I am trying to forward FFT an image as an array of pixelcolors and then backward FFT it to get the same array of pixelcolors. Here's what I do:

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];
    }
}

Could someone please show me an example of how to forward FFT an image and then backward FFT the image using FFTW to get the same result? I have been looking at a lot of examples showing how to use FFTW to FFT, but I can't figure out how it applies to my situation where I have an array of pixelcolors representing an Image.

解决方案

One important thing to note when you do forward FFT followed by inverse FFT is that this normally results in a scaling factor of N being applied to the final result, i.e. the resulting image pixel values will need to be divided by N in order to match the original pixel values. (N being the size of the FFT.) So your output loop should probably look something like this:

//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);
    }
}

Also note that you probably want to do a real-to-complex FFT followed by a complex-to-real IFFT (somewhat more efficient in terms of both memory and performance). For now though it looks like you're doing complex-to-complex in both directions, which is fine, but you're not filling your input arrays correctly. If you're going to stick with complex-to-complex then you probably want to change your input loop to something like this:

//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;
    }
}

i.e. the pixel values go into the real parts of the complex input values and the imaginary parts need to be zeroed.

One more thing to note: when you eventually get this working you'll find that performance is terrible - it takes a long time to create a plan relative to the time taken for the actual FFT. The idea is that you create the plan just once, but use it to perform many FFTs. So you'll want to separate out the plan creation from the actual FFT code and put it in an initialisation routine or constructor or whatever.

这篇关于前向FFT图像和后向FFT图像以获得相同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆