【问题标题】:Weird but close fft and ifft of image in c++c ++中奇怪但关闭图像的fft和ifft
【发布时间】:2015-06-09 04:59:04
【问题描述】:

我编写了一个程序,用于加载、保存和执行黑白 png 图像的 fft 和 ifft。经过一番调试头痛后,我终于得到了一些连贯的输出,却发现它扭曲了原始图像。

输入:

fft:

ift:

据我测试,每个数组中的像素数据都是正确存储和转换的。像素存储在两个数组中,“data”包含每个像素的 b/w 值,“complex_data”是“data”的两倍,并将每个像素的实数 b/w 值和虚部存储在交替索引中。我的 fft 算法在一个像“complex_data”结构的数组上运行。在从用户读取命令的代码之后,这里是有问题的代码:

if (cmd == "fft")
        {              
            if (height > width) size = height;
            else size = width;

            N = (int)pow(2.0, ceil(log((double)size)/log(2.0)));

            temp_data = (double*) malloc(sizeof(double) * width * 2); //array to hold each row of the image for processing in FFT()

            for (i = 0; i < (int) height; i++)
            {
                for (j = 0; j < (int) width; j++)
                {
                    temp_data[j*2] = complex_data[(i*width*2)+(j*2)];
                    temp_data[j*2+1] = complex_data[(i*width*2)+(j*2)+1];
                }
                FFT(temp_data, N, 1);
                for (j = 0; j < (int) width; j++)
                {
                    complex_data[(i*width*2)+(j*2)] = temp_data[j*2];
                    complex_data[(i*width*2)+(j*2)+1] = temp_data[j*2+1];
                }
            }
            transpose(complex_data, width, height); //tested
            free(temp_data);
            temp_data = (double*) malloc(sizeof(double) * height * 2);
            for (i = 0; i < (int) width; i++)
            {
                for (j = 0; j < (int) height; j++)
                {
                    temp_data[j*2] = complex_data[(i*height*2)+(j*2)];
                    temp_data[j*2+1] = complex_data[(i*height*2)+(j*2)+1];
                }
                FFT(temp_data, N, 1);
                for (j = 0; j < (int) height; j++)
                {
                    complex_data[(i*height*2)+(j*2)] = temp_data[j*2];
                    complex_data[(i*height*2)+(j*2)+1] = temp_data[j*2+1];
                }
            }
            transpose(complex_data, height, width);

            free(temp_data);
            free(data);

            data = complex_to_real(complex_data, image.size()/4); //tested
            image = bw_data_to_vector(data, image.size()/4); //tested
            cout << "*** fft success ***" << endl << endl;



void FFT(double* data, unsigned long nn, int f_or_b){ // f_or_b is 1 for fft, -1 for ifft

unsigned long n, mmax, m, j, istep, i;
double wtemp, w_real, wp_real, wp_imaginary, w_imaginary, theta;
double temp_real, temp_imaginary;

// reverse-binary reindexing to separate even and odd indices
// and to allow us to compute the FFT in place

n = nn<<1;
j = 1;
for (i = 1; i < n; i += 2) {
    if (j > i) {
        swap(data[j-1], data[i-1]);
        swap(data[j], data[i]);
    }
    m = nn;
    while (m >= 2 && j > m) {
        j -= m;
        m >>= 1;
    }
    j += m;
};

// here begins the Danielson-Lanczos section

mmax = 2;
while (n > mmax) {
    istep = mmax<<1;
    theta = f_or_b * (2 * M_PI/mmax);
    wtemp = sin(0.5 * theta);
    wp_real = -2.0 * wtemp * wtemp;
    wp_imaginary = sin(theta);
    w_real = 1.0;
    w_imaginary = 0.0;
    for (m = 1; m < mmax; m += 2) {
        for (i = m; i <= n; i += istep) {
            j = i + mmax;
            temp_real = w_real * data[j-1] - w_imaginary * data[j];
            temp_imaginary = w_real * data[j] + w_imaginary * data[j-1];

            data[j-1] = data[i-1] - temp_real;
            data[j] = data[i] - temp_imaginary;
            data[i-1] += temp_real;
            data[i] += temp_imaginary;
        }
        wtemp = w_real;
        w_real += w_real * wp_real - w_imaginary * wp_imaginary;
        w_imaginary += w_imaginary * wp_real + wtemp * wp_imaginary;
    }
    mmax=istep;
}}

我的 ifft 仅在 f_or_b 设置为 -1 而不是 1 时相同。我的程序在每一行上调用 FFT(),转置图像,再次在每一行上调用 FFT(),然后转回。我的索引可能有错误吗?

【问题讨论】:

  • 与您的问题无关,但您应该真正避免在 c++ 中使用 malloc/free 并改用 new/delete。
  • c 编码的旧习惯。
  • Dangerous habit 只要你使用非 POD 数据
  • 在子链接中查看how to compute DFFT,您将找到我的 (I)DFT/DFFT/DCT/DFCT 的 C++ 源代码,因此您可以将其用于调试(与您的结果进行比较)

标签: c++ image image-processing fft ifft


【解决方案1】:

不是一个实际的答案,因为这个问题只是调试所以一些提示:

你的结果真的很糟糕

应该是这样的:

  • 第一行是实际的DFFT结果
  • Re,Im,Power 被一个常数放大,否则你会看到黑色图像
  • 最后一张图片是未放大的原始图像的IDFFTRe,IM结果
  • 第二行是一样的,但 DFFT 结果被展位x,y 中的一半图像包裹,以匹配大多数 DIP/CV 文本中的常见结果

如您所见,如果您 IDFFT 返回包装的结果,则结果不正确(棋盘掩码)

您只有一个图像作为 DFFT 结果

  • 是功率谱吗?
  • 或者您忘记包含虚部?仅查看或也可以在某处进行计算?

您的 1D **DFFT 工作正常吗?**

  • 对于真实数据,结果应该是对称的
  • 查看我评论中的链接并比较一些示例一维数组的结果
  • 首先调试/修复您的一维 FFT,然后才能进入下一个级别
  • 不要忘记测试真实和复杂的数据...

您的 IDFFT 看起来 BW(无灰色)饱和

  • 那么您是否放大了 DFFT 结果以查看图像并将其用于 IDFFT 而不是原始 DFFT 结果?
  • 还要检查您是否在计算过程中的某处不四舍五入到整数

小心 (I)DFFT 上溢/下溢

如果您的图像像素强度很大并且图像的分辨率也很大,那么您的计算可能会损失精度。新人在图像中看到了这一点,但如果您的图像是 HDR,那么它是可能的。这是 DFFT 为大多项式计算的卷积的常见问题。

【讨论】:

    【解决方案2】:

    感谢大家的意见。所有关于内存损坏的东西,虽然它说明了一点,但并不是问题的根源。我分配的数据大小并不过分,我在正确的地方释放它们。在学习 c 时,我对此进行了很多练习。问题也不是 fft 算法,甚至也不是我的 2D 实现。

    我错过的只是在我的 ifft 代码末尾按 1/(M*N) 缩放。因为图像是 512x512,所以我需要将 ifft 输出缩放 1/(512*512)。另外,我的 fft 看起来像白噪声,因为像素数据没有重新调整到 0 到 255 之间。

    【讨论】:

    • 您应该接受您的回答(点击左侧投票柜台附近的复选图标,以便其他人清楚快速地看到您的问题已解决(以及如何解决)
    【解决方案3】:

    建议你看文章http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html

    Christophe 有一个很好的观点,但他认为这与问题无关是错误的,因为似乎在现代使用 malloc 而不是 new()/free() 不会初始化内存或选择会导致的最佳数据类型在下面列出的所有问题中:-

    可能的原因有:

    1. 数字符号在某处发生变化,当在 dll 上使用平台调用并且值是按值而不是引用传递时,我看到了类似的问题。这是由于内存不一定是空的,因此当您的图像数据输入时,它将对其值执行布尔数学运算。我建议您在将图像数据放在那里之前确保内存是空的。

    2. 内存向右旋转(汇编语言中的 ROR)或向左旋转 (ROL)。如果使用的数据类型不一定匹配,例如,就会发生这种情况。输入无符号数据类型的有符号值,或者一个变量中的位数与另一个变量不同。

    3. 由于输入有符号变量的无符号值导致数据丢失。结果丢失 1 位,因为它将用于确定负数或正数,或者在极端情况下,如果发生二进制补码,则该数字的含义将反转,请在 wikipedia 上查找二进制补码。

    还可以查看在使用前应如何清除/分配内存。 http://www.cprogramming.com/tutorial/memory_debugging_parallel_inspector.html

    【讨论】:

    • 以后,请“编辑”您的答案以添加更多信息,而不是针对同一问题发布多个答案。
    猜你喜欢
    • 2010-12-13
    • 2012-08-11
    • 2020-06-14
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2012-01-01
    相关资源
    最近更新 更多