本節(jié)主要記錄OpenCV 兩類五種常見的濾波方式:
線性濾波:方框濾波、均值濾波、高斯濾波
非線性濾波: 中值濾波、雙邊濾波
文章首先概括各種濾波方式的特點以及用法,最后給出相應(yīng)的效果及demo;
濾波的目的:
濾波的目的有兩個即:1.抽出對象的特征作為圖像識別的特征模式;2.為適應(yīng)圖像處理要求,消除數(shù)字圖像所混入的噪聲 .
對圖像濾波有兩個要求:1.不能損壞圖像的輪廓和邊緣等重要信息;2.使圖像清晰視覺效果更好.
為了進行圖像平滑操作,通常在圖像上加一個濾波器(filter),最常見的類型是線性的,輸出像素值(g(i, j))最終由原像素值和加權(quán)值決定。其公式如下:
其中h(k, l)被稱為核(kernel),是加到圖像上濾波器(filter)的系數(shù);
一.方框濾波BoxBlur:
這是所有濾波器中最簡單的一種濾波方式。每一個輸出像素的是內(nèi)核鄰域像素值的平均值得到。 也就意味著濾波核越大,濾波結(jié)果圖像越平滑,也就越模糊;
通用的濾波kernel如下:
這里是一個長寬分別為Kwidth和Kheight的窗口函數(shù),在此區(qū)域內(nèi)鄰域中像素值疊加求平均即可求出位于kernel中心點像素的像素值。opencv中提供了方框濾波函數(shù)boxFilter()
/! smooths the image using the box filter. Each pixel is processed in O(1) time
CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth,
Size ksize, Point anchor=Point(-1,-1),
bool normalize=true,
int borderType=BORDER_DEFAULT );
其中:
- InputArray src: 輸入圖像,可以是Mat類型 ;
- OutputArray dst: 經(jīng)濾波后輸出圖像 ;
- int ddepth: 目標(biāo)圖像的深度,若設(shè)置為-1,則深度與原圖像深度相同 ;
- Size ksize: Size類型,內(nèi)核的大小,一般用Size(w, h)表示,如Size(3, 3);
- Point anchor:默認(rèn)值為 Point(-1,-1), 標(biāo)記進行濾波操作的點,如果是默認(rèn)值(-1, -1)說明對上述窗口中心點所對應(yīng)的像素點進行操作 ;
- bool normalize: 默認(rèn)值true,標(biāo)記內(nèi)核是否被歸一化處理,所謂歸一化,簡單說就是將結(jié)果控制在摸個范圍之內(nèi);
- int borderType:默認(rèn)值BORDER_DEFAULT,用于推斷圖像外部像素的某種便捷模式;
二.均值濾波 blur:
理解了方框濾波,再看均值濾波也就比較簡單了,在方框濾波當(dāng)中,若 normalize = false即為均值濾波;OpenCV對應(yīng)函數(shù):
//! a synonym for normalized box filter
CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT );
其中:
- InputArray src:
- OutputArray dst:
- Size ksize:
- Point anchor=Point(-1,-1):
- int borderType=BORDER_DEFAULT :
參數(shù)均與方框濾波含義相同;
三.高斯濾波GaussianBlur()
高斯濾波是一種線性平滑濾波,對于除去高斯噪聲(概率分布服從正態(tài)分布)有很好的效果。高斯濾波被形容為”Probably the most useful filter”,同時也指出高斯濾波并不是效率最高的濾波算法;高斯濾波是通過對輸入數(shù)組的每個點與輸入的高斯濾波模板執(zhí)行卷積計算然后將這些結(jié)果一塊組成了濾波后的輸出數(shù)組,通俗的講就是高斯濾波是對整幅圖像進行加權(quán)平均的過程,每一個像素點的值都由其本身和鄰域內(nèi)的其他像素值經(jīng)過加權(quán)平均后得到。高斯濾波的具體操作是:用一個模板(或稱卷積、掩模)掃描圖像中的每一個像素,用模板確定的鄰域內(nèi)像素的加權(quán)平均灰度值去替代模板中心像素點的值。
高斯濾波和高斯模糊:高斯濾波和高斯模糊并非同一概念,二者的區(qū)別主要在于所采用的濾波器是高通還是低通;比如低通濾波器,像素能量低的通過,而對于像素能量高的部分將會采取加權(quán)平均的方法重新計算像素的值,將能量像素的值編程能量較低的值,我們知道對于圖像而言其高頻部分展現(xiàn)圖像細(xì)節(jié),所以經(jīng)過低通濾波器之后整幅圖像變成低頻造成圖像模糊,這就被稱為高斯模糊;相反高通濾波是允許高頻通過而過濾掉低頻,這樣將低頻像素進行銳化操作,圖像變的更加清晰,被稱為高斯濾波;
簡單說:高斯濾波是指用高斯函數(shù)作為濾波函數(shù)的濾波操作而高斯模糊是用高斯低通濾波器。
高斯函數(shù)如下:
OpenCV對應(yīng)函數(shù)如下:
//! smooths the image using Gaussian filter.
CV_EXPORTS_W void GaussianBlur( InputArray src,
OutputArray dst, Size ksize,
double sigmaX, double sigmaY=0,
int borderType=BORDER_DEFAULT );
其中:
InputArray src:
OutputArray dst:輸出圖像,與輸入圖像有相同的類型和尺寸。
Size ksize: 高斯內(nèi)核大小,這個尺寸與前面兩個濾波kernel尺寸不同,ksize.width和ksize.height可以不相同但是這兩個值必須為正奇數(shù),如果這兩個值為0,他們的值將由sigma計算。
double sigmaX: 高斯核函數(shù)在X方向上的標(biāo)準(zhǔn)偏差
double sigmaY=0:高斯核函數(shù)在Y方向上的標(biāo)準(zhǔn)偏差,如果sigmaY是0,則函數(shù)會自動將sigmaY的值設(shè)置為與sigmaX相同的值,如果sigmaX和sigmaY都是0,這兩個值將由ksize.width和ksize.height計算而來。具體可以參考getGaussianKernel()函數(shù)查看具體細(xì)節(jié)。建議將size、sigmaX和sigmaY都指定出來。
int borderType=BORDER_DEFAULT : 有默認(rèn)值BORDER_DEFAULT,如果沒有特殊需要不用更改,具體可以參考borderInterpolate()函數(shù)。
四.中值濾波medianBlur()
中值濾波是一種典型的非線性濾波,是基于排序統(tǒng)計理論的一種能夠有效抑制噪聲的非線性信號處理技術(shù),基本思想是用像素點鄰域灰度值的中值來代替該像素點的灰度值,讓周圍的像素值接近真實的值從而消除孤立的噪聲點。該方法在取出脈沖噪聲、椒鹽噪聲(二值圖像上表現(xiàn)為使一些像素點變白,一些像素點變黑)的同時能保留圖像的邊緣細(xì)節(jié)。這些優(yōu)良特性是線性濾波所不具備的。
中值濾波首先也得生成一個濾波模板,將該模板內(nèi)的各像素值進行排序,生成單調(diào)上升或單調(diào)下降的二維數(shù)據(jù)序列,二維中值濾波輸出為g(x, y)=medf{f(x-k, y-l),(k, l∈w)}
,其中f(x,y)
和g(x,y)
分別是原圖像和處理后圖像, w為輸入的二維模板,能夠在整幅圖像上滑動,通常尺寸為3 * 3或5 * 5區(qū)域,也可以是不同的形狀如線狀、圓形、十字形、圓環(huán)形等。通過從圖像中的二維模板取出奇數(shù)個數(shù)據(jù)進行排序,用排序后的中值取代要處理的數(shù)據(jù)即可。
中值濾波對消除椒鹽噪聲非常有效,能夠克服線性濾波器帶來的圖像細(xì)節(jié)模糊等弊端,能夠有效保護圖像邊緣信息,是非常經(jīng)典的平滑噪聲處理方法。在光學(xué)測量條紋圖像的相位分析處理方法中有特殊作用,但在條紋中心分析方法中作用不大。
OpenCV對應(yīng)函數(shù)如下:
//! smooths the image using median filter.
CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );
其中:
- InputArray src: 輸入圖像,圖像為1、3、4通道的圖像,當(dāng)模板尺寸為3或5時,圖像深度只能為CV_8U、CV_16U、CV_32F中的一個,如而對于較大孔徑尺寸的圖片,圖像深度只能是CV_8U;
- OutputArray dst:輸出圖像,尺寸和類型與輸入圖像一致,可以使用Mat::Clone以原圖像為模板來初始化輸出圖像dst ;
- int ksize:濾波模板的尺寸大小,必須是大于1的奇數(shù)
五.雙邊濾波bilateralFilter()
雙邊濾波是一種非線性的濾波方法,是結(jié)合圖像的空間鄰近度和像素值相似度的一種折衷處理,同時考慮空間與信息和灰度相似性,達到保邊去噪的目的,具有簡單、非迭代、局部處理的特點。之所以能夠達到保邊去噪的濾波效果是因為濾波器由兩個函數(shù)構(gòu)成:一個函數(shù)是由幾何空間距離決定濾波器系數(shù),另一個是由像素差值決定濾波器系數(shù)。
雙邊濾波器中,輸出像素的值依賴于鄰域像素的值的加權(quán)組合,其公式如下:
權(quán)重系數(shù)w(i,j,k,l)取決于定義域核
[站外圖片上傳中...(image-bf88e3-1515383334366)]
和值域核
的乘積,也就是
通俗來講就是雙邊濾波模板主要有兩個模板生成,第一個是高斯模板,第二個是以灰度級的差值作為函數(shù)系數(shù)生成的模板,然后這兩個模板點乘就得到了最終的雙邊濾波模板,第一個模板是全局模板,所以只需要生成以西,第二個模板需要對每個像素都計算一次。雙邊濾波器比高斯濾波器多了一個高斯方差sigma-d,它是基于空間分布的高斯濾波函數(shù),所以在邊緣附近,離的較遠(yuǎn)的像素不會太多影響到邊緣上的像素,這樣就能對邊緣附近的像素值予以保存,但是由于保存過多的高頻信息,對于彩色圖像里的高頻噪聲,雙邊濾波器不能夠干凈的濾掉,只能夠?qū)τ诘皖l信息進行較好的濾除。
OpenCV中函數(shù)如下:
//! smooths the image using bilateral filter
CV_EXPORTS_W void bilateralFilter( InputArray src,
OutputArray dst, int d,
double sigmaColor, double sigmaSpace,
int borderType=BORDER_DEFAULT );
其中:
- InputArray src:輸入圖像,可以是Mat類型,圖像必須是8位或浮點型單通道、三通道的圖像。
- OutputArray dst:輸出圖像,和原圖像有相同的尺寸和類型。
- int d:表示在過濾過程中每個像素鄰域的直徑范圍。如果這個值是非正數(shù),則函數(shù)會從第五個參數(shù)sigmaSpace計算該值。
- double sigmaColor:顏色空間過濾器的sigma值,這個參數(shù)的值越大,表明該像素鄰域內(nèi)有越寬廣的顏色會被混合到一起,產(chǎn)生較大的半相等顏色區(qū)域。
- double sigmaSpace:坐標(biāo)空間中濾波器的sigma值,如果該值較大,則意味著顏色相近的較遠(yuǎn)的像素將相互影響,從而使更大的區(qū)域中足夠相似的顏色獲取相同的顏色。當(dāng)d>0時,d指定了鄰域大小且與sigmaSpace無關(guān),否則d正比于sigmaSpace.
- int borderType=BORDER_DEFAULT:
另一種形態(tài):
//! smooths the image using adaptive bilateral filter
CV_EXPORTS_W void adaptiveBilateralFilter( InputArray src,
OutputArray dst, Size ksize,
double sigmaSpace, double maxSigmaColor = 20.0, Point anchor=Point(-1, -1),
int borderType=BORDER_DEFAULT );
雙邊濾波器可以很好的保存圖像邊緣細(xì)節(jié)而濾除掉低頻分量的噪音,但是雙邊濾波器的效率不是太高,花費的時間相較于其他濾波器而言也比較長。
對于簡單的濾波而言,可以將兩個sigma值設(shè)置成相同的值,如果值<10,則對濾波器影響很小,如果值>150則會對濾波器產(chǎn)生較大的影響,會使圖片看起來像卡通。