我正在尝试使用 http://www.fftw.org/ 中的库对图像进行 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,然后使用 FFTW 对图像进行后向 FFT,以获得相同的结果?我一直在看很多展示如何使用 FFTW 到 FFT 的示例,但我无法弄清楚它如何适用于我有一组代表图像的像素颜色的情况。
最佳答案
在执行正向 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,然后再进行复数到实数的 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 代码分开,并将其放入初始化例程或构造函数或其他任何内容中。
关于c++ - 前向 FFT 图像和后向 FFT 图像以获得相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7790877/