文章目錄
QQ:3020889729 小蔡
圖像過濾的本質·簡要——濾波
我們對於一維數據或者說信號,我們通常有許多的處理方法——而其中對信號濾波處理是爲了數據更爲理想所必要的。對於一維的信息濾波——有低通(LPF)和高通(HPF)。低通,通常用來去噪等操作。
到這裏,可以順着思路想到二維圖像呢?當然啦,同樣的,二維圖像也是有屬於自己的同一維一樣的濾波形式——低通用於除去圖像的噪點和實現模糊圖像,而高通可以用來實現邊緣查找(這個在後邊介紹。)
——濾波簡單介紹:用一維的信號來說吧
濾波電路——實現相應頻率的輸出/控制:
即只允許一定頻率範圍內的信號成分正常通過,而阻止另一部分頻率成分通過的電路(也叫做經典濾波器)。——這樣的只允許一部分滿足條件的信號/數據得以展現/或者說有效,就是濾波的基本體現。
實現圖像模糊的opencv方法/操作
- 主要步驟爲:
- 1.設置內核——也就是模糊因子——一個矩陣形狀的數據
- 2.將內核與原圖像作相應的運算——這個運算包含在cv. filter2D()或其它的一些函數/方法
- (具體方法在後邊對應問題列出——主要是基本方法的實現。)
平均模糊的實現(2D卷積)
cv. filter2D()——這裏使用的卷積函數實際上知識直接計算——並未真的實現卷積,若是真要卷積的話需要對內核提前進行cv.flip翻轉內核纔行。
計算方法如下:x,y爲輸入圖像的數據。
~kernel是內核
實現的函數參數講解
cv. filter2D()參數如下:
- 輸入參數:輸入圖像
- 深度:數據處理層次,一般設置-1
- 內核(kernel):模糊因子——及變換矩陣
- 內核的錨點,指示內核中已過濾點的相對位置;錨點應位於內核內;默認值(-1,-1)表示錨點位於內核中心。
- 插入值(一般不涉及,默認)
- 邊緣像素推斷(處理)方法(一般不涉及,默認)
- 邊緣像素處理方法的選擇有:前往邊緣像素處理方法簡介
代碼實例
代碼:
import cv2 as cv
import numpy as np
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
kernel = np.ones((5, 5), np.float32)/25
# 注意哦,內核應該保證內核每一個值之和爲1
print("原圖形:\n", img[:, :, 2], end='\n'*4) # 輸出比較處理前後的像素信息發生的變化
dst = cv.filter2D(img, -1, kernel)
print("處理後的圖形:\n", dst[:, :, 2])
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
常用的模糊方法
相對於採用filter2D實現根據內核變化的任意模糊(濾波)處理,我們有時更傾向於專門用來解決某一問題的方法——比如接下來這幾個常用模糊方法。
平滑模糊(也就是平均模糊)
實現方法以及參數
有兩種方法:
其一,也是自己用着比較習慣的(主要是方便):
cv.blur()——使用歸一化框濾鏡模糊圖像。
參數如下:
- 輸入參數:輸入圖像
- 內核大小——即多少乘以多少的矩陣形狀
- 然後就是錨點,邊框/邊緣像素的處理方法(還是一般都不設置,默認爲(-1, -1)也就是內核中心)
其二,採用boxFilter()實現平滑模糊
參數如下:依次爲:輸入圖像,輸出圖像(用返回值接收,所以省略),深度(默認-1),大小(內核大小)——以及後邊不常用的錨點,是否採用歸一化處理數據,邊緣像素的處理方法。
代碼示例——採用cv.blur()
import cv2 as cv
import numpy as np
# 圖像平均模糊處理——blur實現內核模糊
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
dst = cv.blur(img, (5, 5))
# 彩色圖形——第一個維度爲高——也就是行數
# 第二個維度爲寬——也就是列數
# 第三個維度——對應像素信息參數
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.waitKey(0)
效果:(內核越大——也就是矩陣形狀越大,模糊程度越大)
代碼實例——採用cv.boxFilter()
與上邊的blur形成對比——
import cv2 as cv
import numpy as np
# 圖像平均模糊處理——boxFilter實現內核模糊
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
dst2 = cv.boxFilter(img, -1, (5, 5))
dst = cv.blur(img, (5, 5))
# 彩色圖形——第一個維度爲高——也就是行數
# 第二個維度爲寬——也就是列數
# 第三個維度——對應像素信息參數
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.imshow('imag3', dst2)
cv.waitKey(0)
cv.destroyAllWindows()
效果:觀察可以得知,用法和效果是相同的~
高斯模糊
實現方法以及參數
採用cv.GaussianBlur()實現高斯模糊,其參數如下:
- 輸入圖像
- 內核大小——矩陣形狀:高斯核大小。ksize.width和ksize.height可以不同,但它們都必須爲正數和奇數。或者,它們可以爲零,然後根據sigma計算得出。
- sigma x:x方向的偏移值(必須設值,可設爲0不偏移)
- sigma y:y方向的偏移值(可設,可不設)
Y方向的高斯核標準差;如果sigmaY爲零,則將其設置爲等於sigmaX;如果兩個sigmas爲零,則分別從ksize.width和ksize.height計算得出。
爲了完全控制結果,而不考慮將來可能對所有這些語義的修改,建議指定所有ksize,sigmaX和sigmaY。 - 邊緣像素的處理方法選擇(一般不選則)
代碼示例
import cv2 as cv
import numpy as np
# 圖像高斯模糊處理——GaussianBlur
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
dst = cv.GaussianBlur(img, (21, 21), 2, 3)
# 彩色圖形——第一個維度爲高——也就是行數
# 第二個維度爲寬——也就是列數
# 第三個維度——對應像素信息參數
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
補充——如果有需要可以使用cv.getGaussianKernel()創建高斯內核——方法如下:
getGaussianKernel(需要的內核大小, 高斯計算需要的標準差, 濾波器數據類型)
以上參數——對應ksize,二元元組;
標準差任意值,不過若爲負數,那麼就根據ksize計算爲sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8的值設置;
最後的數據類型可以選擇:CV_32F或CV_64F——這裏一般選用32,具體看圖像參數運算需要吧。
中位模糊
函數cv.medianBlur()提取內核區域下所有像素的中值,並將中心元素替換爲該中值。
該濾波器中,中心元素是新計算的值,該值可以是圖像中的像素值或新值。但是在中位模糊中,中心元素始終被圖像中的某些像素值代替。能有效降低噪音。
實現方法以及參數
採用的是cv.medianBlur()實現中位模糊,參數如下:
- 輸入圖像
- 孔徑大小——也可以說是中位模糊濾鏡下的內核大小——可是該內核僅僅是一個正奇數且>=1
代碼示例
import cv2 as cv
import numpy as np
# 圖像中位模糊處理——medianBlur
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
dst = cv.medianBlur(img, 7)
# 彩色圖形——第一個維度爲高——也就是行數
# 第二個維度爲寬——也就是列數
# 第三個維度——對應像素信息參數
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.waitKey(0)
cv.destroyAllWindows()
效果:
看一下其它實例的效果:(官方效果)——左爲原圖
雙邊過濾
cv.bilateralFilter()在消除噪聲的同時保持邊緣清晰的方面非常有效。缺點:該操作速度較慢。
需要知道的是,高斯濾波器採用像素周圍的鄰域並找到其高斯加權平均值。且高斯濾波器是空間的函數,也就是說,濾波時會考慮附近的像素。但它不考慮像素是否具有幾乎相同的強度。它不考慮像素是否是邊緣像素。因此,它也模糊了邊緣,這是我們不想做的。所以有了雙邊過濾——也就是對高斯濾波的掌控。
雙邊濾波的實現,是在空間中需要一個高斯濾波器,同時又有一個高斯濾波器,它是像素差異的函數——控制像素的強度差。空間的高斯函數可確保只考慮附近的像素進行模糊處理,而強度差的高斯函數可確保考慮強度與中央像素相似的像素進行模糊處理。由於邊緣的像素強度變化較大,因此可以保留邊緣。
實現方法以及參數
cv.bilateralFilter()的參數如下:
- 輸入圖像
- 計算像素空間的直徑大小。如果它不是正值,則從sigmaSpace計算得出。——空間濾波直徑大小,加權平均的取樣點的範圍
- sigmaColor設置過濾閾值——在色彩空間中需要過濾的sigma。該參數的值越大,表示像素鄰域內的其他顏色(請參見sigmaSpace)將混合在一起的可能越大也越多,從而產生更大的半均等顏色區域。
- sigmaSpace:sigma像素顏色空間大小——也就是高斯計算的範圍直徑,且滿足:d < 0時,d與sigmaSpace成比例。——像素強度的直徑範圍,與sigmaColor相關。
——這就對應着前面說到的兩個高斯濾波,通過不同的濾波效果組合,實現雙邊過濾。 - 邊緣像素的處理方法
代碼示例
import cv2 as cv
import numpy as np
# 圖像雙邊模糊處理——bilateralFilter
if __name__ == "__main__":
img = cv.imread('../imag_in_save/class1.jpg')
dst = cv.bilateralFilter(img, 20, 55, 20)
# 彩色圖形——第一個維度爲高——也就是行數
# 第二個維度爲寬——也就是列數
# 第三個維度——對應像素信息參數
cv.imshow('imag1', img)
cv.imshow('imag2', dst)
cv.waitKey(0)
cv.destroyAllWindows()
效果:sigmaColor爲55的效果
sigmaColor爲100的效果——像素顏色混合範圍增大,會越來越混合
之後的補充內容,是爲了方便一些參數的理解——不必深究,僅是爲了引入理解,可能會有些描述上的問題,或者其它一些錯誤,如有問題,還望指出。
錨點含義簡要補充(爲了方便理解內容引入,對於opencv中的錨點不盡相同)
前往平均模糊的實現(2D卷積)
錨點——即定位點(這個定位點又有些特殊,由比例組成,也就是x,y均滿足絕對值小於等於1)。
遊輪有拋錨停靠,只要假設拋錨後,錨固定不動,,並且把船體比作一個點,那麼無論長潮或者水面下降,船體與錨的相對位置不變——而對於岸邊(即其它視角的位置)可能會改變哦。
即圖像的排布位置取決於錨點的值——這裏不需要很深的理解。
下面用一種比較一般的
圖解:(這裏的(-1, -1)就是錨點(0, 0),實際上在一些不同的應用環境中是不能有(-1, -1)的),只需要理解錨點的大概意思——及決定圖像的相對位置即可,無需深究這個圖。因爲opencv中錨點值對應的不盡相同,比如在opencv中(-1, -1)代表着內核中心,相當於這裏圖中的(0.5, 0.5)
邊緣像素處理方法可選參數(僅僅展示部分,不做過多說明)
前往原參數列表位置
有興趣可以嘗試下:(就直接貼圖了,具體的處理效果,可以參考以下指出的幾個。)
到這裏,全部內容就結束了。或許,文中錯誤還是有的,如有錯誤還望大家能批評指出。讓我能及時矯正,更改。