頻域濾波


1、頻域濾波的步驟小結

1、給定一副大小為M*N的輸入圖像,首先得到填充參數P和Q,通常填充(滿足)。

2、對添加必要數量的0,形成大小P*Q的填充圖像。

3、添加的虛部,全部為0即可,合並成新的Mat對象

4、計算步驟3的圖像的DFT,得到,這里要將進行變換。

5、根據相應的算法生成P*Q大小的濾波函數,用陣列相乘.

6、將進行變換,然后對進行IDFT變換。

2、填充圖像

填充圖像主要是將圖像由MN大小填充到PN大小,這里要滿足
填充常數0。這樣做的主要原因是避免循環卷積中的纏繞錯誤。常見的填充大小為P=2M,Q=2N。

2.1、填充代碼

void paddingPQ(Mat& src, Mat& dst)
{
	//要求輸入一張單通道圖片
	//輸入圖像f(x,y) 通常P=2M Q=2N 這里填充為常量0
	int M = src.rows;//高
	int N = src.cols;//寬
	cout << "M N" << M << " " << N << endl;
	dst = Mat::zeros(Size(2 * N, 2 * M), CV_8UC1);

	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N; j++)
		{
			dst.at<uchar>(i, j) = src.at<uchar>(i, j);
		}
	}
}

2.2、填充結果

3 灰度圖像的DFT和IDFT變換

3.1 DFT

1、對於輸入一張灰度圖片如果是CV_8UC1的,先轉換成CV_32FC1。
2、構建輸入圖片的虛部,這也是一個CV_32F的Mat對象,數據全0就可以了。
3、將實部和虛部合並成一個Mat對象,調用dft()函數。
4、對步驟3得到的乘以,主要是將四個角的低頻部分轉換到中間。
5、計算實部和虛部的幅度值,並用,轉換灰度值的范圍(這步主要是為了方便觀察)。
6、展示處理結果。

3.2 DFT代碼

void takeDFT(Mat& source, Mat& destination)
{
	// CV_8UC1 to CV_32FC1
	Mat originalFloat;
	source.convertTo(originalFloat, CV_32FC1, 1.0 / 255.0);
	// ready dft data complex;
	Mat originalComplex[2] = { originalFloat,Mat::zeros(originalFloat.size(),CV_32F) };
	Mat dftOriginal;
	merge(originalComplex, 2, dftOriginal);
	dft(dftOriginal, destination, DFT_COMPLEX_OUTPUT);
}
void showDFT(Mat& source)
{
	Mat sourceComplex[2];
	split(source, sourceComplex);
	Mat logReady;
	magnitude(sourceComplex[0], sourceComplex[1], logReady);
	logReady += Scalar::all(1);
	log(logReady, logReady);
	changeQuadrant(logReady);
	normalize(logReady, logReady, 0, 1, NORM_MINMAX);
	namedWindow("spectrum", WINDOW_FREERATIO);
	imshow("spectrum", logReady);
}
void changeQuadrant(Mat& source)
{
	//draw spectrum
	int cx = source.cols / 2;
	int cy = source.rows / 2;

	Mat q0(source, Rect(0, 0, cx, cy));
	Mat q1(source, Rect(cx, 0, cx, cy));
	Mat q2(source, Rect(0, cy, cx, cy));
	Mat q3(source, Rect(cx, cy, cx, cy));

	Mat tmp;
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);

	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);
}

3.3、DFT效果

4 IDFT

IDFT基本步驟
1、將包含實部和虛部的數據信息的Mat對象,調用下idft()函數就可以,后面實驗都有我就不做單獨演示。
注意:如果前面做了象限的轉換(將低頻轉到中間)這個步驟,現在做一下逆過程。

5 理想低通濾波器

對於做了DFT變換的圖像,高頻主要是圖像中的細節信息,如果做低通濾波,保留的就是直流分量。大致的講就是讓圖片變得模糊。其實這也告訴我們空域的卷積和頻域的點乘可以達到同樣的效果。
在原點為圓心,以為半徑的圓內,無衰減的通過所有的頻率,而圓外阻斷所有的頻率的低通濾波器稱為理想低通濾波器(ILPF),它的的定義為

是一個正常值,表示中心點到頻域中心的距離。

具體步驟:
1、創建P*Q的理想低通濾波過濾器
2、頻域濾波,然后IDFT變換到空域。

5.1 理想低通濾波器實現代碼

void make_ILPE_filter(int width, int height, double D0,Mat& dst) 
{
	dst = Mat::zeros(Size(width, height), CV_32F);
	double D0_2 = pow(D0, 2);
	double half_h = height * (1.0) / 2;
	double half_w = width * (1.0) / 2;
	//創建理想低通濾波器
	for (int i = 0; i < height; i++) 
	{
		for (int j = 0; j < width; j++) 
		{
			double distance = pow((half_h - (double)i), 2) + pow((half_w - (double)j), 2);
			if (less<double>()(distance,D0_2)) {
				dst.at<float>(i, j) = 1;
			}
		}
	}
}

void iILPF(Mat& src, Mat& dst, double D0)
{
	//這里輸入的src是剛通過DFT處理后的Mat 並沒有進行其他的處理
	//先將低頻高亮部分移到中間
	changeQuadrant(src);

	//Mat sourceComplex[2];
	//split(src, sourceComplex);

	//創建低通濾波器
	Mat ifilter;
	make_ILPE_filter(src.cols, src.rows, D0, ifilter);


	Mat sourceComplex[2];
	split(src, sourceComplex);

	Mat temp[2];
	multiply(sourceComplex[0], ifilter, temp[0]);
	multiply(sourceComplex[1], ifilter, temp[1]);

	Mat idft;
	merge(temp, 2, idft);
	//轉換回相應的象限
	changeQuadrant(idft);

	dft(idft, dst, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE);
	imshow("理想低通濾波", dst);
}

5.3理想低通濾波器實驗效果

ILPE 並不實用,ILPE在空間域的振鈴現象是特別的明顯。
這里,很明顯過濾掉了很多細節。

6 理想高通濾波器

理想高通濾波器和理想低通濾波器功能相反,主要是保留圖片的細節。
在原點為圓心,以為半徑的圓內,阻斷通過所有的頻率,而圓外通過所有的頻率的高通通濾波器稱為理想高通濾波器(IHPF),它的的定義為

是一個正常值,截止頻率,表示中心點到頻域中心的距離

6.1、理想高通濾波器實現代碼

void make_IHPE_filter(int width, int height, double D0, Mat& dst)
{
	dst = Mat::ones(Size(width, height), CV_32F);
	double D0_2 = pow(D0, 2);
	double half_h = height * (1.0) / 2;
	double half_w = width * (1.0) / 2;
	//創建理想高通濾波器
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			double distance = pow((half_h - (double)i), 2) + pow((half_w - (double)j), 2);
			if (less<double>()(distance, D0_2)) {
				dst.at<float>(i, j) = 0;
			}
		}
	}
}

void iHLPF(Mat& src, Mat& dst, double D1)
{
	//這里輸入的src是剛通過DFT處理后的Mat 並沒有進行其他的處理
	//先將低頻高亮部分移到中間
	changeQuadrant(src);
	Mat ifilter;
	make_IHPE_filter(src.cols, src.rows, D1, ifilter);


	Mat sourceComplex[2];
	split(src, sourceComplex);

	Mat temp[2];
	multiply(sourceComplex[0], ifilter, temp[0]);
	multiply(sourceComplex[1], ifilter, temp[1]);

	Mat idft;
	merge(temp, 2, idft);
	//轉換回相應的象限
	changeQuadrant(idft);

	dft(idft, dst, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE);
	imshow("理想高通濾波", dst);
}

6.2、理想高通濾波器效果

IHPF和ILPF一樣具有相同的振鈴性質。
這里截止頻率

7 布特沃斯高通濾波器

布特沃斯高通濾波器的定義:

布特沃斯高通濾波器比理想高通濾波器更平滑,這里的n是階數,是截止頻率。

7.1布特沃斯高通濾波器實現

void make_BHPF_filter(int width, int height, double D0,double n, Mat& dst)
{
	dst = Mat::ones(Size(width, height), CV_32F);
	double D0_2 = pow(D0, 2);
	double half_h = height * (1.0) / 2;
	double half_w = width * (1.0) / 2;
	//創建理想高通濾波器
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			double distance = pow((half_h - (double)i), 2) + pow((half_w - (double)j), 2);
			double temp = pow(D0 / sqrt(distance), 2 * n);
			dst.at<float>(i, j) = 1.0 / (1.0 + temp);
		}
	}
}

void iBHPF(Mat& src, Mat& dst, double D1,double n) 
{
	//這里輸入的src是剛通過DFT處理后的Mat 並沒有進行其他的處理
	//先將低頻高亮部分移到中間
	changeQuadrant(src);
	Mat ifilter;
	make_BHPF_filter(src.cols, src.rows, D1,n, ifilter);

	Mat sourceComplex[2];
	split(src, sourceComplex);

	Mat temp[2];
	multiply(sourceComplex[0], ifilter, temp[0]);
	multiply(sourceComplex[1], ifilter, temp[1]);

	Mat idft;
	merge(temp, 2, idft);
	//轉換回相應的象限
	changeQuadrant(idft);

	dft(idft, dst, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE);
	imshow("布特沃斯高通濾波", dst);
}

7.2 布特沃斯高通濾波器實驗效果

n=2

n=2

n=2

8 布特沃斯低通濾波器

布特沃斯低通濾波器的定義:

這里的n是階數,是截止頻率。BLPF傳遞函數並沒有通過頻率和濾除頻率之間給出明顯截止的急劇不連續性,基本上沒有振鈴現象。

8.1布特沃斯低通濾波器代碼實現

void make_BIPF_filter(int width, int height, double D0, double n, Mat& dst)
{
	dst = Mat::ones(Size(width, height), CV_32F);
	double D0_2 = pow(D0, 2);
	double half_h = height * (1.0) / 2;
	double half_w = width * (1.0) / 2;
	//布特沃斯低通濾波器
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			double distance = pow((half_h - (double)i), 2) + pow((half_w - (double)j), 2);
			double temp = pow(sqrt(distance)/D0, 2 * n);
			dst.at<float>(i, j) = 1.0 / (1.0 + temp);
		}
	}
}

void iBIPF(Mat& src, Mat& dst, double D1, double n)
{
	//這里輸入的src是剛通過DFT處理后的Mat 並沒有進行其他的處理
	//先將低頻高亮部分移到中間
	changeQuadrant(src);
	Mat ifilter;
	make_BIPF_filter(src.cols, src.rows, D1, n, ifilter);

	Mat sourceComplex[2];
	split(src, sourceComplex);

	Mat temp[2];
	multiply(sourceComplex[0], ifilter, temp[0]);
	multiply(sourceComplex[1], ifilter, temp[1]);

	Mat idft;
	merge(temp, 2, idft);
	//轉換回相應的象限
	changeQuadrant(idft);

	dft(idft, dst, DFT_INVERSE | DFT_REAL_OUTPUT | DFT_SCALE);
	imshow("布特沃斯低通濾波", dst);
}

8.2布特沃斯低通濾波器實驗效果

BLPF傳遞函數並沒有通過頻率和濾除頻率之間給出明顯的截止的急劇不連續。使用BLPF處理過的圖像基本沒有振鈴現象。
空間域的一階布特沃斯濾波器沒有振鈴現象,二階中,振鈴現象通常很難察覺,但是更高階數的濾波器中振鈴現象會很明顯。
階數越大,越接近理想濾波器。
n=2

n=2

n=2

9、實驗過程遇到的問題

1、雖然實驗是自己做的也完成了,但是傅里葉變換的推導公式哪里還是有些懵懵的,之前學的時候搞懂了,現在又忘了。
2、實驗中觀察振鈴現象,具體的頻譜圖我沒記錄下來,后面改進的時候將這部分代碼單獨拎出來。

完整代碼地址

后記

1、幅度譜決定了一副圖像含有的各種頻率分量的多少,相位譜決定每種頻率分量的位置,通常在圖像處理中是不用處理相位譜的。
2、先對圖像做0填充,然后創建尺寸與填充圖像一樣大的濾波器,這會導致纏繞錯誤,因為沒有對該濾波器進行填充。但是這種方式的錯誤可以通過
圖像填充提供間隔有效地減輕,並且盡力消除振鈴現象(本次實驗中采用的方法是填充為P*Q大小)。
3、另外一種思路構建一個與圖像尺寸大小相同的濾波器,然后計算它的空域濾波器,然后在空域進行填充,然后再計算IDF返回頻域。這種方式會由於
頻域濾波器的空間上具有無限擴展的成分,任何0填充的空間截斷將引入不連續,通常會在頻率域導致振鈴現象(一般情況)。
4、以上的方法由於相位角與實部和虛部之比有關,改變實部和虛部並沒有改變相位,我們稱這樣的濾波器為“零相移濾波器”。
5、 高斯濾波器沒有振鈴現象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM