空間濾波是一種採用濾波處理的圖像增強方法。其理論基礎是空間卷積和空間相關。目的是改善圖像質量。
空間濾波的模板被稱爲空間濾波器。
在圖像中的任意一點(x,y),濾波器的響應g(x,y)是濾波器係數與該濾波器包圍的圖像像素的乘積之和。
一般來說,用大小爲m * n的濾波器對大小爲M * N的圖像進行線性空間濾波,可由下式表示:
w是濾波器的係數,f是像素值。對於m * n的模板,我們假設m = 2a + 1,n = 2b + 1,a,b爲正整數。
①方框濾波 box Filter
void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT )
- 第一個參數,InputArray類型的src,輸入圖像,即源圖像。
- 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。
- 第三個參數,int類型的ddepth,輸出圖像的深度,-1代表使用原圖深度,即src.depth()。
- 第四個參數,Size類型的ksize,內核的大小。一般這樣寫Size( w,h )來表示內核的大小( 其中,w 爲像素寬度, h爲像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小,也就是濾波器模板的大小。
- 第五個參數,Point類型的anchor,表示錨點(即被平滑的那個點),默認值爲Point(-1,-1)。如果這個點座標是負值的話,就表示取核的中心爲錨點,所以默認值Point(-1,-1)表示這個錨點在覈的中心。
- 第六個參數,bool類型的normalize,默認值爲true,一個標識符,表示內核是否被其區域歸一化(normalized)了。
- 第七個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。有默認值BORDER_DEFAULT,我們一般不去管它。
Mat srcImage = imread("M:/圖像處理實驗/boxFilter/src.bmp");
boxFilter(srcImage, srcImage, -1,Size(5, 5));
imwrite("M:/圖像處理實驗/boxFilter/dst.bmp", srcImage);
Public Shared Sub BoxFilter(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ddepth As Emgu.CV.CvEnum.DepthType, ksize As System.Drawing.Size, anchor As System.Drawing.Point, Optional normalize As Boolean = True, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)
Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\圖像處理實驗\boxFilter\src.bmp")
CvInvoke.BoxFilter(img, img, Emgu.CV.CvEnum.DepthType.Cv8U, New System.Drawing.Size(5, 5), New System.Drawing.Point(-1, -1), True, Emgu.CV.CvEnum.BorderType.Reflect101)
img.Save("M:\圖像處理實驗\boxFilter\src-result.bmp")
void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
- 第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。該函數對通道是獨立處理的,且可以處理任意通道數的圖片,但需要注意,待處理的圖片深度應該爲CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
- 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。比如可以用Mat::Clone,以源圖片爲模板,來初始化得到如假包換的目標圖。
- 第三個參數,Size類型(對Size類型稍後有講解)的ksize,內核的大小。一般這樣寫Size( w,h )來表示內核的大小( 其中,w 爲像素寬度, h爲像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
- 第四個參數,Point類型的anchor,表示錨點(即被平滑的那個點),注意他有默認值Point(-1,-1)。如果這個點座標是負值的話,就表示取核的中心爲錨點,所以默認值Point(-1,-1)表示這個錨點在覈的中心。
- 第五個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。有默認值BORDER_DEFAULT,我們一般不去管它。
Mat srcImage = imread("M:/圖像處理實驗/blur/src.bmp");
blur(srcImage, srcImage,Size(5, 5), Point(-1,-1));
imwrite("M:/圖像處理實驗/blur/dst.bmp", srcImage);
PublicSharedSubBlur ( srcAsIInputArray, dstAsIOutputArray, ksizeAsSize, anchorAsPoint, Optional borderTypeAsBorderType = BorderType.Reflect101 )
Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\圖像處理實驗\blur\src.bmp")
CvInvoke.Blur(img, img, New System.Drawing.Size(5, 5), New System.Drawing.Point(-1, -1), Emgu.CV.CvEnum.BorderType.Reflect101)
img.Save("M:\圖像處理實驗\blur\src-result.bmp")
下面這幅圖中的是均值濾波器模板
鄰域越大平滑的效果越好。但是鄰域過大,平滑會使邊緣信息損失的越大,從而使輸出的圖像變得模糊,因此需要合理的選擇鄰域的大小。
需要注意的是,與Matlab不同,OpenCV的濾波操作處理後的圖像與輸入圖像的大小是相同的。爲了達到這一效果,OpenCV在圖像的邊界之外創造了虛擬的像素,默認情況下通過對邊緣的複製來實現。
模板的大小由那些即將融入背景中的物體R的尺寸來決定。
濾波後的圖像中可能會有黑邊。這是由於我們用0(黑色)填充原圖像的邊界,經濾波後,再去除填充區域的結果,某些黑的混入了濾波後的圖像。對於使用較大濾波器平滑的圖像,這就成了問題。
void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )
- 第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可。它可以是單獨的任意通道數的圖片,但需要注意,圖片深度應該爲CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
- 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。比如可以用Mat::Clone,以源圖片爲模板,來初始化得到如假包換的目標圖。
- 第三個參數,Size類型的ksize高斯內核的大小。其中ksize.width和ksize.height可以不同,但他們都必須爲正數和奇數。或者,它們可以是零的,它們都是由sigma計算而來。
- 第四個參數,double類型的sigmaX,表示高斯核函數在X方向的的標準偏差。
- 第五個參數,double類型的sigmaY,表示高斯核函數在Y方向的的標準偏差。若sigmaY爲零,就將它設爲sigmaX,如果sigmaX和sigmaY都是0,那麼就由ksize.width和ksize.height計算出來。
- 爲了結果的正確性着想,最好是把第三個參數Size,第四個參數sigmaX和第五個參數sigmaY全部指定到。
- 第六個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。有默認值BORDER_DEFAULT,我們一般不去管它。
Mat srcImage = imread("M:/圖像處理實驗/GaussianBlur/src.bmp");
Mat dstImage;
GaussianBlur(srcImage, dstImage, Size(5, 5), 0, 0);
imwrite("M:/圖像處理實驗/GaussianBlur/dst.bmp", dstImage);
Public Shared Sub GaussianBlur(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ksize As System.Drawing.Size, sigmaX As Double, Optional sigmaY As Double = 0.0, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)
Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\圖像處理實驗\GaussianBlur\src.bmp")
CvInvoke.GaussianBlur(img, img, New System.Drawing.Size(5, 5), 0, 0)
img.Save("M:\圖像處理實驗\GaussianBlur\src-result.bmp")
高斯濾波是一種線性平滑濾波,適用於服從正太分佈的噪聲,廣泛應用於圖像處理的減噪過程。通俗的講,高斯濾波就是對整幅圖像進行加權平均的過程,每一個像素點的值,都由其本身和鄰域內的其他像素值經過加權平均後得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描圖像中的每一個像素,用模板確定的鄰域內像素的加權平均灰度值去替代模板中心像素點的值。
在圖像處理中,高斯濾波一般有兩種實現方式,一是用離散化窗口滑窗卷積,另一種通過傅里葉變換。最常見的就是第一種滑窗實現,只有當離散化的窗口非常大,用滑窗計算量非常大(即使用可分離濾波器的實現)的情況下,可能會考慮基於傅里葉變化的實現方法。
OpenCV的GaussianBlur就是基於離散化窗口卷積實現的。
大家常常說高斯濾波最有用的濾波操作,雖然它用起來,效率往往不是最高的。
高斯模糊技術生成的圖像,其視覺效果就像是經過一個半透明屏幕在觀察圖像,這與鏡頭焦外成像效果散景以及普通照明陰影中的效果都明顯不同。高斯平滑也用於計算機視覺算法中的預先處理階段,以增強圖像在不同比例大小下的圖像效果(參見尺度空間表示以及尺度空間實現)。從數學的角度來看,圖像的高斯模糊過程就是圖像與正態分佈做卷積。由於正態分佈又叫作高斯分佈,所以這項技術就叫作高斯模糊。
圖像與圓形方框模糊做卷積將會生成更加精確的焦外成像效果。由於高斯函數的傅立葉變換是另外一個高斯函數,所以高斯模糊對於圖像來說就是一個低通濾波操作。
所謂的加權平均是指,用不同的係數去乘以像素。即一些像素的重要性(權重)比另外一些像素的重要性更大。
係數越大,在計算中可以爲該像素提供更大的權重。
這種加權重的策略的目的是,在平滑處理中,試圖降低模糊。
void medianBlur(InputArray src,OutputArray dst, int ksize)
- 第一個參數,InputArray類型的src,函數的輸入參數,填1、3或者4通道的Mat類型的圖像;當ksize爲3或者5的時候,圖像深度需爲CV_8U,CV_16U,或CV_32F其中之一,而對於較大孔徑尺寸的圖片,它只能是CV_8U。
- 第二個參數,OutputArray類型的dst,即目標圖像,函數的輸出參數,需要和源圖片有一樣的尺寸和類型。
- 第三個參數,int類型的ksize,孔徑的線性尺寸(aperture linear size),注意這個參數必須是大於1的奇數
Mat srcImage=imread("M:/圖像處理實驗/MedianBlur/src.bmp");
Mat dstImage;
medianBlur( srcImage, out, 5);
imwrite("M:/圖像處理實驗/MedianBlur/dst.bmp", dstImage);
Public Shared Sub MedianBlur(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, ksize As Integer)
Dim img As Image(Of Bgr, Byte) = New Image(Of Bgr, Byte)("M:\圖像處理實驗\MedianBlur\src.bmp")
CvInvoke.MedianBlur(img, img, 7)
img.Save("M:\圖像處理實驗\MedianBlur\src-result.bmp")
中值濾波器的使用非常的普遍,它對於一定類型的隨機噪聲提供了一種優秀的去噪能力。而且比同尺寸的線性平滑濾波器的模糊程度明顯要低。不足之處就是中值濾波花費的時間是均值濾波的5倍以上。
中值濾波器對於處理脈衝噪聲非常有效,這種噪聲稱爲椒鹽噪聲,因爲這種噪聲是以黑白點的形式疊加在圖像上的。
中值濾波器的主要功能是使擁有不同灰度的點看起來更接近於他們的相鄰點。
void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
- 第一個參數,InputArray類型的src,輸入圖像,即源圖像,需要爲8位或者浮點型單通道、三通道的圖像。
- 第二個參數,OutputArray類型的dst,即目標圖像,需要和源圖片有一樣的尺寸和類型。
- 第三個參數,int類型的d,表示在過濾過程中每個像素鄰域的直徑。如果這個值我們設其爲非正數,那麼OpenCV會從第五個參數sigmaSpace來計算出它來。
- 第四個參數,double類型的sigmaColor,顏色空間濾波器的sigma值。這個參數的值越大,就表明該像素鄰域內有更寬廣的顏色會被混合到一起,產生較大的半相等顏色區域。
- 第五個參數,double類型的sigmaSpace座標空間中濾波器的sigma值,座標空間的標註方差。他的數值越大,意味着越遠的像素會相互影響,從而使更大的區域足夠相似的顏色獲取相同的顏色。當d>0,d指定了鄰域大小且與sigmaSpace無關。否則,d正比於sigmaSpace。
- 第六個參數,int類型的borderType,用於推斷圖像外部像素的某種邊界模式。注意它有默認值BORDER_DEFAULT。
Mat srcImage=imread("M:/圖像處理實驗/bilateralFilter/src.bmp");
Mat dstImage;
bilateralFilter( srcImage, dstImage, 25, 25*2, 25/2 );
imwrite("M:/圖像處理實驗/bilateralFilter/dst.bmp", dstImage);
Public Shared Sub BilateralFilter(src As Emgu.CV.IInputArray, dst As Emgu.CV.IOutputArray, d As Integer, sigmaColor As Double, sigmaSpace As Double, Optional borderType As Emgu.CV.CvEnum.BorderType = Reflect101)
'對於彩色圖像,像素值的接近與否不能使用RGB空間值,雙邊濾波的原始文獻建議使用CIE顏色空間。
Dim img As Image(Of Gray, Byte) = New Image(Of Gray, Byte)("M:\圖像處理實驗\bilateralFilter\src.bmp")
CvInvoke.BilateralFilter(img, img, 7, 7 * 2, 7 / 2)
img.Save("M:\圖像處理實驗\bilateralFilter\src-result.bmp")