在這邊文章中已完成了正向變換,使用idft()實現逆變換;
大致流程如下:
1、讀取圖像,獲取最佳尺寸,快速傅里葉變換要求爲2的N次方
2、以0爲邊緣填充圖像;
3、爲原圖像增加一個通道,進行傅里葉變換;
4、分離通道,獲取幅度圖像,交叉替換 四分之一區域;
5、copy一份用於逆變換,idft-->分離channel,歸一化;
6、log處理dft變換後的圖像,方便查看;
代碼如下:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
static void help(char* progName)
{
cout << endl
<< "This program demonstrated the use of the discrete Fourier transform (DFT). " << endl
<< "The dft of an image is taken and it's power spectrum is displayed." << endl
<< "Usage:" << endl
<< progName << " [image_name -- default ../data/lena.jpg] " << endl << endl;
}
int main(int argc,char *argv[])
{
help(argv[0]);
const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
Mat input = imread(filename, IMREAD_GRAYSCALE);
if( input.empty())
return -1;
imshow("input",input);//顯示原圖
int w=getOptimalDFTSize(input.cols);
int h=getOptimalDFTSize(input.rows);//獲取最佳尺寸,快速傅立葉變換要求尺寸爲2的n次方
Mat padded; //將輸入圖像延擴到最佳的尺寸 在邊緣添加0
copyMakeBorder(input,padded,0,h-input.rows,0,w-input.cols,BORDER_CONSTANT,Scalar::all(0));//填充圖像保存到padded中
Mat plane[]={Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F)};//創建通道
Mat complexIm;
merge(plane,2,complexIm);//爲延擴後的圖像增添一個初始化爲0的通道
dft(complexIm,complexIm);//進行傅立葉變換,結果保存在自身
split(complexIm,plane);//分離通道
magnitude(plane[0],plane[1],plane[0]);//獲取幅度圖像,0通道爲實數通道,1爲虛數,因爲二維傅立葉變換結果是複數
plane[0] = plane[0](Rect(0, 0, plane[0].cols & -2, plane[0].rows & -2));
int cx=padded.cols/2;int cy=padded.rows/2;//一下的操作是移動圖像,左上與右下交換位置,右上與左下交換位置
Mat temp;
Mat part1(plane[0],Rect(0,0,cx,cy));
Mat part2(plane[0],Rect(cx,0,cx,cy));
Mat part3(plane[0],Rect(0,cy,cx,cy));
Mat part4(plane[0],Rect(cx,cy,cx,cy));
part1.copyTo(temp);
part4.copyTo(part1);
temp.copyTo(part4);
part2.copyTo(temp);
part3.copyTo(part2);
temp.copyTo(part3);
//*******************************************************************
Mat _complexim;
complexIm.copyTo(_complexim);//把變換結果複製一份,進行逆變換,也就是恢復原圖
Mat iDft[]={Mat::zeros(plane[0].size(),CV_32F),Mat::zeros(plane[0].size(),CV_32F)};//創建兩個通道,類型爲float,大小爲填充後的尺寸
idft(_complexim,_complexim);//傅立葉逆變換
split(_complexim,iDft);//結果貌似也是複數
magnitude(iDft[0],iDft[1],iDft[0]);//分離通道,主要獲取0通道
// normalize(iDft[0],iDft[0],1,0,CV_MINMAX);//歸一化處理,float類型的顯示範圍爲0-1,大於1爲白色,小於0爲黑色
normalize(iDft[0], iDft[0], 0, 1, NORM_MINMAX);
imshow("idft",iDft[0]);//顯示逆變換
//*******************************************************************
// compute the magnitude and switch to logarithmic scale
// => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
plane[0]+=Scalar::all(1);//傅立葉變換後的圖片不好分析,進行對數處理,結果比較好看
log(plane[0],plane[0]);
normalize(plane[0],plane[0],0,1,NORM_MINMAX);
imshow("dft",plane[0]);
waitKey();
return 0;
}
結果顯示:
原圖:
dft圖:
idft圖像:
逆變換的結果顯示,多了一圈黑邊,這是因爲填充後的結果