【问题标题】:C++ Image 2D Fast Fourier TransformC++ 图像 2D 快速傅里叶变换
【发布时间】:2017-12-31 01:06:34
【问题描述】:

我必须在图像上实现 2D FFT 变换(我不能使用库来为我做这件事 - 课程的一部分)。我使用CImg 来加载和保存图像。我做了以下代码:

CImg<Complex> FastFourier(CImg<unsigned char> &originalImage)
{
    //check size in the main.cpp
    CImg<Complex> resultantImage = TransformToComplex(originalImage);
    vector< vector< vector< Complex > > > vectorImage = imageToVector(resultantImage);
    //cout << "Transform to complex" << endl;
    int size = originalImage.width();

    for(int i = 0; i < size; i++)
        FastFourier1D(vectorImage[i], false);

    vectorImage = rotateVector(vectorImage);

    for(int i = 0; i < size; i++)
       FastFourier1D(vectorImage[i], false);

    vectorImage = rotateVector(vectorImage);

    resultantImage = vectorToImage(vectorImage);

    return resultantImage;
}

还有:

void FastFourier1D(vector< vector< Complex > > &input, bool inverse)
{
    int size = input.size();
    double angle;

    if(size <= 1)
        return;

    int channels = input[0].size();
    vector< vector< Complex > > even;
    vector< vector< Complex > > odd;

    for(int i = 0; i < size; i+=2)
    {
        vector< Complex > tempEven;
        vector< Complex > tempOdd;
        for(int channelIterator = 0; channelIterator < channels; channelIterator++)
        {
            tempEven.push_back(input[i][channelIterator]);
            tempOdd.push_back(input[i + 1][channelIterator]);
        }

        even.push_back(tempEven);
        odd.push_back(tempOdd);
    }

    FastFourier1D(even, inverse);
    FastFourier1D(odd, inverse);

    for(int channelIterator = 0; channelIterator < channels; channelIterator++)
    {
        for(int i = 0; i < size / 2; i++)
        {
           if(inverse == false)
               angle = -2.0 * (double)PI * (double)i / (double)size;
           else
               angle = 2.0 * (double)PI * (double)i / (double)size;

           double real = cos(angle);
           double imaginary = sin(angle);

           Complex W;
           W.setRP(real);
           W.setIP(imaginary);

           W = W * odd[i][channelIterator];

           input[i][channelIterator] = even[i][channelIterator] + W;
           input[(size / 2) + i][channelIterator] = even[i][channelIterator] - W;
       }
    }
}

但是结果并不好。输入图像:

FFT(没有任何变换):

逆FFT:

如您所见,它具有 lena 的颜色,但看起来不像 lena。你可以帮帮我吗?有错吗?

【问题讨论】:

  • 在您的第一个代码 sn-p 中,两次调用 FastFourier1D,您将 false 传递给 inverse。这是故意的吗?
  • 是的,这是有意的,因为它是“前向”傅立叶。 Inverse 与传递的“true”几乎相同。我必须调用它两次,因为在 2D 傅里叶中,我必须在第一次通过后用列更改行。
  • 只是一个调试建议。为什么不尝试更简单的图像而不是 Lena?见这个想法:www.fmwconcepts.com/misc_tests/FFT_tests/index.html
  • 如果这不是作业,您可以使用std::complex 代替您自己的课程。
  • 谢谢,正如我在答案中所写,我发现我的乘法运算符有错误的实现。现在,一切正常。

标签: c++ fft ifft cimg


【解决方案1】:

我发现答案是我的 Complex 类中乘法运算符的错误实现。

Complex Complex::operator*(const Complex& a)
{
    Complex number;
    double RP = realPart * a.getRP() - imaginaryPart * a.getIP(); // this line was wrong
    double IP = realPart * a.getIP() + imaginaryPart * a.getRP();
    number.setRP(RP);
    number.setIP(IP);
    return number;
}

real part 中,我忘记了minus。现在整个实现工作正常,傅立叶成功地将图像转换为频域,并逆向转换为空间域。

【讨论】:

    猜你喜欢
    • 2015-08-19
    • 2011-07-12
    • 1970-01-01
    • 2017-09-14
    • 2012-12-10
    • 2010-12-13
    • 2013-03-31
    • 2012-05-25
    • 2020-03-29
    相关资源
    最近更新 更多