1. 程式人生 > >Opencv 傅立葉變換 傅立葉逆變換

Opencv 傅立葉變換 傅立葉逆變換

作業要求:

1.計算一個圖片的傅立葉變換

2.進行傅立葉逆變換

環境:Win7(64bits),Visual Studio2010,OpenCV 2.4.10

1.計算一個圖片的傅立葉變換

離散傅立葉變換的原理

對一張影象使用傅立葉變換就是將它分解成正弦和餘弦兩個部分,也就是將影象從空間域轉換到頻域。

二維影象的傅立葉變換可以用以下的數學公式表達:


         其中,f是空間域的值,F是頻域的值。

基本資料結構型別:Mat

主要函式:dft() , getOptimalDFTSize(), copyMakeBorder(),magnitude(),normalize(),idft()

---------------------------------------------------------------------------------------------------------------------------------------

voiddft(

InputArraysrc,

OutputArraydst,

intflags=0,

intnonzeroRows=0);            計算DFT的函式

src,儲存源影象的Mat

dst,儲存影象進行傅立葉變換的結果

flags,轉換識別符號,預設為0

nonzeroRows,單獨處理的行,預設為0

dft()呼叫方式:

dft(complexI,complexI,DFT_INVERSE);

intgetOptimalDFTSize(int vecsize);            返回傅立葉最優尺寸大小,有利於提高傅立葉運算的速度

getOptimalDFTSize()呼叫方式:

intm = getOptimalDFTSize(img_in.rows);

intn = getOptimalDFTSize(img_in.cols);

voidcopyMakeBorder(

InputArraysrc,

OutputArraydst,

inttop,

intbottom,

intleft,

intright,

intborderType,

constScalar& value=Scalar() );           作用是擴充影象的邊界

src,輸入影象

dst,輸出影象

top,bottom,left,right,四個方向上需要各擴充的畫素寬度

borderType,邊界型別,一般選擇BORDER_CONSTANT

Scalar,填充的顏色,預設為0

copyMakeBorder()呼叫方式:

copyMakeBorder(img_in,padded,0,m-img_in.rows,0,n-img_in.cols,BORDER_CONSTANT,Scalar::all(0));

voidmagnitude(

InputArrayx,

InputArrayy,

OutputArraymagnitude);

x,x座標

y,y座標

magnitude,根據幅值公式計算得到的公式

magnitude()呼叫方式:

magnitude(planes[0],planes[1],planes[0]);

void normalize(

InputArray src,

OutputArray dst,

double alpha=1,double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray())

src,輸入影象

dst,輸出影象

alpha,歸一化後最大值,預設為1;beta,歸一化後最小值,預設為0

norm_type,歸一化型別

dtype,深度型別

mask,可選擇的操作掩膜

呼叫方式:

normalize(magnitudeImage,magnitudeImage,0,1,NORM_MINMAX);

2.進行傅立葉逆變換

源影象轉換為頻域經過濾波處理後,需要重新轉換到空間域上,這時需要用到傅立葉逆變換。

二維影象的傅立葉變換可以用以下的數學公式表達:


主要函式:idft ();

voididft(

InputArraysrc,

OutputArraydst,

intflags=0,

intnonzeroRows=0);            計算IDFT的函式

src,儲存源影象的Mat

dst,儲存影象進行傅立葉變換的結果

flags,轉換識別符號,預設為0

nonzeroRows,單獨處理的行,預設為0

idft ()呼叫方式:

idft(complexI,invDFT, DFT_SCALE | DFT_REAL_OUTPUT );


執行結果:

源影象                             傅立葉變換影象                         逆變換後圖像

  

程式:

#include <opencv2/core/core.hpp>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/opencv.hpp>

#include <iostream>

using namespace std;

using namespace cv;

int main()

{

    Mat img_in = imread("origin.JPG",0);

    imshow("img_in",img_in);

    int m = getOptimalDFTSize(img_in.rows);//計算最佳擴充尺寸

    int n = getOptimalDFTSize(img_in.cols);

    Mat padded;

    copyMakeBorder(img_in,padded,0,m-img_in.rows,0,n-img_in.cols,BORDER_CONSTANT,Scalar::all(0));//擴充影象

    Mat planes[] = {Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F)};//新增維度,用於儲存傅立葉變換的結果

    Mat complexI;

    merge(planes,2,complexI);//合併通道

    dft(complexI,complexI,DFT_INVERSE);//離散傅立葉變換

    split(complexI,planes);//將儲存在complexI的結果分解到planes[0],planes[1]

    magnitude(planes[0],planes[1],planes[0]);//計算複製

    Mat magnitudeImage = planes[0];

    magnitudeImage = magnitudeImage + Scalar::all(1);

    log(magnitudeImage,magnitudeImage);//用對數表示

    magnitudeImage = magnitudeImage(Rect(0,0,magnitudeImage.cols & -2,magnitudeImage.rows & -2));

    int cx = magnitudeImage.cols/2;

    int cy = magnitudeImage.rows/2;

    Mat q0(magnitudeImage,Rect(0,0,cx,cy));

    Mat q1(magnitudeImage,Rect(cx,0,cx,cy));

    Mat q2(magnitudeImage,Rect(0,cy,cx,cy));

    Mat q3(magnitudeImage,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(magnitudeImage,magnitudeImage,0,1,NORM_MINMAX);//歸一化

    imshow("magnitudeImage",magnitudeImage);

    Mat invDFT,invDFTcvt;

    idft(complexI, invDFT, DFT_SCALE | DFT_REAL_OUTPUT );//離散傅立葉逆變換

    invDFT.convertTo(invDFTcvt, CV_8U);

    imshow("invDFTcvt", invDFTcvt);

    waitKey(0);

    return 0;

}