圖像傅里葉變換

 

 

 

簡單說一下圖像傅里葉變換的思路。函數

文章思路,先理解傅里葉級數,由連續傅里葉級數說明傅里葉變換。以後引入取樣函數,對連續函數取樣,就能夠獲得離散函數的傅里葉變換。由此推倒出單變量傅里葉變換。由一維傅里葉變換,就能夠推導出二維傅里葉變換,及圖像的傅里葉變換。下一篇博客再講圖像傅里葉變換性質。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;

}

  圖像變換結果:

 

條紋狀,觀察其對稱性:

能夠看到中心的斜線與原圖像條紋垂直。這和條紋的明暗變化方向一致。

相關文章
相關標籤/搜索