opencv 傅立叶变换及其逆变换实例及其理解

傅立叶变换是把图像从空间域转化到频率域的变换。

空间域

一般的情况下,空间域的图像是f(x,y)=灰度级(0-255),形象一点就是一个二维矩阵,每个坐标对应一个颜色值。

频率域

先介绍几个概念

频率:对于图像来说可以指图像颜色值的梯度,即灰度级的变化速度

幅度:可以简单的理解为是频率的权,即该频率所占的比例

能量=幅度(可能不太准确)

变换结果为F(u,v)

F代表幅度值,u代表x方向的频率,v代表y方向的频率

opencv 傅立叶变换及其逆变换实例及其理解_第1张图片

一般会对变换结果进行一定的处理,以便以图片的形式展现,结果就是幅度值被当作灰度级,亮的地方表示能量高

图像的主要部分集中在低频部分,边界和噪声主要集中在高频部分

由于图像变换的结果原点在边缘部分,不容易显示,所以会将原点移动到中心部分。

那么结果便是中间一个亮点朝着周围发散开来,越远离中心位置的能量越低(越暗)。

接下来展示一下代码

 

#include
#include
using namespace std;
using namespace cv;
int main(int a,char **p)
{
	Mat input=imread(p[1],CV_LOAD_IMAGE_GRAYSCALE);//以灰度图像的方式读入图片
        //如果不知到怎么传入p[1]。可以改为
       //Mat input=imread("image.jpg",CV_LOAD_IMAGE_GRAYSCALE);      
 imshow("input",input);//显示原图
	int w=getOptimalDFTSize(input.cols);
	int h=getOptimalDFTSize(input.rows);//获取最佳尺寸,快速傅立叶变换要求尺寸为2的n次方
	Mat padded;
	copyMakeBorder(input,padded,0,h-input.rows,0,w-input.cols,BORDER_CONSTANT,Scalar::all(0));//填充图像保存到padded中
	Mat plane[]={Mat_(padded),Mat::zeros(padded.size(),CV_32F)};//创建通道
	Mat complexIm;
	merge(plane,2,complexIm);//合并通道
	dft(complexIm,complexIm);//进行傅立叶变换,结果保存在自身
	split(complexIm,plane);//分离通道
	magnitude(plane[0],plane[1],plane[0]);//获取幅度图像,0通道为实数通道,1为虚数,因为二维傅立叶变换结果是复数
	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,Rect(padded.cols/4,padded.rows/4,padded.cols/2,padded.rows/2));
	//opyMakeBorder(_complexim,_complexim,padded.rows/4,padded.rows/4,padded.cols/4,padded.cols/4,BORDER_CONSTANT,Scalar::all(0.75));
	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为黑色
	imshow("idft",iDft[0]);//显示逆变换
//*******************************************************************
	plane[0]+=Scalar::all(1);//傅立叶变换后的图片不好分析,进行对数处理,结果比较好看
	log(plane[0],plane[0]);
	normalize(plane[0],plane[0],1,0,CV_MINMAX);

	imshow("dft",plane[0]);
	waitKey(100086110);
	return 0;
}
	

运行结果

 

opencv 傅立叶变换及其逆变换实例及其理解_第2张图片

接下来介绍一下运行结果

左边到右边,第一副图像是原图,第二图是幅值图,第三副图是逆变换后的结果

幅值图,结果和预料的一样

逆变换的结果显示,多了一圈黑边,这是因为填充后的结果

 

你可能感兴趣的:(opencv)