作業要求:
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;
}