1. 程式人生 > >OpenCv--影象模糊處理(均值,高斯,中值,雙邊)

OpenCv--影象模糊處理(均值,高斯,中值,雙邊)

影象模糊 -

  1. 線性濾波

  • 均值濾波
  • 高斯濾波
  • 中值濾波

     2.非線性濾波

  • 雙邊濾波

影象模糊的作用 -

        模糊操作時影象處理中最簡單和常用的操作之一,該使用的操作之一原因就為了給影象預處理時減低噪聲。

模糊操作的基本原理 - (數學的卷積運算)

        $$ g(i,j)= \ sum_ {k,l} f(i + k,j + l)* h(k,l)$$

其中權重核H(K,L)H(K,L)為“濾波係數”上面的式子可以簡記為:  通常這些卷積運算元計算都是線性操作,所以又叫線性濾波。
$$ g = f \ bigotimes h $$

均值濾波(歸一化濾波)

        解釋:均值濾波是典型的線性濾波演算法,它是指在影象上對目標畫素給一個模板,該模板包括了其周圍的臨近畫素(以目標畫素為中心的周圍8個畫素,構成一個濾波模板,即去掉目標畫素本身),再用模板中的全體畫素的平均值來代替原來畫素值。

缺點:  。由於影象邊框上的畫素無法被模板覆蓋,不做所以處理 
這當然造成了影象邊緣的缺失 

OpenCV中提供均值濾波API:

void blur(Mat src,Mat dst, Size(xradius,yradius), Point(-1, -1))

中值濾波(椒鹽去燥)

        解釋:中值,中間值,將資料從小到大排序後的中間值,用3×3大小模板進行中值濾波。對模板中的9個數進行從小到大排序:1,1,1,2 ,2,5,6,6,10。中間值為2所有,中值濾波後(2,2)位置的值變為2.同理對其他畫素點。 

è¿éåå¾çæè¿°

中值濾波對於椒鹽噪聲抑制作用較強,但是對於高斯噪聲就無能為力了!

OpenCV的提供中值濾波API:

void medianBlur(InputArray src, OutputArray dst, int ksize)

高斯濾波

      高斯濾波是一種線性平滑濾波,適用於消除高斯噪聲,廣泛應用於影象處理的減噪過程。通俗的講,濾波高斯就是對整幅影象進行加權平均的過程,每一個畫素點的值,都由其本身和鄰域內的其他畫素值經過加權平均後得到。

高斯濾波的具體操作是:用一個模板(或稱卷積,掩模)掃描影象中的每一個畫素,用模板確定的鄰域內畫素的加權平均灰度值去替代模板中心畫素點的值。

下面我們來看一下高斯函式:

這是一維的

這是二維的

一維函式圖

二維函式圖

OpenCV中提供API:

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int bord

引數解釋: 
。InputArray src:輸入影象,可以是Mat型別,影象深度為CV_8U,CV_16U,CV_16S,CV_32F,CV_64F 
。OutputArray dst:輸出影象,與輸入影象有相同的型別和尺寸 
。大小ksize:高斯核心大小,這個尺寸與前面兩個濾波核心尺寸不同,ksize.width和ksize.height可以不相同但是這兩個值必須為正奇數,如果這兩個值為0,他們的值將由西格瑪計算。 
。double sigmaX:高斯核函式在X方向上的標準偏差(實測影響不大)
。double sigmaY:高斯核函式在Y方向上的標準偏差,如果sigmaY是0,則函式會自動將sigmaY的值設定為與sigmaX相同的值,如果sigmaX和sigmaY都是0,這兩個值將由ksize。 width和ksize.height計算而來。具體可以參考getGaussianKernel()函式檢視具體細節。建議將size,sigmaX和sigmaY都指定出來 
。int borderType = BORDER_DEFAULT:推斷影象外部畫素的某種便捷模式,有預設值BORDER_DEFAULT,如果沒有特殊需要不用更改,具體可以參考borderInterpolate()函式。

雙邊濾波(非線性濾波)

       解釋及原理:雙邊濾波是一種非線性的濾波方法,是結合影象的空間鄰近度和畫素值相似度的一種折中處理,同時考慮空間與資訊和灰度相似性,達到保邊去噪的目的,具有簡單,非迭代,區域性處理的特點之所以能夠達到保邊去噪的濾波效果是因為濾波器由兩個函式構成:一個函式是由幾何空間距離決定濾波器係數,另一個是由畫素差值決定濾波器係數。 
雙邊濾波器中,輸出畫素的值依賴於鄰域畫素的值的加權組合,其公式如下:  權重係數W(I,J,K,L)取決於定義域核  值域狀語從句:核  的乘積,也就是 
這裡寫圖片描述 

這裡寫圖片描述 

這裡寫圖片描述 

這裡寫圖片描述

通俗來講就是雙邊濾波模板主要有兩個模板生成,第一個是高斯模板,第二個是以灰度級的差值作為函式係數生成的模板,然後這兩個模板點乘就得到了最終的雙邊濾波模板,第一個模板是全域性模板,所以只需要生成以西,第二個模板需要對每個畫素都計算一次。雙邊濾波器比高斯濾波器多了一個高斯方差Σ-d,它是基於空間分佈的高斯濾波函式,所以在邊緣附近,離的較遠的畫素不會太多影響到邊緣上的畫素,這樣就能對邊緣附近的畫素值予以儲存,但是由於儲存過多的高頻資訊,對於彩色影象裡的高頻噪聲,雙邊濾波器不能夠乾淨的濾掉,只能夠對於低頻資訊進行較好的濾除。

/雙邊濾波的核函式是空間域核與畫素範圍域核的綜合結果:
//在影象的平坦區域,畫素值變化很小,對應的畫素範圍域權重接近於1,此時空間域權重起主要作用,相當於進行高斯模糊;
//在影象的邊緣區域,畫素值變化很大,畫素範圍域權重變大,從而保持了邊緣的資訊
//
//當遠離邊界時,即顏色十分相近,顏色權基本一樣時,類似於高斯濾波,這樣變可平滑處理影象。//
當處在邊界時(所謂邊界,就是顏色反差極大的地方),邊界上的點互相顏色相近,會取極大的權值,
//而邊界外的的點,顏色距離很遠,權值取的很小(甚重可以忽略不計),這樣就保護了邊緣

//效率較低,使用比較少

的OpenCV中提供了雙邊濾波器()函式來實現雙邊濾波操作,其原型如下:

C++: void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )

引數解釋: 
。InputArray src:輸入影象,可以是Mat型別,影象必須是8位或浮點型單通道,三通道的影象 
。OutputArray dst:輸出影象,和原影象有相同的尺寸和型別 
。int d:表示在過濾過程中每個畫素鄰域的直徑範圍。如果這個值是非正數,則函式會從第五個引數sigmaSpace計算該值 
。double sigmaColor:顏色空間過濾器的sigma值,這個引數的值月大,表明該畫素鄰域內有月寬廣的顏色會被混合到一起,產生較大的半相等顏色區域 
。double sigmaSpace:座標空間中濾波器的sigma值,如果該較大,則意味著顏色相近的較遠的畫素將相互影響,從而使更大的區域中足夠相似的顏色獲取相同的顏色。當d > 0時,d指定了鄰域大小且與sigmaSpace五官,否則d正比於sigmaSpace。 
。int borderType = BORDER_DEFAULT:用於推斷影象外部畫素的某種邊界模式,有預設值BORDER_DEFAULT。

雙邊濾波器可以很好的儲存影象邊緣細節而濾除掉低頻分量的噪音,但是雙邊濾波器的效率不是太高,花費的時間相較於其他濾波器而言也比較長。 
對於簡單的濾波而言,可以將兩個西格馬值設定成相同的值,如果值<10,則對濾波器影響很小,如果值> 150則會對濾波器產生較大的影響,會使圖片看起來像卡通。 

程式碼實現:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()//模糊的作用是給 影象預處理時候 減低噪聲, 背後的原理是 卷積操作,這些卷積操作都是線性操作,所以叫做線性濾波
{
	Mat src1, src2,src3;
	src1 = imread("C:\\Users\\馬迎偉\\Desktop\\heibao.jpg");
	//src2 = imread("C:\\Users\\馬迎偉\\Desktop\\a1a.jpg");
	if (src1.empty())
	{
		cout << "could not find src1" << endl;
		return -1;
	}
	imshow("原圖",src1);//  size 裡  是正數  且 為奇數
	blur(src1, src2, Size(3, 3), Point(-1, -1));
	namedWindow("blur",CV_WINDOW_AUTOSIZE);
	imshow("blur",src2);

	GaussianBlur(src1, src3, Size(3, 3), 11, 11);
	imshow("gaussianblur", src3);

	waitKey(0);

	return 0;
}
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
	Mat src1, src2, src3,src4;
	src1 = imread("C:\\Users\\馬迎偉\\Desktop\\douyin.jpg");
	//src2 = imread("C:\\Users\\馬迎偉\\Desktop\\a1a.jpg");
	if (src1.empty())
	{
		cout << "could not find src1" << endl;
		return -1;
	}
	imshow("原圖", src1);
	
	//中值濾波 椒鹽去燥
	medianBlur(src1,src4,3);

	//雙邊濾波 ,解釋在最上邊,但是 效率較低
	bilateralFilter(src1, src2, 11, 22, 1.5);
	imshow("bilateralfilter",src2);

	//高斯濾波
	GaussianBlur(src1, src3, Size(3, 3), 11, 11);
	imshow("gaussianblur", src3);

	waitKey(0);

	return 0;
}