简单说一下图像傅里叶变换的思路。函数
文章思路,先理解傅里叶级数,由连续傅里叶级数说明傅里叶变换。以后引入取样函数,对连续函数取样,就能够获得离散函数的傅里叶变换。由此推倒出单变量傅里叶变换。由一维傅里叶变换,就能够推导出二维傅里叶变换,及图像的傅里叶变换。下一篇博客再讲图像傅里叶变换性质。3d
https://www.zhihu.com/question/19714540orm
这篇文章很详细讲述了傅里叶变换公式blog
https://zhuanlan.zhihu.com/p/19759362get
这篇文章没有公式,很清晰讲述了傅里叶变换的意义。就再也不多说,这里只是简单列一下我理解的思路。博客
对于连续变量t,傅里叶级数为it
其实Cn就是频域基的系数,频域就是以
为基的坐标系。io
由傅里叶级数可知,连续变量的傅里叶变换以下:图像处理
,其实就是求的频率域的系数,反变换
class
若对冲击函数对作傅里叶变换,其频率域的冲激函数也是冲激函数对。
可由取样函数将连续函数傅里叶变换推广到离散傅里叶变换。使用冲激函数对连续傅里叶函数取样,就获得了离散傅里叶函数。对离散函数作傅里叶变换。
对两个函数的积作傅里叶变换,至关于对两个函数的傅里叶变换作卷积。
其实至关于将连续函数的傅里叶变换作无限平移,平移距离为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; }
图像变换结果:
条纹状,观察其对称性:
能够看到中心的斜线与原图像条纹垂直。这和条纹的明暗变化方向一致。