作者 | 楊秀璋,責編 | 夕顏
頭圖 | CSDN付費下載自視覺中國
出品 | CSDN博客
本篇文章主要講解Python調用OpenCV實現圖像平滑,包括四個算法:均值濾波、方框濾波、高斯濾波和中值濾波。全文均是基礎知識,希望對您有所幫助。知識點如下:
1.圖像平滑
2.均值濾波
3.方框濾波
4.高斯濾波
5.中值濾波
PS:本文介紹圖像平滑,想讓大家先看看圖像處理的效果,后面還會補充一些基礎知識供大家學習。文章參考自己的博客及網易云課堂李大洋老師的講解,強烈推薦大家學習。
圖像平滑
1.圖像增強
圖像增強是對圖像進行處理,使其比原始圖像更適合于特定的應用,它需要與實際應用相結合。對于圖像的某些特征如邊緣、輪廓、對比度等,圖像增強是進行強調或銳化,以便于顯示、觀察或進一步分析與處理。圖像增強的方法是因應用不同而不同的,研究內容包括:(參考課件和左飛的《數字圖像處理》)
2.圖像平滑
圖像平滑是一種區域增強的算法,平滑算法有鄰域平均法、中指濾波、邊界保持類濾波等。在圖像產生、傳輸和復制過程中,常常會因為多方面原因而被噪聲干擾或出現數據丟失,降低了圖像的質量(某一像素,如果它與周圍像素點相比有明顯的不同,則該點被噪聲所感染)。這就需要對圖像進行一定的增強處理以減小這些缺陷帶來的影響。
簡單平滑-鄰域平均法
3.鄰域平均法
圖像簡單平滑是指通過鄰域簡單平均對圖像進行平滑處理的方法,用這種方法在一定程度上消除原始圖像中的噪聲、降低原始圖像對比度的作用。它利用卷積運算對圖像鄰域的像素灰度進行平均,從而達到減小圖像中噪聲影響、降低圖像對比度的目的。
但鄰域平均值主要缺點是在降低噪聲的同時使圖像變得模糊,特別在邊緣和細節處,而且鄰域越大,在去噪能力增強的同時模糊程度越嚴重。
首先給出為圖像增加噪聲的代碼。
# -*- 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
輸出結果如下所示:
均值濾波
1.原理
均值濾波是指任意一點的像素值,都是周圍N*M個像素值的均值。例如下圖中,紅色點的像素值為藍色背景區域像素值之和除25。
其中紅色區域的像素值均值濾波處理過程為:((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的矩陣稱為核,針對原始圖像內的像素點,采用核進行處理,得到結果圖像。
提取1/25可以將核轉換為如下形式:
2.代碼
Python調用OpenCV實現均值濾波的核心函數如下:
result = cv2.blur(原始圖像,核大小)
其中,核大小是以(寬度,高度)表示的元祖形式。常見的形式包括:核大小(3,3)和(5,5)。
代碼如下所示:
#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
輸出結果如下圖所示:
核設置為(10,10)和(20,20)會讓圖像變得更加模糊。
如果設置為(1,1)處理結果就是原圖,核中每個權重值相同,稱為均值。
方框濾波
方框濾波和均值濾波核基本一致,區別是需不需要均一化處理。OpenCV調用boxFilter函數實現方框濾波。函數如下:
result = cv2.boxFilter(原始圖像, 目標圖像深度, 核大小, normalize屬性)
其中,目標圖像深度是int類型,通常用“-1”表示與原始圖像一致;核大小主要包括(3,3)和(5,5),如下所示。
normalize屬性表示是否對目標圖像進行歸一化處理。當normalize為true時需要執行均值化處理,當normalize為false時,不進行均值化處理,實際上為求周圍各像素的和,很容易發生溢出,溢出時均為白色,對應像素值為255。
在圖像簡單平滑中,算法利用卷積模板逐一處理圖像中每個像素,這一過程可以形象地比作對原始圖像的像素一一進行過濾整理,在圖像處理中把鄰域像素逐一處理的算法過程稱為濾波器。平滑線性濾波器的工作原理是利用模板對鄰域內像素灰度進行加權平均,也稱為均值濾波器。
代碼如下所示:
#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表示進行歸一化處理,此時與均值濾波相同,輸出結果如下圖所示:
下面是圖像左上角處理前后的像素結果:
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
輸出結果如下圖所示:
上圖很多像素為白色,因為圖像求和結果幾乎都是255。如果設置的是2*2矩陣,只取四個像素結果要好些。
result = cv2.boxFilter(source, -1, (2,2), normalize=0)
高斯濾波
為了克服簡單局部平均法的弊端(圖像模糊),目前已提出許多保持邊緣、細節的局部平滑算法。它們的出發點都集中在如何選擇鄰域的大小、形狀和方向、參數加平均及鄰域各店的權重系數等。
圖像高斯平滑也是鄰域平均的思想對圖像進行平滑的一種方法,在圖像高斯平滑中,對圖像進行平均時,不同位置的像素被賦予了不同的權重。高斯平滑與簡單平滑不同,它在對鄰域內像素進行平均時,給予不同位置的像素不同的權值,下圖的所示的 3 * 3 和 5 * 5 領域的高斯模板。
高斯濾波讓臨近的像素具有更高的重要度,對周圍像素計算加權平均值,較近的像素具有較大的權重值。如下圖所示,中心位置權重最高為0.4。
Python中OpenCV主要調用GaussianBlur函數,如下:
dst = cv2.GaussianBlur(src, ksize, sigmaX)
其中,src表示原始圖像,ksize表示核大小,sigmaX表示X方向方差。注意,核大小(N, N)必須是奇數,X方向方差主要控制權重。
代碼如下:
#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
輸出結果如下所示:
如果使用15*15的核,則圖形將更加模糊。
中值濾波
1.概念
在使用鄰域平均法去噪的同時也使得邊界變得模糊。而中值濾波是非線性的圖像處理方法,在去噪的同時可以兼顧到邊界信息的保留。選一個含有奇數點的窗口W,將這個窗口在圖像上掃描,把窗口中所含的像素點按灰度級的升或降序排列,取位于中間的灰度值來代替該點的灰度值。例如選擇濾波的窗口如下圖,是一個一維的窗口,待處理像素的灰度取這個模板中灰度的中值,濾波過程如下:
如下圖所示,將臨近像素按照大小排列,取排序像素中位于中間位置的值作為中值濾波的像素值。
2.代碼
OpenCV主要調用medianBlur函數實現中值濾波。圖像平滑里中值濾波的效果最好。
dst = cv2.medianBlur(src, ksize)
其中,src表示源文件,ksize表示核大小。核必須是大于1的奇數,如3、5、7等。
代碼如下所示:
#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
輸出結果如下圖所示:
常用的窗口還有方形、十字形、圓形和環形。不同形狀的窗口產生不同的濾波效果,方形和圓形窗口適合外輪廓線較長的物體圖像,而十字形窗口對有尖頂角狀的圖像效果好。中值濾波對于消除孤立點和線段的干擾十分有用,尤其是對于二進噪聲,但對消除高斯噪聲的影響效果不佳。對于一些細節較多的復雜圖像,可以多次使用不同的中值濾波。
希望文章對大家有所幫助,如果有錯誤或不足之處,還請海涵。
版權聲明:本文為CSDN博主「Eastmount」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:
https://blog.csdn.net/Eastmount/article/details/82216380