二维图像上的 FFTW 错误反向变换 [with Qt]

FFTW wrong backward transform on 2D image [with Qt]

我在 Qt 中创建了一个应用程序,它允许我打开图像并使用带有 FFTW 库的 2D FFT 变换。问题是我无法通过向后转换检索正确的像素值。但让我们从头开始。

这是我使用的 FFTW 函数的样子

void FFTInterface::FFTW(int rows, int cols, QColor **imageInput,fftw_complex * in, fftw_complex * out)
{
    fftw_plan g;

    g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_FORWARD, FFTW_MEASURE);

    int k = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            in[k][0] = imageInput[i][j].red();
            in[k][1] = 0.0;
            k++;
         }
     }
     fftw_execute(g);
     fftw_destroy_plan(g);
}

rows,cols是一张图片的大小,imageInput是QColor的数组,保存像素值(灰度) , inout 是 fftw_complex 输入和输出数组的对象。

这个函数给我一些结果,必须显示出来。为此,我进行了某种缩放。首先,我对每个值都使用 abs() 函数,以确保它具有正值。之后,我缩放结果。

void FFTInterface::Abs(fftw_complex *out, int rows, int cols)
{
    int k = 0;
    for(int i = 0; i < rows; i++){
        for(int j = 0; j<cols; j++){
            out[k][0] = abs(out[k][0]);
            out[k][1] = abs(out[k][1]);
            k++;
        }
    }
}
void FFTInterface::Scale(fftw_complex * in,int rows, int cols)
{
    float c = 255.0 / log(1+Max(in,rows,cols));

    int k = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            in[k][0] = c*log(1+in[k][0]);
            in[k][1] = c*log(1+in[k][0]);
            k++;
        }
    }
}

这个过程给了我一些我需要的东西。图像看起来不错。但我无法将图像恢复为原始图像。 BACKWARD 的函数如下所示

void FFTInterface::IFFTW(int rows, int cols, fftw_complex * in, fftw_complex * out)
{
    fftw_plan g;
    g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_BACKWARD, FFTW_MEASURE);

    int k = 0;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            in[k][1] = 0.0;
            k++;
         }
    }

    fftw_execute(g);
    fftw_destroy_plan(g);
}

我发现某处没有标准化(结果非常大)。为了规范化,我只是将值除以 N(256,512 等)- 图像的宽度或高度(它始终是一个正方形),但这些值与原始值不同。

你知道我遗漏了什么吗?缩放?我应该使用库中的其他 fft 方法吗?我卡住了。

为了显示图像而采用绝对值和缩放复杂组件,您正在以逆变换不再为您提供原始输入的方式修改数据。为避免此问题,我建议您在缩放之前创建要显示的数据的副本。另外,请确保不要忘记逆变换的输入应该是正向变换的输出(或者可能是信号处理链中的最后一个输出)。

在伪代码中你可以这样做:

interface.FFTW(rows, cols, imageInput, in, out);

size_t N = rows*cols;
fftw_complex* todisplay = fftw_malloc(N);
std::copy(out, out+N, todisplay);
interface.Abs(todisplay);
interface.Scale(todisplay);
... display "todisplay" on your Qt user interface
fftw_free(todislay);

interface.IFFTW(rows, cols, out, reconstructed);