在这边文章中已完成了正向变换,使用idft()实现逆变换;
大致流程如下:
1、读取图像,获取最佳尺寸,快速傅里叶变换要求为2的N次方
2、以0为边缘填充图像;
3、为原图像增加一个通道,进行傅里叶变换;
4、分离通道,获取幅度图像,交叉替换 四分之一区域;
5、copy一份用于逆变换,idft-->分离channel,归一化;
6、log处理dft变换后的图像,方便查看;
代码如下:
#include
#include
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_
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图像:
逆变换的结果显示,多了一圈黑边,这是因为填充后的结果