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