傅立葉轉換(Fourier Transform)

傅立葉轉換是一對一函數,可以是連續函數或者離散數列,正向傅立葉轉換,是把一個複雜的波,拆解成N個sin和cos組成的波,頻率從0倍到N-1倍,逆向傅立葉轉換,是把N個sin和cos組成的波,頻率從0倍到N-1倍,分別乘上強度、加上相位,再疊加成一個複雜的波。基本上任何的函式可以被無窮的sin和cos函式的加權和來表示,在影像處理上,經由傅立葉轉換將影像從空間域轉成頻率域,經過一些處理,再由反傅立葉轉換從頻率域轉回空間域。

傅立葉轉換時間複雜度為O(N2),實務上通常使用快速傅立葉轉換(Fast Fourier Transform, FFT),將公式的偶數項與奇數項分開整理,把時間複雜度降至O(NlogN),因為必須剛好對半分,所以影像的長、寬都須為2的次方,當長或寬不是2的次方,可在輸入像素末端補零,使得長和寬皆為2的次方。


Fourier Transform

以下示範將影像進行傅立葉轉換,得到頻譜,再從頻譜進行逆向傅立葉轉換,得到原始圖:

int main(){
    Mat inputImg = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    Mat padded;                         
    int m = getOptimalDFTSize(inputImg.rows);  //m為大於等於inputImg.rows裡的最小值,且須為2、3、5的次方相乘
    int n = getOptimalDFTSize(inputImg.cols); 
    copyMakeBorder(inputImg, padded, 0, m-inputImg.rows, 0, n-inputImg.cols, BORDER_CONSTANT, Scalar::all(0)); //為了效率,所以對影像邊界拓展

    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexImg;
    merge(planes, 2, complexImg);        
    dft(complexImg, complexImg);            

    split(complexImg, planes);                  //分離通道,planes[0]為實數部分,planes[1]為虛數部分 
    magnitude(planes[0], planes[1], planes[0]); //planes[0] = sqrt((planes[0])^2 + (planes[1])^2
    Mat magI = planes[0];
    magI += Scalar::all(1);                     //magI = log(1+planes[0])
    log(magI, magI);

    magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));  //令邊長為偶數

    //將區塊重排,讓原點在影像的中央
    int cx = magI.cols/2;
    int cy = magI.rows/2;

    Mat q0(magI, Rect(0, 0, cx, cy));   
    Mat q1(magI, Rect(cx, 0, cx, cy));  
    Mat q2(magI, Rect(0, cy, cx, cy));  
    Mat q3(magI, Rect(cx, cy, cx, cy)); 

    Mat tmp;                          
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);
    q1.copyTo(tmp);                    
    q2.copyTo(q1);
    tmp.copyTo(q2);

    normalize(magI, magI, 0, 1, CV_MINMAX); 

    imshow("輸入圖", inputImg);    
    imshow("頻譜", magI);

    //逆向傅立葉轉換
    Mat ifft;  
    idft(complexImg,ifft,DFT_REAL_OUTPUT);  
    normalize(ifft,ifft,0,1,CV_MINMAX);  
    imshow("逆向求輸入圖",ifft);  
    waitKey();

    return 0;    
}

Fourier Transform

Fourier Transform

Fourier Transform

回到首頁

回到OpenCV教學


參考資料:

OpenCV 教程

演算法筆記