OpenCV 中的濾波函數(shù)

blur

也稱為 box filter、均值濾波器澡为,就是簡單地將每個像素的值替換成鄰域平均值。

cv::blur(image, result, cv::Size(3,3));

如果用 kernel (也稱為 mask) 表示顶别,就是

boxFilter1.png

如果采用積分圖的方法拒啰,可以更快的計算這種 box filter 的結(jié)果。
在積分圖中谋旦,只需要三次加法運算,一次乘法運算即可册着,即通過積分圖,算出 kernel 內(nèi)部區(qū)域的像素和演熟,然后取平均。

積分圖

積分圖中每一點 (x,y)? 的值是原圖中對應(yīng)位置左上角區(qū)域所有值的和:
I(x,y) = \sum_{x'\le x \\ y'\le y}i(x',y')
積分圖的計算可以很高效:
I(x,y) = i(x,y) + I(x-1, y) + I(x,y-1) - I(x-1,y-1)

每次計算只需要新增一個像素值芒粹,其他值都是之前已經(jīng)計算出來的。
積分圖一旦計算出來化漆,對任意矩形區(qū)域內(nèi)像素和的計算都可以在常數(shù)時間(即計算時間固定,與區(qū)域的大小無關(guān))內(nèi)完成获三,例如:

integral.png

\sum_{A(x)<x'<C(x) \\ ~ A(y)<y'<C(y)} i(x', y') = I(C) -I(B) -I(D) + I(A)

GaussianBlur

在高斯濾波器中疙教,當(dāng)前像素值取鄰域的加權(quán)平均棺聊,離當(dāng)前像素越近贞谓,權(quán)重越大,權(quán)重服從高斯分布祟同。
在實際應(yīng)用中理疙,幾乎總是首選高斯濾波器晕城,很少直接用 box filter.

cv::GaussianBlur(image, result, cv::Size(5,5), 1.5); //最后的參數(shù)表示高斯分布的方差 sigma

上述命令中窖贤,最后兩個參數(shù) kernel size 和 ?\sigma 如果只設(shè)置一個,則另一個可以通過以下公式推出:
\sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8 \\ ksize = round(3 * \sigma * 2 + 1)

第二個式子很好理解滤蝠,就是借助高斯函數(shù)的性質(zhì)(距離均值 3 個標(biāo)準(zhǔn)差范圍內(nèi)的取值占總數(shù)的 99.7%)授嘀,因此窗口大小就是 3 倍的 ?\sigma *2 (兩邊)然后再加上 1 (自身)。
第一個式子與第二個非常近似蹄皱,但是又做了一些微調(diào)。

上述高斯濾波器內(nèi)部實際上是先調(diào)用如下函數(shù)巷折,產(chǎn)生服從高斯分布的一系列權(quán)重:

cv::getGaussianKernel(9, sigma, CV_32F); // 產(chǎn)生 9 個權(quán)重,與中心像素的距離依次為 -4晴弃,-3, ...3, 4

上述 9 個權(quán)重是經(jīng)過歸一化的,即和為 1上鞠,其公式為
k_i = \alpha \cdot e^{-\frac{(i-(ksize-1)/2)^2}{2\sigma ^2}}

其中 \alpha? 滿足歸一化的要求,ksize 必須是奇數(shù)世曾。如果要生成二維的高斯矩陣權(quán)重,則是先產(chǎn)生一個權(quán)重列向量轮听,然后令該列向量與自身的轉(zhuǎn)置相乘岭佳,得到高斯矩陣權(quán)重,最后再統(tǒng)一進(jìn)行歸一化珊随,保證矩陣所有元素和為 1。

另外叶洞,還可以分別產(chǎn)生兩個不同的高斯權(quán)重向量,對應(yīng)行和列方向上的高斯模糊權(quán)重螟炫,然后把它們相乘得到高斯矩陣艺晴。由于滿足這種分離的性質(zhì)昼钻,高斯濾波器被稱為可分離的濾波器财饥。

非線性濾波器:中值濾波器

前邊在進(jìn)行濾波操作時折晦,都只包含線性操作(算數(shù)平均、加權(quán)平均)满着。
另外還可以采用非線性操作,對應(yīng)非線性濾波器宁改。非線性濾波器不能表示成 kernel 矩陣卷積操作的形式魂莫。

中值濾波器是一種非線性濾波器还蹲。它把當(dāng)前像素和鄰域像素組成一個集合,排序之后潭兽,選擇中間值(即排序中間位置的數(shù)值)替換當(dāng)前像素值斗遏。

椒鹽噪聲:像素隨機替換成白色或者黑點。在通訊時诵次,如果部分像素值丟失,就會產(chǎn)生這種噪聲逾一。

中值濾波器可以有效的消除椒鹽噪聲,因為這些噪聲點在排序時很難成為中間值归敬,因此全都被剔除了鄙早。

Sobel 邊緣檢測濾波器

Sobel 也是線性濾波器汪茧,只不過采用了特殊的 kernel 矩陣:

sobel1.png

分別針對水平方向和垂直方向的操作舱污。

用上述 kernel 進(jìn)行操作,就是計算水平或者垂直方向像素值的差分扩灯,近似反映了像素值水平和垂直變化的速度霜瘪,合在一起就是圖像梯度的近似。

// 橫向的
cv::Sobel(image,  // 輸入
          sobelX, // 輸出
          CV_8U,  // 輸出數(shù)據(jù)類型
          1, 0,  // 采用第一個 kernel颖对,即計算 x 軸方向(橫向)像素變化率 
          3,  // kernel 的大小
          0.4, 128); // 縮放因子和偏移量

// 縱向的
cv::Sobel(image,  
          sobelY, 
          CV_8U,  
          0, 1,  // 采用第二個 kernel悔橄,即計算 y 軸方向(縱向)像素變化率 
          3, 
          0.4, 128); 

在默認(rèn)情況下自娩,差分運算的結(jié)果很可能超過 [0,255] 這個范圍,而且有正有負(fù)江解,應(yīng)該用 CV_16S 數(shù)據(jù)類型表示徙歼。經(jīng)過上述縮放和偏移之后犁河,才勉強適合用 CV_8U 表示,但還是需要飽和截斷操作耕魄。

cv::Sobel(image, sobelX, CV_16S, 1, 0);

在分別得到橫向彭谁、縱向變化率之后吸奴,可以整合起來計算梯度的大小

cv::Mat sobel;

sobel = abs(sobelX) + abs(sobelY); // 這里采用了 L1 范數(shù)

一般如果要顯示最后的 sobel 邊緣檢測的結(jié)果缠局,還需要把上述模值轉(zhuǎn)化到 [0,255] 范圍內(nèi)。

高斯導(dǎo)數(shù)

sobel 實際上包含了平滑和求導(dǎo)兩個操作读处,其中鄰域像素累加相當(dāng)于高斯平滑唱矛,距離越近的像素權(quán)重越高罚舱。
sobel 的 kernel size 可以選擇 1, 3, 5 和 7绎谦,其中 1 代表 1×3 或者 3×1,此時是沒有高斯平滑的包个。
對于大的 size,這種平滑更明顯碧囊。此時纤怒,sobel 不是高通濾波器,而是帶通濾波器泊窘,既消除了部分高頻,又消除了部分低頻州既。

其他梯度算子

與 Sobel 算子類似的還有其他幾個計算梯度的算子萝映,只是采用不同的 kernel.

  • Prewitt
    cv::Prewitt(image, prewittX, CV_16S, 1, 0);
    
prewitt1.png
  • Roberts
    cv::Roberts(image, robertsX, CV_16S, 1, 0);
    
roberts1.png
  • Scharr
    cv::Scharr(image, robertsX, CV_16S, 1, 0);
    
scharr1.png

上述所有的濾波器都是近似計算圖像函數(shù)的一階導(dǎo)數(shù)序臂,像素變化大的區(qū)域計算得到的值較大实束,平坦的區(qū)域計算值較小逊彭。

Laplacian 算子

sobel 算子通過對圖片函數(shù)求導(dǎo)咸灿,那些數(shù)值絕對值較高的點對應(yīng)了邊界區(qū)域:

laplacian1.jpg

如果繼續(xù)求二階導(dǎo)避矢,則導(dǎo)數(shù)較大的點對應(yīng)了過零點:

laplacian2.jpg

因此卸勺,也可以通過搜索二階導(dǎo)的過零點來檢測邊界點悟狱。

Laplacian 算子的定義
L[I(x,y)] = \frac{\partial ^2 I}{\partial x^2} + \frac{\partial ^2 I}{\partial y^2}

對照 Hessian 矩陣:
H[I(x,y)] = \begin{bmatrix} \frac{\partial^2 I} {\partial x^2} & \frac{\partial^2 I}{\partial x \partial y} \\ \frac{\partial^2 I}{\partial x \partial y} & \frac{\partial^2 I}{\partial y^2} \end{bmatrix}

Laplacian 算子實際上就是 Hessian 矩陣的 Trace富稻。
具體到圖像操作中,二階導(dǎo)有如下表達(dá)式:
\frac{\partial ^2 I} {\partial x^2} = [f(x+1,y)-f(x,y)]-[f(x,y)-f(x-1,y)] = f(x+1,y)+f(x-1,y)-2f(x,y) \\ \frac{\partial ^2 I}{\partial y^2} = [f(x,y+1)-f(x,y)]-[f(x,y)-f(x,y-1)] = f(x,y+1)+f(x,y-1)-2f(x,y)

所以最終 Laplacian 算子表達(dá)式為:
L[I(x,y)] = f(x+1,y)+f(x,y+1)+f(x-1,y)+f(x,y-1)-4f(x,y)

在具體實現(xiàn)中,可以用以下 kernel 進(jìn)行卷積操作:

laplacian1.png

Laplacian 算子具有旋轉(zhuǎn) 90 度不變性硼身,即一幅圖旋轉(zhuǎn) 90 度及其倍數(shù)营袜,對應(yīng)的 Laplacian 算子操作結(jié)果相同啸驯。
為了得到更好的旋轉(zhuǎn)不變性针姿,可以將 Laplacian 算子 kernel 擴展為如下形式:

laplacian2.png

這樣就具有了旋轉(zhuǎn) 45 度及其倍數(shù)的不變性。

cv::Laplacian(input, 
              output, 
              int ddepth,  // 元素類型筒饰,由于輸入的是CV_8U,為了避免數(shù)據(jù)溢出,一般設(shè)定為 CV_16S
              int ksize=1, // 求導(dǎo)數(shù)的 Sobel 算子的窗口大小帮孔,一般 ksize >1 奇數(shù)燎孟,如果取 ksize=1爆侣,則直接用上述 [1, -4, ...] kernel.
              double scale=1, // 是否對計算得到的值進(jìn)行放縮
              double delta, // 在存儲到 output 之前忍法,是否添加 bias
              int borderType); // 邊界像素插值方式,具體選項可以官網(wǎng)查看 https://docs.opencv.org/3.4/d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5
LoG (Laplacian of Gaussian)

Laplacian 算子對噪聲比較敏感羹蚣,因此一般在進(jìn)行 Laplacian 之前先進(jìn)行高斯平滑濾波。
兩個步驟合并稱為 LoG (Laplacian of Gaussian)咽弦。
在具體實現(xiàn)中,我們并不需要先高斯再拉普拉斯离唬,而是兩步并作一步:將拉普拉斯算子作用在高斯 kernel 上划鸽,得到新的 kernel输莺,再與 image 做卷積:
\triangledown ^2(f*g) = f*\triangledown^2g

最后作用在 (x,y) ? 位置上的卷積權(quán)重為
LoG(x,y) = -\frac{1}{\pi \sigma^4}\left[ 1-\frac{x^2+y^2}{2\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2} } \right]

同樣也是通過 \sigma? 設(shè)定濾波范圍嫂用。

對高斯函數(shù)取拉普拉斯算子操作是什么樣子的?

  • 一維形式
log1.png
  • 二維形式
log2.png

二維情況下得到的曲面很像“墨西哥草帽”嘱函。
\sigma? 的大小決定了檢測的粗粒度:

log3.png
DoG ( LoG 的近似)

Difference of Gaussians
為了減少 LoG 計算量埂蕊,用兩個不同 ?\sigma 的高斯做差疏唾,來近似 LoG

log4.png

上圖中兩個 \sigma? 的取值好像反了函似。。撇寞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔑担,一起剝皮案震驚了整個濱河市牌废,隨后出現(xiàn)的幾起案子啤握,更是在濱河造成了極大的恐慌,老刑警劉巖排抬,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異莫绣,居然都是意外死亡,警方通過查閱死者的電腦和手機对室,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門咖祭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人么翰,你說我怎么就攤上這事『葡樱” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵追迟,是天一觀的道長。 經(jīng)常有香客問我敦间,道長,這世上最難降的妖魔是什么廓块? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮带猴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浓利。我一直安慰自己钞速,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布苹威。 她就那樣靜靜地躺著,像睡著了一般牙甫。 火紅的嫁衣襯著肌膚如雪调违。 梳的紋絲不亂的頭發(fā)上窟哺,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天技肩,我揣著相機與錄音,去河邊找鬼虚婿。 笑死,一個胖子當(dāng)著我的面吹牛然痊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锹引,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼唆香,長吁一口氣:“原來是場噩夢啊……” “哼粤蝎!你這毒婦竟也來了袋马?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碑宴,失蹤者是張志新(化名)和其女友劉穎软啼,沒想到半個月后延柠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡贞间,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了整以。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡公黑,死狀恐怖摄咆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吭从,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布涩金,位于F島的核電站,受9級特大地震影響鸭廷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辆床,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轿秧。 院中可真熱鬧,春花似錦菇篡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽议蟆。三九已至,卻和暖如春咐容,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戳粒。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奄妨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓展蒂,卻偏偏與公主長得像苔咪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子团赏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容