簡單說一下圖像傅里葉變換的思路。函數
文章思路,先理解傅里葉級數,由連續傅里葉級數說明傅里葉變換。以後引入取樣函數,對連續函數取樣,就能夠獲得離散函數的傅里葉變換。由此推倒出單變量傅里葉變換。由一維傅里葉變換,就能夠推導出二維傅里葉變換,及圖像的傅里葉變換。下一篇博客再講圖像傅里葉變換性質。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; }
圖像變換結果:
條紋狀,觀察其對稱性:
能夠看到中心的斜線與原圖像條紋垂直。這和條紋的明暗變化方向一致。