[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

Eastmount發表於2018-09-02

該系列文章是講解Python OpenCV影象處理知識,前期主要講解影象入門、OpenCV基礎用法,中期講解影象處理的各種演算法,包括影象銳化運算元、影象增強技術、影象分割等,後期結合深度學習研究影象識別、影象分類應用。希望文章對您有所幫助,如果有不足之處,還請海涵~

同時推薦作者的C++影象系列知識:
[數字影象處理] 一.MFC詳解顯示BMP格式圖片
[數字影象處理] 二.MFC單文件分割視窗顯示圖片
[數字影象處理] 三.MFC實現影象灰度、取樣和量化功能詳解
[數字影象處理] 四.MFC對話方塊繪製灰度直方圖
[數字影象處理] 五.MFC影象點運算之灰度線性變化、灰度非線性變化、閾值化和均衡化處理詳解
[數字影象處理] 六.MFC空間幾何變換之影象平移、映象、旋轉、縮放詳解
[數字影象處理] 七.MFC影象增強之影象普通平滑、高斯平滑、Laplacian、Sobel、Prewitt銳化詳解

前文參考:
[Python影象處理] 一.影象處理基礎知識及OpenCV入門函式
[Python影象處理] 二.OpenCV+Numpy庫讀取與修改畫素
[Python影象處理] 三.獲取影象屬性、興趣ROI區域及通道處理

本篇文章主要講解Python呼叫OpenCV實現影象平滑,包括四個演算法:均值濾波、方框濾波、高斯濾波和中值濾波。全文均是基礎知識,希望對您有所幫助。知識點如下:
1.影象平滑
2.均值濾波
3.方框濾波
4.高斯濾波
5.中值濾波

PS:本文介紹影象平滑,想讓大家先看看影象處理的效果,後面還會補充一些基礎知識供大家學習。文章參考自己的部落格及網易雲課堂李大洋老師的講解,強烈推薦大家學習。

PSS:2019年1~2月作者參加了CSDN2018年部落格評選,希望您能投出寶貴的一票。我是59號,Eastmount,楊秀璋。投票地址:https://bss.csdn.net/m/topic/blog_star2018/index

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波
五年來寫了314篇部落格,12個專欄,是真的熱愛分享,熱愛CSDN這個平臺,也想幫助更多的人,專欄包括Python、資料探勘、網路爬蟲、影象處理、C#、Android等。現在也當了兩年老師,更是覺得有義務教好每一個學生,讓貴州學子好好寫點程式碼,學點技術,"師者,傳到授業解惑也",提前祝大家新年快樂。2019我們攜手共進,為愛而生。

一.影象平滑

1.影象增強
影象增強是對影象進行處理,使其比原始影象更適合於特定的應用,它需要與實際應用相結合。對於影象的某些特徵如邊緣、輪廓、對比度等,影象增強是進行強調或銳化,以便於顯示、觀察或進一步分析與處理。影象增強的方法是因應用不同而不同的,研究內容包括:(參考課件和左飛的《數字影象處理》)

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

2.影象平滑
影象平滑是一種區域增強的演算法,平滑演算法有鄰域平均法、中指濾波、邊界保持類濾波等。在影象產生、傳輸和複製過程中,常常會因為多方面原因而被噪聲干擾或出現資料丟失,降低了影象的質量(某一畫素,如果它與周圍畫素點相比有明顯的不同,則該點被噪聲所感染)。這就需要對影象進行一定的增強處理以減小這些缺陷帶來的影響。
簡單平滑-鄰域平均法

3.鄰域平均法
影象簡單平滑是指通過鄰域簡單平均對影象進行平滑處理的方法,用這種方法在一定程度上消除原始影象中的噪聲、降低原始影象對比度的作用。它利用卷積運算對影象鄰域的畫素灰度進行平均,從而達到減小影象中噪聲影響、降低影象對比度的目的。
但鄰域平均值主要缺點是在降低噪聲的同時使影象變得模糊,特別在邊緣和細節處,而且鄰域越大,在去噪能力增強的同時模糊程度越嚴重。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

首先給出為影象增加噪聲的程式碼。

# -*- coding:utf-8 -*-
import cv2
import numpy as np

#讀取圖片
img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape

#加噪聲
for i in range(5000):    
    x = np.random.randint(0, rows) 
    y = np.random.randint(0, cols)    
    img[x,y,:] = 255

cv2.imshow("noise", img)
           
#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波


二.均值濾波

1.原理
均值濾波是指任意一點的畫素值,都是周圍N*M個畫素值的均值。例如下圖中,紅色點的畫素值為藍色背景區域畫素值之和除25。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波
其中紅色區域的畫素值均值濾波處理過程為: ((197+25+106+156+159)+ (149+40+107+5+71)+ (163+198+**226**+223+156)+ (222+37+68+193+157)+ (42+72+250+41+75)) / 25

其中5*5的矩陣稱為核,針對原始影象內的畫素點,採用核進行處理,得到結果影象。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

提取1/25可以將核轉換為如下形式:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

2.程式碼
Python呼叫OpenCV實現均值濾波的核心函式如下:
result = cv2.blur(原始影象,核大小)
其中,核大小是以(寬度,高度)表示的元祖形式。常見的形式包括:核大小(3,3)和(5,5)。
(1)K=19[111111111] K=\frac{1}{9}\left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{matrix} \right] \tag{1}
(2)K=125[1111111111111111111111111] K=\frac{1}{25}\left[ \begin{matrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ \end{matrix} \right] \tag{2}

程式碼如下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
img = cv2.imread('test01.png')
source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
 
#均值濾波
result = cv2.blur(source, (5,5))
 
#顯示圖形
titles = ['Source Image', 'Blur Image']  
images = [source, result]  
for i in xrange(2):  
   plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()  

輸出結果如下圖所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

核設定為(10,10)和(20,20)會讓影象變得更加模糊。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

如果設定為(1,1)處理結果就是原圖,核中每個權重值相同,稱為均值。



三.方框濾波

方框濾波和均值濾波核基本一致,區別是需不需要均一化處理。OpenCV呼叫boxFilter()函式實現方框濾波。函式如下:
result = cv2.boxFilter(原始影象, 目標影象深度, 核大小, normalize屬性)
其中,目標影象深度是int型別,通常用“-1”表示與原始影象一直;核大小主要包括(3,3)和(5,5),如下所示。

(3)K=19[111111111] K=\frac{1}{9}\left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{matrix} \right] \tag{3}
(4)K=125[1111111111111111111111111] K=\frac{1}{25}\left[ \begin{matrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ \end{matrix} \right] \tag{4}

normalize屬性表示是否對目標影象進行歸一化處理。當normalize為true時需要執行均值化處理,當normalize為false時,不進行均值化處理,實際上為求周圍各畫素的和,很容易發生溢位,溢位時均為白色,對應畫素值為255。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

在影象簡單平滑中,演算法利用卷積模板逐一處理影象中每個畫素,這一過程可以形象地比作對原始影象的畫素一一進行過濾整理,在影象處理中把鄰域畫素逐一處理的演算法過程稱為濾波器。平滑線性濾波器的工作原理是利用模板對鄰域內畫素灰度進行加權平均,也稱為均值濾波器。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

程式碼如下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
img = cv2.imread('test01.png')
source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
 
#方框濾波
result = cv2.boxFilter(source, -1, (5,5), normalize=1)
 
#顯示圖形
titles = ['Source Image', 'BoxFilter Image']  
images = [source, result]  
for i in xrange(2):  
   plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()  

程式碼中使用5*5的核,normalize=1表示進行歸一化處理,此時與均值濾波相同,輸出結果如下圖所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

下面是影象左上角處理前後的畫素結果:

print(source[0:3, 0:3, 0])
#[[115 180 106]
# [ 83 152  72]
# [ 55  58  55]]
print(result[0:3, 0:3, 0])
#[[92 90 78]
# [92 89 77]
# [82 80 72]]

如果省略引數normalize,則預設是進行歸一化處理。如果normalize=0則不進行歸一化處理,畫素值為周圍畫素之和,影象更多為白色。

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
img = cv2.imread('test01.png')
source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
 
#方框濾波
result = cv2.boxFilter(source, -1, (5,5), normalize=0)
 
#顯示圖形
titles = ['Source Image', 'BoxFilter Image']  
images = [source, result]  
for i in xrange(2):  
   plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show() 

輸出結果如下圖所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

上圖很多畫素為白色,因為影象求和結果幾乎都是255。如果設定的是2*2矩陣,只取四個畫素結果要好些。
result = cv2.boxFilter(source, -1, (2,2), normalize=0)

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波


四.高斯濾波

為了克服簡單區域性平均法的弊端(影象模糊),目前已提出許多保持邊緣、細節的區域性平滑演算法。它們的出發點都集中在如何選擇鄰域的大小、形狀和方向、引數加平均及鄰域各店的權重係數等。
影象高斯平滑也是鄰域平均的思想對影象進行平滑的一種方法,在影象高斯平滑中,對影象進行平均時,不同位置的畫素被賦予了不同的權重。高斯平滑與簡單平滑不同,它在對鄰域內畫素進行平均時,給予不同位置的畫素不同的權值,下圖的所示的 3 * 3 和 5 * 5 領域的高斯模板。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

高斯濾波讓臨近的畫素具有更高的重要度,對周圍畫素計算加權平均值,較近的畫素具有較大的權重值。如下圖所示,中心位置權重最高為0.4。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波
[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

Python中OpenCV主要呼叫GaussianBlur函式,如下:
dst = cv2.GaussianBlur(src, ksize, sigmaX)
其中,src表示原始影象,ksize表示核大小,sigmaX表示X方向方差。注意,核大小(N, N)必須是奇數,X方向方差主要控制權重。

(5)K(3,3)=[0.050.10.050.10.40.10.050.10.05] K(3,3)=\left[ \begin{matrix} 0.05 & 0.1 & 0.05 \\ 0.1 & 0.4 & 0.1 \\ 0.05 & 0.1 & 0.05 \end{matrix} \right] \tag{5}
(4)K(5,5)=[1121113431248421343111211] K(5,5)=\left[ \begin{matrix} 1 & 1 & 2 & 1 & 1 \\ 1 & 3 & 4 & 3 & 1 \\ 2 & 4 & 8 & 4 & 2 \\ 1 & 3 & 4 & 3 & 1 \\ 1 & 1 & 2 & 1 & 1 \\ \end{matrix} \right] \tag{4}

程式碼如下:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
img = cv2.imread('test01.png')
source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
 
#高斯濾波
result = cv2.GaussianBlur(source, (3,3), 0)

#顯示圖形
titles = ['Source Image', 'GaussianBlur Image']  
images = [source, result]  
for i in xrange(2):  
   plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')  
   plt.title(titles[i])  
   plt.xticks([]),plt.yticks([])  
plt.show()  

輸出結果如下所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

如果使用15*15的核,則圖形將更加模糊。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波


五.中值濾波

1.概念
在使用鄰域平均法去噪的同時也使得邊界變得模糊。而中值濾波是非線性的影象處理方法,在去噪的同時可以兼顧到邊界資訊的保留。選一個含有奇數點的視窗W,將這個視窗在影象上掃描,把視窗中所含的畫素點按灰度級的升或降序排列,取位於中間的灰度值來代替該點的灰度值。 例如選擇濾波的視窗如下圖,是一個一維的視窗,待處理畫素的灰度取這個模板中灰度的中值,濾波過程如下:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

如下圖所示,將臨近畫素按照大小排列,取排序畫素中位於中間位置的值作為中值濾波的畫素值。

2.程式碼
OpenCV主要呼叫medianBlur()函式實現中值濾波。影象平滑裡中值濾波的效果最好。
dst = cv2.medianBlur(src, ksize)
其中,src表示原始檔,ksize表示核大小。核必須是大於1的奇數,如3、5、7等。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

程式碼如下所示:

#encoding:utf-8
import cv2  
import numpy as np  
import matplotlib.pyplot as plt
 
#讀取圖片
img = cv2.imread('test01.png')
 
#高斯濾波
result = cv2.medianBlur(img, 3)

#顯示影象
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

#等待顯示
cv2.waitKey(0)
cv2.destroyAllWindows()

輸出結果如下圖所示:

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

常用的視窗還有方形、十字形、圓形和環形。不同形狀的視窗產生不同的濾波效果,方形和圓形視窗適合外輪廓線較長的物體影象,而十字形視窗對有尖頂角狀的影象效果好。中值濾波對於消除孤立點和線段的干擾十分有用,尤其是對於二進噪聲,但對消除高斯噪聲的影響效果不佳。對於一些細節較多的複雜影象,可以多次使用不同的中值濾波。

[Python影象處理] 四.影象平滑之均值濾波、方框濾波、高斯濾波及中值濾波

希望文章對大家有所幫助,如果有錯誤或不足之處,還請海涵。
(By:Eastmount 2018-09-01 早8點 https://blog.csdn.net/Eastmount/)

相關文章