OpenCV高斯濾波GaussianBlur

圖像處理中,常用的濾波算法有均值濾波、中值濾波以及高斯濾波等。

三種濾波器的對比
濾波器種類 基本原理 特點
均值濾波 使用模板內所有像素的平均值代替模板中心像素灰度值 易收到噪聲的干擾,不能完全消除噪聲,只能相對減弱噪聲
中值濾波 計算模板內所有像素中的中值,並用所計算出來的中值體改模板中心像素的灰度值 對噪聲不是那麼敏感,能夠較好的消除椒鹽噪聲,但是容易導致圖像的不連續性
高斯濾波 對圖像鄰域內像素進行平滑時,鄰域內不同位置的像素被賦予不同的權值 對圖像進行平滑的同時,同時能夠更多的保留圖像的總體灰度分佈特徵

下面本文主要對高斯濾波展開詳細的介紹。

基本原理

數值圖像處理中,高斯濾波主要可以使用兩種方法實現。一種是離散化窗口滑窗卷積,另一種方法是通過傅里葉變化。最常見的就是滑窗實現,只有當離散化的窗口非常大,用滑窗計算量非常搭的情況下,可能會考慮基於傅里葉變化的實現方法。所以本文將主要介紹滑窗實現的卷積。

離散化窗口划船卷積時主要利用的是高斯核,高斯核的大小爲奇數,因爲高斯卷積會在其覆蓋區域的中心輸出結果。常用的高斯模板有如下幾種形式:

高斯模板是通過高斯函數計算出來的,公式如下:

以3 × 3的高斯濾波器模板爲例,以模板的中心位置爲座標原點進行取樣。模板在各個位置的座標,如下所示(x軸水平向右,y軸豎直向上)。

這樣,將各個位置的座標帶入到高斯函數G中,得到的每個值按照位置排列,就得到了模板。

這樣輸出的模板有兩種形式:

① 小數類型:直接計算得到的值,沒有經過任何處理。

② 整數類型:將得到的值進行歸一化處理,即將坐上叫的值歸一化爲1,其他每個係數都除以左上角的係數,然後取整。在使用整數模板時,則需要在模板的前面加一個係數,該係數爲模板係數之和的倒數。

例如:生成高斯核爲3 × 3,σ = 0.8的模板

小數模板:

0.057118 0.12476 0.057118
0.12476 0.2725 0.12476
0.057118 0.12476 0.057118

 

整數模板:

1 2.1842 1
2.1842 4.7707 2.1842
1 2.1842 1

                 再經過四捨五入和添加係數得到最終結果:

 從以上描述中我們可以看出,高斯濾波模板中最重要的參數就是高斯分佈的標準差σ。它代表着數據的離散程度,如果σ較小,那麼生成的模板中心繫數越大,而周圍的係數越小,這樣對圖像的平滑效果就不是很明顯;相反,σ較大時,則生成的模板的各個係數相差就不是很大,比較類似於均值模板,對圖像的平滑效果就比較明顯。通過下面的一維高斯分佈圖也可驗證上述觀點。

GaussianBlur函數

函數原型:

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);

參數詳解如下:

src,輸入圖像,即源圖像,填Mat類的對象即可。它可以是單獨的任意通道數的圖片,但需要注意,圖片深度應該爲CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。

dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。比如可以用Mat::Clone,以源圖片爲模板,來初始化得到如假包換的目標圖。

ksize,高斯內核的大小。其中ksize.width和ksize.height可以不同,但他們都必須爲正數和奇數(並不能理解)。或者,它們可以是零的,它們都是由sigma計算而來。

sigmaX,表示高斯核函數在X方向的的標準偏差。

sigmaY,表示高斯核函數在Y方向的的標準偏差。若sigmaY爲零,就將它設爲sigmaX,如果sigmaX和sigmaY都是0,那麼就由ksize.width和ksize.height計算出來。

\sigma _x=(\frac{n_x-1}{2})\cdot 0.30+0.80,n_x=ksize.width-1

\sigma _y=(\frac{n_y-1}{2})\cdot 0.30+0.80,n_y=ksize.height-1

應用示例

#include "stdafx.h"
#include <opencv2/opencv.hpp>


int main()
{
	// 創建兩個窗口,分別顯示輸入和輸出的圖像
	cv::namedWindow("Example2-5_in", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("Example2-5_out", cv::WINDOW_AUTOSIZE);
	
	// 讀取圖像,並用輸入的窗口顯示輸入圖像
	cv::Mat img = cv::imread("C:\\Users\\Bello\\Desktop\\test.jpg", -1);
	cv::imshow("Example2-5_in", img);

	// 聲明輸出矩陣
	cv::Mat out;

	// 進行平滑操作,可以使用GaussianBlur()、blur()、medianBlur()或bilateralFilter()
	// 此處共進行了兩次模糊操作
	cv::GaussianBlur(img, out, cv::Size(5, 5), 3, 3);
	cv::GaussianBlur(out, out, cv::Size(5, 5), 3, 3);

	// 在輸出窗口顯示輸出圖像
	cv::imshow("Example2-5_out", out);
	// 等待鍵盤事件
	cv::waitKey(0);

	// 關閉窗口並釋放相關聯的內存空間
	cv::destroyAllWindows();
	
    return 0;
}

運行結果:

平滑處理前 平滑處理後

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章