作业要求:
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
#include
#include
#include
#include
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;
}