
學習模糊/平滑圖像,消除噪點。圖檔等可到源碼處下載下傳。
1、目标
2、教程
濾波與模糊
推薦大家先閱讀:番外篇:卷積基礎(圖檔邊框),有助于了解卷積和濾波的概念。
關于濾波和模糊,很多人分不清,我來給大家理理(雖說如此,我後面也會混着用,,ԾㅂԾ,,):
它們都屬于卷積,不同濾波方法之間隻是卷積核不同(對線性濾波而言)
低通濾波器是模糊,高通濾波器是銳化
低通濾波器就是允許低頻信号通過,在圖像中邊緣和噪點都相當于高頻部分,是以低通濾波器用于去除噪點、平滑和模糊圖像。高通濾波器則反之,用來增強圖像邊緣,進行銳化處理。
常見噪聲有椒鹽噪聲和高斯噪聲,椒鹽噪聲可以了解為斑點,随機出現在圖像中的黑點或白點;高斯噪聲可以了解為拍攝圖檔時由于光照等原因造成的噪聲。
均值濾波
均值濾波是一種最簡單的濾波處理,它取的是卷積核區域内元素的均值,用cv2.blur()實作,如3×3的卷積核:
img = cv2.imread('lena.jpg')
blur = cv2.blur(img, (3, 3)) # 均值模糊
所有的濾波函數都有一個可選參數borderType,這個參數就是番外篇:卷積基礎(圖檔邊框)中所說的邊框填充方式。
方框濾波
方框濾波跟均值濾波很像,如3×3的濾波核如下:
用cv2.boxFilter()函數實作,當可選參數normalize為True的時候,方框濾波就是均值濾波,上式中的a就等于1/9;normalize為False的時候,a=1,相當于求區域内的像素和。
# 前面的均值濾波也可以用方框濾波實作:normalize=True
blur = cv2.boxFilter(img, -1, (3, 3), normalize=True)
高斯濾波
前面兩種濾波方式,卷積核内的每個值都一樣,也就是說圖像區域中每個像素的權重也就一樣。高斯濾波的卷積核權重并不相同:中間像素點權重最高,越遠離中心的像素權重越小,來,數學時間( ╯□╰ ),還記得标準正态分布的曲線嗎?
顯然這種處理元素間權值的方式更加合理一些。圖像是2維的,是以我們需要使用2維的高斯函數,比如OpenCV中預設的3×3的高斯卷積核(具體原理和卷積核生成方式請參考文末的番外小篇):
OpenCV中對應函數為cv2.GaussianBlur(src,ksize,sigmaX):
img = cv2.imread('gaussian_noise.bmp')
# 均值濾波vs高斯濾波
blur = cv2.blur(img, (5, 5)) # 均值濾波
gaussian = cv2.GaussianBlur(img, (5, 5), 1) # 高斯濾波
參數3 σx值越大,模糊效果越明顯。高斯濾波相比均值濾波效率要慢,但可以有效消除高斯噪聲,能保留更多的圖像細節,是以經常被稱為最有用的濾波器。均值濾波與高斯濾波的對比結果如下(均值濾波丢失的細節更多):
中值濾波
中值又叫中位數,是所有數排序後取中間的值。中值濾波就是用區域内的中值來代替本像素值,是以那種孤立的斑點,如0或255很容易消除掉,适用于去除椒鹽噪聲和斑點噪聲。中值是一種非線性操作,效率相比前面幾種線性濾波要慢。
比如下面這張斑點噪聲圖,用中值濾波顯然更好:
雙邊濾波
模糊操作基本都會損失掉圖像細節資訊,尤其前面介紹的線性濾波器,圖像的邊緣資訊很難保留下來。然而,邊緣(edge)資訊是圖像中很重要的一個特征,是以這才有了雙邊濾波。用cv2.bilateralFilter()函數實作:
img = cv2.imread('lena.jpg')
# 雙邊濾波vs高斯濾波
gau = cv2.GaussianBlur(img, (5, 5), 0) # 高斯濾波
blur = cv2.bilateralFilter(img, 9, 75, 75) # 雙邊濾波
可以看到,雙邊濾波明顯保留了更多邊緣資訊。
3、番外小篇:高斯濾波卷積核
要解釋高斯濾波卷積核是如何生成的,需要先複習下機率論的知識(What??又是數學( ╯□╰ ))
一維的高斯函數/正态分布X∼N(μ,σ2)X∼N(μ,σ2):
當μ=0,σ2=1μ=0,σ2=1時,稱為标準正态分布X∼N(0,1)X∼N(0,1):
二維X/Y互相獨立的高斯函數:
由上可知,二維高斯函數具有可分離性,是以OpenCV分兩步計算二維高斯卷積,先水準再垂直,每個方向上都是一維的卷積。OpenCV中這個一維卷積的計算公式類似于上面的一維高斯函數:
print(cv2.getGaussianKernel(3, 0))
# 結果:[[0.25][0.5][0.25]]
生成之後,先進行三次的水準卷積:
然後再進行垂直的三次卷積:
這就是OpenCV中高斯卷積核的生成方式。其實,OpenCV源碼中對小于7×7的核是直接計算好放在數組裡面的,這樣計算速度會快一點,感興趣的可以看下源碼:getGaussianKernel()
上面矩陣也可以寫成:
4、小結
在不知道用什麼濾波器好的時候,優先高斯濾波cv2.GaussianBlur(),然後均值濾波cv2.blur()。
斑點和椒鹽噪聲優先使用中值濾波cv2.medianBlur()。
要去除噪點的同時盡可能保留更多的邊緣資訊,使用雙邊濾波cv2.bilateralFilter()。
線性濾波方式:均值濾波、方框濾波、高斯濾波(速度相對快)。
非線性濾波方式:中值濾波、雙邊濾波(速度相對慢)。
文章轉載自 EX2TRON'S BLOG
http://ex2tron.wang/opencv-python-smoothing-images/