數字圖像處理(11): 圖像平滑 (均值濾波、中值濾波和高斯濾波)

目錄

1 圖像增強——圖像平滑

1.1 圖像增強簡介

1.2 圖像平滑

2 均值濾波

3 中值濾波

4 高斯濾波

參考資料


1 圖像增強——圖像平滑

1.1 圖像增強簡介

圖像增強是對圖像進行處理,使其比原始圖像更適合於特定的應用,它需要與實際應用相結合。對於圖像的某些特徵如邊緣、輪廓、對比度等,圖像增強是進行強調或銳化,以便於顯示、觀察或進一步分析與處理。圖像增強主要是一個主觀過程,而圖像復原大部分是一個客觀過程。圖像增強的方法是因應用不同而不同的,研究內容包括:

 

1.2 圖像平滑

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

圖像平滑 有均值濾波、方框濾波、中值濾波和高斯濾波等。下面將介紹常用的均值濾波、中值濾波和高斯濾波。

爲了實驗方便,首先給圖像加一點噪聲

 

代碼如下所示:

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

# 讀取圖片
img = cv2.imread("zxp.jpg", cv2.IMREAD_UNCHANGED)
img_noise=img

cv2.imshow("src", img)

rows, cols, chn = img_noise.shape


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


cv2.imshow("noise", img_noise)

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

#保存含噪聲圖像
cv2.imwrite("zxp_noise.jpg", img_noise)

 

運行結果如下圖所示:

 


2 均值濾波

均值濾波是指任意一點的像素值,都是周圍 N \times M 個像素值的均值。例如下圖中,紅色點的像素值是其周圍藍色背景區域像素值之和除25,25=5\times5 是藍色區域的大小。

 

均值濾波詳細的計算方法如下圖所示:

 

其中5\times5的矩陣稱爲,針對原始圖像內的像素點,採用核進行處理,得到結果圖像,如下圖所示:

 

 

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

Python調用OpenCV實現 均值濾波 的函數如下:

result = cv2.blur(原始圖像,核大小)
其中,核大小是以(寬度,高度)表示的元祖形式。常見的形式包括:核大小(3,3)和(5,5)。

                                                                                  K=\frac{1}{9}\times \left[ \begin{matrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \\ \end{matrix} \right]     

                                                                           K=\frac{1}{25}\times \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]

 

(1) 核大小爲 3\times3

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值濾波
result = cv2.blur(source, (3, 3)) #可以更改核的大小

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

 

運行結果如下圖所示:

 

(2) 核大小爲 5\times5

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值濾波
result = cv2.blur(source, (5, 5)) #可以更改核的大小

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

 

運行結果如下圖所示:

 

 

(2) 核大小爲 10\times10

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 均值濾波
result = cv2.blur(source, (10, 10)) #可以更改核的大小

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

 

運行結果如下圖所示:

 

注:

1)隨着核大小逐漸變大,會讓圖像變得更加模糊;

2)如果設置爲核大小爲(1,1),則結果就是原始圖像。

 


3 中值濾波

在使用鄰域平均法去噪的同時也使得邊界變得模糊。而中值濾波是非線性的圖像處理方法,在去噪的同時可以兼顧到邊界信息的保留。選一個含有奇數點的窗口W,將這個窗口在圖像上掃描,把窗口中所含的像素點按灰度級的升或降序排列,取位於中間的灰度值來代替該點的灰度值。計算過程如下圖所示:

 

Python調用OpenCV實現 中值濾波 的函數如下:

OpenCV主要調用 medianBlur() 函數實現中值濾波。圖像平滑裏中值濾波的效果最好。

dst = cv2.medianBlur(src, ksize)

其中,src表示源圖像,ksize表示核大小。核必須是大於1的奇數,如3、5、7等。

 

(1)核大小爲 3\times3

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')

# 中值濾波
result = cv2.medianBlur(img, 3)#可以更改核的大小

# 顯示圖像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

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

 

運行結果如下圖所示:

 

(2)核大小爲 5\times5

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')

# 中值濾波
result = cv2.medianBlur(img, 5) #可以更改核的大小

# 顯示圖像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

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

 

運行結果如下圖所示:

 

(3)核大小爲 7\times7

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')

# 中值濾波
result = cv2.medianBlur(img, 7) #可以更改核的大小

# 顯示圖像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)

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

 

運行結果如下圖所示:

 

注:

1)隨着核大小逐漸變大,會讓圖像變得更加模糊;

2)核必須是大於1的奇數,如3、5、7等;

3)在代碼 dst = cv2.medianBlur(src, ksize) 中 填寫核大小時,只需填寫一個數即可,如3、5、7等,對比均值濾波函數用法。

 


4 高斯濾波

爲了克服簡單局部平均法的弊端(圖像模糊),目前已提出許多保持邊緣、細節的局部平滑算法。它們的出發點都集中在如何選擇鄰域的大小、形狀和方向、參數加平均及鄰域各店的權重係數等。

圖像高斯平滑也是鄰域平均的思想對圖像進行平滑的一種方法,在圖像高斯平滑中,對圖像進行平均時,不同位置的像素被賦予了不同的權重。高斯平滑與簡單平滑不同,它在對鄰域內像素進行平均時,給予不同位置的像素不同的權值,下圖的所示的 3\times3 和 5\times5 鄰域的高斯模板。

(1)核大小爲 3\times3

                                                          \frac{1}{16}\times \left[ \begin{matrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \\ \end{matrix} \right]=\left[ \begin{matrix} {}^{1}\!\!\diagup\!\!{}_{16}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{16}\; \\ {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{4}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; \\ {}^{1}\!\!\diagup\!\!{}_{16}\; & {}^{1}\!\!\diagup\!\!{}_{8}\; & {}^{1}\!\!\diagup\!\!{}_{16}\; \\ \end{matrix} \right]

 

(1)核大小爲 5\times5

                                                              \frac{1}{273}\times \left[ \begin{matrix} 1 & 4 & 7 & 4 & 1 \\ 4 & 16 & 26 & 16 & 4 \\ 7 & 26 & 41 & 26 & 7 \\ 4 & 16 & 26 & 16 & 4 \\ 1 & 4 & 7 & 4 & 1 \\ \end{matrix} \right]

 

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

 

 

Python中OpenCV主要調用GaussianBlur函數,如下:

dst = cv2.GaussianBlur(src, ksize, sigmaX)

其中,src表示原始圖像,ksize表示核大小,sigmaX表示X方向方差。注:核大小(N, N)必須是奇數,X方向方差主要控制權重。

1)核大小爲 3\times3

                                                                    K=\left[ \begin{matrix} 0.05 & 0.1 & 0.05 \\ 0.1 & 0.4 & 0.1 \\ 0.05 & 0.1 & 0.05 \\ \end{matrix} \right]

2)核大小爲 5\times5

                                                                    K=\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]

 

(1)核大小爲 3\times3

代碼如下所示:


# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 高斯濾波
result = cv2.GaussianBlur(source, (3, 3), 0) #可以更改核大小

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

 

運行結果如下圖所示:

 

(2)核大小爲 5\times5

代碼如下所示:

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 讀取圖片
img = cv2.imread('zxp_noise.jpg')
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 高斯濾波
result = cv2.GaussianBlur(source, (5, 5), 0) #可以更改核大小

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

 

運行結果如下圖所示:

 

注:

1)隨着核大小逐漸變大,會讓圖像變得更加模糊;

2)核大小(N, N)必須是大於1的奇數,如3、5、7等;


 

參考資料

[1] https://blog.csdn.net/Eastmount/article/details/82216380

[2] Python+OpenCV圖像處理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章