2017-12-31 34 views
0

画像に2D FFT変換を実装する必要があります(コースの一部としてライブラリを使用することはできません)。私は画像をロードして保存するのにCImgを使います。C++画像2D高速フーリエ変換

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; 
     } 
    } 
} 

結果は良いものではありませんしかし、私は、次のコードを作ってきました。入力画像: Input image

FFT(任意の変換なし): FFT (without any transform)

逆FFT:

Inverse FFT

あなたが見ることができるように、それはレナの色を持っていますが、似ていませんレナ私たちを手伝ってくれますか?間違いはありますか?

+1

最初のコードスニペットでは、「FastFourier1D」と「FastFourier1D」の両方が呼び出されたときに、 'inverse'に' false'を渡します。これは意図的ですか? – Obicere

+0

はい、 "前方"フーリエであるため意図的です。逆は、 "真の"合格とほぼ同じです。 2Dフーリエでは、最初のパスの後に列で行を変更する必要があるため、2回呼び出す必要があります。 – mgrzellak

+0

デバッグのための単なる提案です。なぜLenaの代わりに簡単な画像を試してみませんか?これを参考にしてください:www.fmwconcepts.com/misc_tests/FFT_tests/index.html – VladP

答えて

0

回答は私のComplexクラスの乗算演算子の実装が間違っていることがわかりました。 real part

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; 
} 

私は約minusを忘れてしまいました。これで、実装全体が機能し、フーリエ変換によって画像が周波数領域に変換され、空間領域に逆変換されます。

関連する問題