2017-12-31 32 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'가 호출 될 때마다 'inverse'에 false를 전달합니다. 이것은 의도적입니까? – Obicere

+0

예, '앞으로'푸리에이므로 의도적 인 것입니다. 반전은 "참된"통과와 거의 동일합니다. 2 차원 푸리에에서는 첫 번째 전달 후 열이있는 행을 변경해야하므로 두 번 호출해야합니다. – mgrzellak

+0

디버깅을위한 제안. 왜 Lena 대신에 단순한 이미지를 시도하지 않습니까? 아이디어를 보려면 www.fmwconcepts.com/misc_tests/FFT_tests/index.html – VladP

답변

0

대답은 내 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를 잊어 버렸습니다. 이제 전체 구현이 작동하고 푸리에는 이미지를 주파수 도메인으로 성공적으로 변환하고 공간 도메인으로 역변환합니다.