图像傅里叶变换

简单说一下图像傅里叶变换的思路。

文章思路,先理解傅里叶级数,由连续傅里叶级数说明傅里叶变换。之后引入取样函数,对连续函数取样,就可以得到离散函数的傅里叶变换。由此推倒出单变量傅里叶变换。由一维傅里叶变换,就可以推导出二维傅里叶变换,及图像的傅里叶变换。下一篇博客再讲图像傅里叶变换性质。

https://www.zhihu.com/question/19714540

这篇文章很详细讲述了傅里叶变换公式

https://zhuanlan.zhihu.com/p/19759362

这篇文章没有公式,很清晰讲述了傅里叶变换的意义。就不再多说,这里只是简单列一下我理解的思路。

对于连续变量t,傅里叶级数为

其实Cn就是频域基的系数,频域就是以为基的坐标系。

由傅里叶级数可知,连续变量的傅里叶变换如下:

,其实就是求的频率域的系数,反变换

若对冲击函数对做傅里叶变换,其频率域的冲激函数也是冲激函数对。

可由取样函数将连续函数傅里叶变换推广到离散傅里叶变换。使用冲激函数对连续傅里叶函数取样,就得到了离散傅里叶函数。对离散函数做傅里叶变换。

  

对两个函数的积做傅里叶变换,相当于对两个函数的傅里叶变换做卷积。

 

其实相当于将连续函数的傅里叶变换做无限平移,平移距离为1/T。此处插入取样定理, 1/T必须大于umax-umin,即频域率的一个周期。

如图:

由对连续函数取样,做傅里叶变换,可推广到单变量的傅里叶变换。

 

其中,取样频率,若要在T内取M个样本,则取样频率为u=m/M,m=0,1,2,3,4

图像就是将一维傅里叶变换扩展到二维。

 图像傅里叶变换特点

平移和旋转

若对图像进行傅里叶变换,在频域进行平移,需要在空间域乘一个系数,公式如下。单纯平移不影响傅里叶谱。

旋转:

周期性

二维傅里叶变换及其反变换在u方向和v方向都是无限周期的,即

由前面离散傅里叶变化可以得到该性质

由周期性和平移特性可知,我们若想让图像在频域呈现一个完整的周期,需要对图像做一个平移。通常做法是在空间域乘-1

对称性

实函数的傅里叶变换频谱是共轭对称的,即F(u,v)=F(-u,-v)

若要避免混淆,一般需要对图像做双倍的填充,之后再对图像进行裁剪。整个的图像傅里叶变换流程如下:

 最后,对某些图像做一些傅里叶变换,并附上代码:

Mat get_freq(Mat src)
{

	Mat srcGray;
	cvtColor(src, srcGray, CV_RGB2GRAY); //灰度图像做傅里叶变换

	int m = getOptimalDFTSize(srcGray.rows); //2,3,5的倍数有更高效率的傅里叶变换
	int n = getOptimalDFTSize(srcGray.cols);

	Mat padded;
	//把灰度图像放在左上角,在右边和下边扩展图像,扩展部分填充为0;
	copyMakeBorder(srcGray, padded, 0, m - srcGray.rows, 0, n - srcGray.cols, BORDER_CONSTANT, Scalar::all(0));
	//cout << padded.size() << endl;
	//这里是获取了两个Mat,一个用于存放dft变换的实部,一个用于存放虚部,初始的时候,实部就是图像本身,虚部全为零
	Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat complexImg;
	//将几个单通道的mat融合成一个多通道的mat,这里融合的complexImg既有实部又有虚部
	merge(planes, 2, complexImg);

	//对上边合成的mat进行傅里叶变换,支持原地操作,傅里叶变换结果为复数.通道1存的是实部,通道二存的是虚部
	dft(complexImg, complexImg);
	//把变换后的结果分割到两个mat,一个实部,一个虚部,方便后续操作
	split(complexImg, planes);
	//这一部分是为了计算dft变换后的幅值,傅立叶变换的幅度值范围大到不适合在屏幕上显示。高值在屏幕上显示为白点,而低值为黑点,高低值的变化无法有效分辨。
	//为了在屏幕上凸显出高低变化的连续性,我们可以用对数尺度来替换线性尺度,以便于显示幅值,计算公式如下:
	//=> log(1 + sqrt(Re(DFT(I))^2 +Im(DFT(I))^2))
	magnitude(planes[0], planes[1], planes[0]);
	Mat mag = planes[0];
	mag += Scalar::all(1);
	log(mag, mag);

	//crop the spectrum, if it has an odd number of rows or columns
	//修剪频谱,如果图像的行或者列是奇数的话,那其频谱是不对称的,因此要修剪
	//这里为什么要用  &-2这个操作,我会在代码后面的 注2 说明
	mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));
	Mat _magI = mag.clone();
	//这一步的目的仍然是为了显示,但是幅度值仍然超过可显示范围[0,1],我们使用 normalize() 函数将幅度归一化到可显示范围。
	normalize(_magI, _magI, 0, 1, CV_MINMAX);
	//imshow("before rearrange", _magI);

	//rearrange the quadrants of Fourier image
	//so that the origin is at the image center
	//重新分配象限,使(0,0)移动到图像中心,  
	//在《数字图像处理》中,傅里叶变换之前要对源图像乘以(-1)^(x+y)进行中心化。  
	//这是是对傅里叶变换结果进行中心化
	int cx = mag.cols / 2;
	int cy = mag.rows / 2;

	Mat tmp;
	Mat q0(mag, Rect(0, 0, cx, cy));   //Top-Left - Create a ROI per quadrant
	Mat q1(mag, Rect(cx, 0, cx, cy));  //Top-Right
	Mat q2(mag, Rect(0, cy, cx, cy));  //Bottom-Left
	Mat q3(mag, Rect(cx, cy, cx, cy)); //Bottom-Right

	//swap quadrants(Top-Left with Bottom-Right)
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);

	// swap quadrant (Top-Rightwith Bottom-Left)
	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);


	normalize(mag, mag, 0, 1, CV_MINMAX);
	return mag;

}

  图像变换结果:

 

条纹状,观察其对称性:

可以看到中心的斜线与原图像条纹垂直。这和条纹的明暗变化方向一致。

原文地址:https://www.cnblogs.com/the-home-of-123/p/11012783.html