Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用FFTW仅转换到频域并返回,得到与源极不相同的结果_C++_Signal Processing_Fft_Fftw - Fatal编程技术网

C++ 使用FFTW仅转换到频域并返回,得到与源极不相同的结果

C++ 使用FFTW仅转换到频域并返回,得到与源极不相同的结果,c++,signal-processing,fft,fftw,C++,Signal Processing,Fft,Fftw,在我的测试用例中,我使用FFTW只是将图像转换为频域,然后再转换回空域。但我最终得到的结果与我最初得到的结果大不相同 要解决一些问题,请执行以下操作: 我之所以在每次调用fft()和ifft()时创建FFTW计划,而不是缓存它们,是为了简单。这应该不是问题 为了简单起见,我在将实值数组传递给fftw之前将其转换为复数数组。我发现这种方法比使用实数到复数的DFT函数更难出错 我的代码(包括实用函数、宏和类)如下所示。它使用libcinder(its的一个旧版本)来表示向量类和图形,但即使您不知

在我的测试用例中,我使用FFTW只是将图像转换为频域,然后再转换回空域。但我最终得到的结果与我最初得到的结果大不相同

要解决一些问题,请执行以下操作:

  • 我之所以在每次调用
    fft()
    ifft()
    时创建FFTW计划,而不是缓存它们,是为了简单。这应该不是问题
  • 为了简单起见,我在将实值数组传递给fftw之前将其转换为复数数组。我发现这种方法比使用实数到复数的DFT函数更难出错
我的代码(包括实用函数、宏和类)如下所示。它使用libcinder(its的一个旧版本)来表示向量类和图形,但即使您不知道libcinder,它也是不言自明的。请原谅代码的长度,我已经努力使它非常小,但像我的Array2D类这样的实用程序占用了相当多的空间

main.cpp:

图形输出:

正如你所看到的,右下角的圆圈有点暗,有点渐变

注意:如果取消注释第二个
backAndForthed=backAndForth(已加载)行,结果是正确的(因此,结果只有第一次是错误的)。

问题在于:

auto plan = fftwf_plan_dft_2d(in.h, in.w,
    (fftwf_complex*)in_complex.data, (fftwf_complex*)result.data,
     FFTW_FORWARD, FFTW_MEASURE);
fftwf_execute(plan);
在那里:

auto plan = fftwf_plan_dft_2d(in.h, in.w,
    (fftwf_complex*)in.data, (fftwf_complex*)result.data,
    FFTW_BACKWARD, FFTW_MEASURE);
fftwf_execute(plan);
使用标志
FFTW\u MEASURE
意味着FFTW会尝试许多DFT算法来选择最快的算法。问题是.data
中的输入数组
在传输过程中被覆盖。因此,在
fftwf_执行(计划)之后
结果.data
与创建计划之前不同,不是.data
中的
的DFT。根据FFTW在以下方面的文件:

重要提示:计划器会在计划期间覆盖输入数组,除非已保存的计划(请参阅WITH)可用于解决该问题,因此您应该在创建计划后初始化输入数据。唯一的例外是
FFTW\u估计值
FFTW\u仅
标志,如下所述

该文档提供了一个解决方案:使用标志
FFTW\u ESTIMATE
可确保在规划期间不会覆盖输入/输出数组。

在这种特殊情况下,使用
FFTW_估计值
而不是
FFTW_度量值
预计不会导致计算时间大幅增加。事实上,由于在计划创建过程中计算了许多DFT,因此使用
fftw\u度量值创建fftw\u计划将比使用
fftw\u估计值创建fftw\u计划慢得多。但是,如果要执行多个相同大小的DFT,则必须使用
FFTW_MEASURE
一次性创建并存储计划。如有必要,可以使用


我的猜测是,您可能已经知道r2c和c2r转换,它们旨在将存储空间和计算时间减少近2。

缓冲区
结果的内存。如果未调用
Init
,则不会分配数据。此外,使用标志
FFTW\u MEASURE
可以修改complex.data
或.data
中的输入缓冲区
:您是否可以尝试使用标志
FFTW\u ESTIMATE
?见@francis:谢谢。不过,我在所有情况下都会调用Init——请查看我在初始化列表中传递给
deleter
的构造函数的内容。使用
FFTW\u ESTIMATE
确实解决了这个问题,但我认为这是一个随机(不太可靠)的解决方案,因为:即使
FFTW\u MEASURE
覆盖了输入缓冲区,那也没关系-
fft()
的输入缓冲区在最后被
ifft()
的返回值覆盖,而
ifft
的输入缓冲区是一个本地缓冲区,在传递到
ifft
后会被丢弃。没错,
Init()
在所有情况下都会被调用。对不起。。。但是,如果使用了
FFTW\u MEASURE
,则在调用
fftwf\u execute(plan)
之前,可以修改复杂数据中的输入数组
。类似地,在
ifft()
中也会发生同样的情况:
in。在调用
fftwf\u execute(plan)
之前,可以修改数据。因此,
fftw\u执行(计划)
后的
result.data
不是创建fftw\u计划之前存在的
in.data
的DFT。我不知道这是否是这里唯一的问题,但这似乎是一个潜在的解释,说明ifft不是fft的逆。@francis:好吧,这很有道理。我还找到了你所说的参考资料。Quote:“除非保存的计划(请参阅WITH)可用于解决该问题,否则计划器将在计划期间覆盖输入数组,因此您应该在创建计划后初始化输入数据。唯一的例外是来自的FFTW_估计和FFTW_WITH_only标志[…]。我通过在创建计划时传递虚拟数组(具有正确的大小、类型、变换方向等)来解决这个问题,然后使用fftw的“新数组执行函数”。@francis:因此,即使使用
fftw\u MEASURE
标志,我也能使它正常工作。请将您的解决方案作为答案发布,以便我可以接受。
array 'source' has sum 31397
array 'backAndForthed' has sum -0.110077
auto plan = fftwf_plan_dft_2d(in.h, in.w,
    (fftwf_complex*)in_complex.data, (fftwf_complex*)result.data,
     FFTW_FORWARD, FFTW_MEASURE);
fftwf_execute(plan);
auto plan = fftwf_plan_dft_2d(in.h, in.w,
    (fftwf_complex*)in.data, (fftwf_complex*)result.data,
    FFTW_BACKWARD, FFTW_MEASURE);
fftwf_execute(plan);