1. 程式人生 > >方框濾波/均值濾波/高斯濾波/中值濾波/雙邊濾波

方框濾波/均值濾波/高斯濾波/中值濾波/雙邊濾波

線性鄰域濾波

“平滑處理“(smoothing)也稱“模糊處理”(bluring),是一項簡單且使用頻率很高的影象處理方法。平滑處理的用途有很多,最常見的是用來減少影象上的噪點或者失真。在涉及到降低影象解析度時,平滑處理是非常好用的方法。

線性濾波器:線性濾波器經常用於剔除輸入訊號中不想要的頻率或者從許多頻率中選擇一個想要的頻率。

濾波可分低通濾波和高通濾波兩種。而高斯濾波是指用高斯函式作為濾波函式的濾波操作,至於是不是模糊,要看是高斯低通還是高斯高通,低通就是模糊,高通就是銳化。

在新版本的OpenCV中,提供瞭如下三種常用的線性濾波操作,他們分別被封裝在單獨的函式中,使用起來非常方便:
方框濾波

——boxblur函式
均值濾波——blur函式,均值濾波,是最簡單的一種濾波操作,輸出影象的每一個畫素是核視窗內輸入影象對應畫素的畫素的平均值( 所有畫素加權係數相等),其實說白了它就是歸一化後的方框濾波。
高斯濾波——GaussianBlur函式,高斯濾波是一種線性平滑濾波,適用於消除高斯噪聲,廣泛應用於影象處理的減噪過程。通俗的講,高斯濾波就是對整幅影象進行加權平均的過程,每一個畫素點的值,都由其本身和鄰域內的其他畫素值經過加權平均後得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描影象中的每一個畫素,用模板確定的鄰域內畫素的加權平均灰度值去替代模板中心畫素點的值。

大家常常說高斯濾波最有用的濾波操作,雖然它用起來,效率往往不是最高的。

高斯模糊技術生成的影象,其視覺效果就像是經過一個半透明螢幕在觀察影象,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。高斯平滑也用於計算機視覺演算法中的預先處理階段,以增強影象在不同比例大小下的影象效果(參見尺度空間表示以及尺度空間實現)。從數學的角度來看,影象的高斯模糊過程就是影象與正態分佈做卷積。由於正態分佈又叫作高斯分佈,所以這項技術就叫作高斯模糊。

影象與圓形方框模糊做卷積將會生成更加精確的焦外成像效果。由於高斯函式的傅立葉變換是另外一個高斯函式,所以高斯模糊對於影象來說就是一個低通濾波操作。

非線性濾波

線性濾波器是兩個訊號之和的響應和他們各自響應之和相等。換句話說,每個畫素的輸出值是一些輸入畫素的加權和,線性濾波器易於構造,並且易於從頻率響應角度來進行分析。

其實在很多情況下,使用鄰域畫素的非線性濾波也許會得到更好的效果。比如在噪聲是散粒噪聲而不是高斯噪聲,即影象偶爾會出現很大的值的時候。在這種情況下,用高斯濾波器對影象進行模糊的話,噪聲畫素是不會被去除的,它們只是轉換為更為柔和但仍然可見的散粒。

中值濾波(Median filter)是一種典型的非線性濾波技術,基本思想是用畫素點鄰域灰度值的中值來代替該畫素點的灰度值,該方法在去除脈衝噪聲、椒鹽噪聲的同時又能保留影象邊緣細節,.

中值濾波是基於排序統計理論的一種能有效抑制噪聲的非線性訊號處理技術,其基本原理是把數字影象或數字序列中一點的值用該點的一個鄰域中各點值的中值代替,讓周圍的畫素值接近的真實值,從而消除孤立的噪聲點,對於斑點噪聲(speckle noise)和椒鹽噪聲(salt-and-pepper noise)來說尤其有用,因為它不依賴於鄰域內那些與典型值差別很大的值。中值濾波器在處理連續影象窗函式時與線性濾波器的工作方式類似,但濾波過程卻不再是加權運算。

中值濾波在一定的條件下可以克服常見線性濾波器如最小均方濾波、方框濾波器、均值濾波等帶來的影象細節模糊,而且對濾除脈衝干擾及影象掃描噪聲非常有效,也常用於保護邊緣資訊, 儲存邊緣的特性使它在不希望出現邊緣模糊的場合也很有用,是非常經典的平滑噪聲處理方法。

中值濾波器與均值濾波器比較的優勢:在均值濾波器中,由於噪聲成分被放入平均計算中,所以輸出受到了噪聲的影響,但是在中值濾波器中,由於噪聲成分很難選上,所以幾乎不會影響到輸出。因此同樣用3x3區域進行處理,中值濾波消除的噪聲能力更勝一籌。中值濾波無論是在消除噪聲還是儲存邊緣方面都是一個不錯的方法。

中值濾波器與均值濾波器比較的劣勢:中值濾波花費的時間是均值濾波的5倍以上。

顧名思義,中值濾波選擇每個畫素的鄰域畫素中的中值作為輸出,或者說中值濾波將每一畫素點的灰度值設定為該點某鄰域視窗內的所有畫素點灰度值的中值。

雙邊濾波(Bilateral filter)是一種非線性的濾波方法,是結合影象的空間鄰近度和畫素值相似度的一種折衷處理,同時考慮空域資訊和灰度相似性,達到保邊去噪的目的。具有簡單、非迭代、區域性的特點。

雙邊濾波器的好處是可以做邊緣儲存(edge preserving),一般過去用的維納濾波或者高斯濾波去降噪,都會較明顯地模糊邊緣,對於高頻細節的保護效果並不明顯。雙邊濾波器顧名思義比高斯濾波多了一個高斯方差sigma-d,它是基於空間分佈的高斯濾波函式,所以在邊緣附近,離的較遠的畫素不會太多影響到邊緣上的畫素值,這樣就保證了邊緣附近畫素值的儲存。但是由於儲存了過多的高頻資訊,對於彩色影象裡的高頻噪聲,雙邊濾波器不能夠乾淨的濾掉,只能夠對於低頻資訊進行較好的濾波。

示例程式

//-----------------------------------【標頭檔案包含部分】---------------------------------------
//            描述:包含程式所依賴的標頭檔案
//----------------------------------------------------------------------------------------------
#include "pch.h"
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>

//-----------------------------------【名稱空間宣告部分】---------------------------------------
//            描述:包含程式所使用的名稱空間
//----------------------------------------------------------------------------------------------- 
using namespace std;
using namespace cv;


//-----------------------------------【全域性變數宣告部分】--------------------------------------
//            描述:全域性變數宣告
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage1, g_dstImage2, g_dstImage3, g_dstImage4, g_dstImage5;
int g_nBoxFilterValue = 6;  //方框濾波核心值
int g_nMeanBlurValue = 10;  //均值濾波核心值
int g_nGaussianBlurValue = 6;  //高斯濾波核心值
int g_nMedianBlurValue = 10;  //中值濾波引數值
int g_nBilateralFilterValue = 10;  //雙邊濾波引數值


//-----------------------------------【全域性函式宣告部分】--------------------------------------
//            描述:全域性函式宣告
//-----------------------------------------------------------------------------------------------
//軌跡條回撥函式
static void on_BoxFilter(int, void *);            //方框濾波
static void on_MeanBlur(int, void *);           //均值塊濾波器
static void on_GaussianBlur(int, void *);                    //高斯濾波器
static void on_MedianBlur(int, void *);               //中值濾波器
static void on_BilateralFilter(int, void*);                    //雙邊濾波器



//-----------------------------------【main( )函式】--------------------------------------------
//            描述:控制檯應用程式的入口函式,我們的程式從這裡開始
//-----------------------------------------------------------------------------------------------
int main()
{
	//載入原圖
	g_srcImage = imread("jinan.jpg", 1);
	if (!g_srcImage.data) { printf("讀取srcImage錯誤~!\n"); return false; }

	//克隆原圖到四個Mat型別中
	g_dstImage1 = g_srcImage.clone();
	g_dstImage2 = g_srcImage.clone();
	g_dstImage3 = g_srcImage.clone();
	g_dstImage4 = g_srcImage.clone();
	g_dstImage5 = g_srcImage.clone();

	//顯示原圖
	namedWindow("【<0>原圖視窗】", 1);
	imshow("【<0>原圖視窗】", g_srcImage);


	//=================【<1>方框濾波】=========================
	//建立視窗
	namedWindow("【<1>方框濾波】", 1);
	//建立軌跡條
	createTrackbar("核心值:", "【<1>方框濾波】", &g_nBoxFilterValue, 50, on_BoxFilter);
	on_MeanBlur(g_nBoxFilterValue, 0);
	imshow("【<1>方框濾波】", g_dstImage1);
	//=====================================================


	//=================【<2>均值濾波】==========================
	//建立視窗
	namedWindow("【<2>均值濾波】", 1);
	//建立軌跡條
	createTrackbar("核心值:", "【<2>均值濾波】", &g_nMeanBlurValue, 50, on_MeanBlur);
	on_MeanBlur(g_nMeanBlurValue, 0);
	//======================================================


	//=================【<3>高斯濾波】===========================
	//建立視窗
	namedWindow("【<3>高斯濾波】", 1);
	//建立軌跡條
	createTrackbar("核心值:", "【<3>高斯濾波】", &g_nGaussianBlurValue, 50, on_GaussianBlur);
	on_GaussianBlur(g_nGaussianBlurValue, 0);
	//=======================================================


	//=================【<4>中值濾波】===========================
	//建立視窗
	namedWindow("【<4>中值濾波】", 1);
	//建立軌跡條
	createTrackbar("引數值:", "【<4>中值濾波】", &g_nMedianBlurValue, 50, on_MedianBlur);
	on_MedianBlur(g_nMedianBlurValue, 0);
	//=======================================================


	//=================【<5>雙邊濾波】===========================
	//建立視窗
	namedWindow("【<5>雙邊濾波】", 1);
	//建立軌跡條
	createTrackbar("引數值:", "【<5>雙邊濾波】", &g_nBilateralFilterValue, 50, on_BilateralFilter);
	on_BilateralFilter(g_nBilateralFilterValue, 0);
	//=======================================================


	//輸出一些幫助資訊
	cout << endl << "\t嗯。好了,請調整滾動條觀察影象效果~\n\n"
		<< "\t按下“q”鍵時,程式退出~!\n";
	while (char(waitKey(1)) != 'q') {}

	return 0;
}

//-----------------------------【on_BoxFilter( )函式】------------------------------------
//            描述:方框濾波操作的回撥函式
//-----------------------------------------------------------------------------------------------
static void on_BoxFilter(int, void *)
{
	//方框濾波操作
	boxFilter(g_srcImage, g_dstImage1, -1, Size(g_nBoxFilterValue + 1, g_nBoxFilterValue + 1));
	//顯示視窗
	imshow("【<1>方框濾波】", g_dstImage1);
}

//-----------------------------【on_MeanBlur( )函式】------------------------------------
//            描述:均值濾波操作的回撥函式
//-----------------------------------------------------------------------------------------------
static void on_MeanBlur(int, void *)
{
	blur(g_srcImage, g_dstImage2, Size(g_nMeanBlurValue + 1, g_nMeanBlurValue + 1), Point(-1, -1));
	imshow("【<2>均值濾波】", g_dstImage2);

}

//-----------------------------【on_GaussianBlur( )函式】------------------------------------
//            描述:高斯濾波操作的回撥函式
//-----------------------------------------------------------------------------------------------
static void on_GaussianBlur(int, void *)
{
	GaussianBlur(g_srcImage, g_dstImage3, Size(g_nGaussianBlurValue * 2 + 1, g_nGaussianBlurValue * 2 + 1), 0, 0);
	imshow("【<3>高斯濾波】", g_dstImage3);
}


//-----------------------------【on_MedianBlur( )函式】------------------------------------
//            描述:中值濾波操作的回撥函式
//-----------------------------------------------------------------------------------------------
static void on_MedianBlur(int, void *)
{
	medianBlur(g_srcImage, g_dstImage4, g_nMedianBlurValue * 2 + 1);
	imshow("【<4>中值濾波】", g_dstImage4);
}


//-----------------------------【on_BilateralFilter( )函式】------------------------------------
//            描述:雙邊濾波操作的回撥函式
//-----------------------------------------------------------------------------------------------
static void on_BilateralFilter(int, void *)
{
	bilateralFilter(g_srcImage, g_dstImage5, g_nBilateralFilterValue, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2);
	imshow("【<5>雙邊濾波】", g_dstImage5);
}

執行截圖:

參考

方框濾波
均值濾波
高斯濾波
中值濾波
雙邊濾波