C ++ FFTW前向后向DFT值被包装

时间:2015-03-10 00:14:29

标签: c++ fftw dft

Hello StackOverflow社区, 我有一个fftw库的dft算法的问题。 我想做的就是向前和向后转换某个模式以再次接收输入模式,当然稍后在转换之间会有某种过滤。

那么,我的程序所做的是:

  1. 创建测试信号
  2. 过滤器或"窗口"测试信号的值为1.0或0.5
  3. 将测试信号复制到fftw_complex数据类型
  4. 执行前进和后退dft
  5. 计算幅度,此处称为阶段
  6. 复制和调整数据以便显示,最后通过OpenCV显示图像
  7. 我的问题是,当不使用过滤时,我的后向变换图像以某种方式被包裹,我无法计算正确的幅度,这应该与我的输入图像/测试信号相同。 当我设置fitler /"窗口"如果值为0.5,则向后转换工作正常,但我的输入图像只有它应该的一半亮。

    下图说明了我的问题:(从左上角到右下角) 1.输入信号,2。后向变换的实部,3。从后向变换后的数据计算出的幅度,4。输入信号乘以0.5,5。后向变换的实部,6。从后向变换后的数据计算出的幅度。 http://imageshack.com/a/img538/5426/nbL9YZ.png

    有没有人知道为什么dft以这种方式表现?!这有点奇怪......

    我的代码看起来像这个atm:

    /***** parameters **************************************************************************/
    int     imSize                                          = 256;
    int     imN                                             = imSize * imSize;
    
    char*   interferogram                                   = new char[imN];
    double* spectrumReal                                    = new double[imN];
    double* spectrumImaginary                               = new double[imN];
    double* outputReal                                      = new double[imN];
    double* outputImaginary                                 = new double[imN];
    double* phase                                           = new double[imN];
    
    char*   spectrumRealChar                                = new char[imN];
    char*   spectrumImaginaryChar                           = new char[imN];
    char*   outputRealChar                                  = new char[imN];
    char*   outputImaginaryChar                             = new char[imN];
    char*   phaseChar                                       = new char[imN];
    
    Mat     interferogramMat                                = Mat(imSize, imSize, CV_8U, interferogram);
    Mat     spectrumRealCharMat                             = Mat(imSize, imSize, CV_8U, spectrumRealChar);
    Mat     spectrumImaginaryCharMat                        = Mat(imSize, imSize, CV_8U, spectrumImaginaryChar);
    Mat     outputRealCharMat                               = Mat(imSize, imSize, CV_8U, outputRealChar);
    Mat     outputImaginaryCharMat                          = Mat(imSize, imSize, CV_8U, outputImaginaryChar);
    Mat     phaseCharMat                                    = Mat(imSize, imSize, CV_8U, phaseChar);
    
    
    /***** compute interferogram ****************************************************************/
    fill_n(interferogram, imN, 0);
    double value = 0;
    double window = 0;
    
    for (int y = 0; y < imSize; y++)
    {
        for (int x = 0; x < imSize; x++)
        {
            value = 127.5 + 127.5 * cos((2*PI) / 10000 * (pow(double(x - imSize/2), 2) + pow(double(y - imSize/2), 2)));
    
            window = 1;
            value *= window;
    
            interferogram[y * imSize + x] = (unsigned char)value;
        }
    }
    
    
    /***** create fftw arays and plans **********************************************************/
    fftw_complex*       input;
    fftw_complex*       spectrum;
    fftw_complex*       output;
    fftw_plan           p_fw;
    fftw_plan           p_bw;
    
    input               = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * imN);
    spectrum            = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * imN);
    output              = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * imN);
    p_fw                = fftw_plan_dft_2d(imSize, imSize, input, spectrum, FFTW_FORWARD, FFTW_ESTIMATE);
    p_bw                = fftw_plan_dft_2d(imSize, imSize, spectrum, output, FFTW_BACKWARD, FFTW_ESTIMATE);
    
    
    /***** copy data ****************************************************************************/
    for (int i = 0; i < imN; i++)
    {
        input[i][0] = double(interferogram[i]) / 255.;
        input[i][1] = 0.;
        spectrum[i][0] = 0.;
        spectrum[i][1] = 0.;
        output[i][0] = 0.;
        output[i][1] = 0.;
    }
    
    
    /***** FPS algorithm ************************************************************************/
    fftw_execute(p_fw);
    
    fftw_execute(p_bw);
    
    for (int i = 0; i < imN; i++)
    {
        phase[i] = sqrt(pow(output[i][0], 2) + pow(output[i][1], 2));
    }
    
    
    /***** copy data ****************************************************************************/
    for (int i = 0; i < imN; i++)
    {
        spectrumReal[i] = spectrum[i][0];
        spectrumImaginary[i] = spectrum[i][1];
    
        outputReal[i] = output[i][0] / imN;
        outputImaginary[i] = output[i][1];
    }
    
    SaveCharImage(interferogram, imN, "01_interferogram_512px_8bit.raw");
    SaveDoubleImage(spectrumReal, imN, "02_spectrum_real_512px_64bit.raw");
    SaveDoubleImage(spectrumImaginary, imN, "03_spectrum_imaginary_512px_64bit.raw");
    SaveDoubleImage(outputReal, imN, "03_output_real_512px_64bit.raw");
    
    DoubleToCharArray(spectrumReal, spectrumRealChar, imSize);
    DoubleToCharArray(spectrumImaginary, spectrumImaginaryChar, imSize);
    
    DoubleToCharArray(outputReal, outputRealChar, imSize);
    DoubleToCharArray(outputImaginary, outputImaginaryChar, imSize);
    
    DoubleToCharArray(phase, phaseChar, imSize);
    
    
    /***** show images **************************************************************************/
    
    imshow("interferogram", interferogramMat);
    imshow("spectrum real", spectrumRealCharMat);
    imshow("spectrum imaginary", spectrumImaginaryCharMat);
    imshow("out real", outputRealCharMat);
    imshow("out imaginary", outputImaginaryCharMat);
    imshow("phase", phaseCharMat);
    
    int key = waitKey(0);
    

1 个答案:

答案 0 :(得分:0)

以下是您的代码的几行:

char*   interferogram  = new char[imN];
...
double value = 0;
double window = 0;

for (int y = 0; y < imSize; y++)
{
   for (int x = 0; x < imSize; x++)
   {
      value = 127.5 + 127.5 * cos((2*PI) / 10000 * (pow(double(x - imSize/2), 2) + pow(double(y - imSize/2), 2)));

      window = 1;
      value *= window;

      interferogram[y * imSize + x] = (unsigned char)value;
   }
}

问题是char介于-128和127之间,而unsigned char介于0到255之间。interferogram[y * imSize + x] = (unsigned char)value;中有char隐式转换

如果window=0.5,它不会影响输出,但如果window=1 value高于127,则会触发更改。这正是您在问题中注意到的问题!

它不会影响第一个显示的图像,因为CV_8U对应unsigned charinterferogram因此被强制转换为unsigned char*。请查看Can I turn unsigned char into char and vice versa?以了解有关charunsigned char演员的更多信息。

问题发生在input[i][0] = double(interferogram[i]) / 255.;:如果window=1interferogram[i]可能为否定,input[i][0]变为否定。

将所有char更改为unsigned char,它应该可以解决问题。

您也可以更改

outputReal[i] = output[i][0] / imN;
outputImaginary[i] = output[i][1];

代表

outputReal[i] = output[i][0];
outputImaginary[i] = output[i][1];

拨打fftw似乎没问题。