天天看點

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

作業要求:

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

2.進行傅立葉逆變換

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

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

離散傅立葉變換的原理

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

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

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

         其中,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.進行傅立葉逆變換

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

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

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

主要函數: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 );

運作結果:

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

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

程式:

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

}