OpenCV系列之影像平滑
目標
- 使用各種低通濾鏡模糊影像
- 將定製的濾鏡應用於影像(2D卷積)
接下來,就簡單介紹一下這倆種常用的濾鏡技術。
影像模糊(影像平滑)
通過將影像與低通濾波器核心進行卷積來實現影像模糊。這對於消除噪音很有用。它實際上從影像中消除了高頻部分(例如噪聲,邊緣)。因此,在此操作中邊緣有些模糊。(有一些模糊技術也可以不模糊邊緣)。OpenCV主要提供四種型別的模糊技術。
- 平均
這是通過將影像與歸一化框濾鏡進行卷積來完成的。它僅獲取核心區域下所有畫素的平均值,並替換中心元素。這是通過功能cv.blur()或cv.boxFilter()完成的。檢查文件以獲取有關核心的更多詳細資訊。我們應該指定核心的寬度和高度。3x3歸一化框式過濾器如下所示:
如下所示,其核心大小是5X5:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1:平均
def imgJZ():
img = cv.imread('E:\Opencv\Demo\IMG\opencv-logo-white.png')
blur=cv.blur(img,(5,5))
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.imshow(blur)
plt.title('Blurred')
plt.xticks([])
plt.yticks([])
plt.show()
if __name__ == '__main__':
imgJZ()
執行看一下效果,明細出現了濾鏡效果,如下圖所示:
注意:如果您不想使用標準化的框式過濾器,請使用cv.boxFilter()。將引數normalize = False傳遞給函式。
- 高斯模糊
使用高斯核,代替盒式濾波器。這個功能是通過cv.GaussianBlur() 完成的。我們應指定核心的寬度和高度,該寬度和高度應為正數和奇數。我們還應指定X和Y方向的標準偏差,分別為sigmaX和sigmaY。如果僅指定sigmaX,則將sigmaY與sigmaX相同。如果兩個都為零,則根據核心大小進行計算。高斯模糊對於從影像中去除高斯噪聲非常有效。
如果需要,可以使用函式cv.getGaussianKernel() 建立高斯核心。
可以修改以上程式碼以實現高斯模糊:
blur = cv.GaussianBlur(img,(5,5),0)
完整程式碼如下:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#高斯濾波器
def imgGaussianBlur():
img = cv.imread('E:\Opencv\Demo\IMG\opencv-logo-white.png')
blur = cv.GaussianBlur(img, (5, 5), 0)
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.imshow(blur)
plt.title('Blurred')
plt.xticks([])
plt.yticks([])
plt.show()
if __name__ == '__main__':
imgGaussianBlur()
執行檢視一下效果圖如下:
3. 中位模糊
函式cv.medianBlur() 提取核心區域下所有畫素的中值,並將中心元素替換為該中值。這對於消除影像中的椒鹽噪聲非常有效。有趣的是,在上述過濾器中,中心元素是新計算的值,該值可以是影像中的畫素值或新值。但是在中值模糊中,中心元素總是被影像中的某些畫素值代替。有效降低噪音。其核心大小應為正奇數整數。
我向原始影像新增了50%的噪聲並應用了中值模糊。檢查結果:
medianBlur = cv.medianBlur(img,5)
完整程式碼如下:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 中位模糊
def imgMedianBlur():
img = cv.imread('E:\Opencv\Demo\IMG\opencv.png')
median =cv.medianBlur(img,5)
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.imshow(median)
plt.title('Blurred')
plt.xticks([])
plt.yticks([])
plt.show()
if __name__ == '__main__':
imgMedianBlur()
好了,執行一下,看一下效果圖:
- 雙邊濾波
cv.bilateralFilter() 在去除噪聲的同時保持邊緣清晰銳利非常有效。但是,與其他過濾器相比,該操作速度較慢。我們已經看到,高斯濾波器採用畫素周圍的鄰域並找到其高斯加權平均值。高斯濾波器僅是空間的函式,也就是說,濾波時會考慮附近的畫素。它不考慮畫素是否具有幾乎相同的強度。它不考慮畫素是否是邊緣畫素。因此它也模糊了邊緣,這是我們不想做的。
雙邊濾波器在空間中也採用高斯濾波器,但是又有一個高斯濾波器,它是畫素差的函式。空間的高斯函式確保僅考慮附近畫素的模糊,而強度差的高斯函式確保僅考慮強度與中心畫素相似的那些畫素的模糊。由於邊緣的畫素強度變化較大,因此可以保留邊緣。
原理分析:
雙邊濾波與高斯濾波器相比,對於影像的邊緣資訊能過更好的儲存。其原理為一個與空間距離相關的高斯函式與一個灰度距離相關的高斯函式相乘:
-
空間距離
指的是當前點與中心點的歐式距離。空間域高斯函式其數學形式為:
-
灰度距離
指的是當前點灰度與中心點灰度的差的絕對值。值域高斯函式其數學形式為:
其中gray(xi,yi)為當前點灰度值,gray(xc,yc)為中心點灰度值,sigma為值域標準差。
對於高斯濾波,僅用空間距離的權值係數核與影像卷積後,確定中心點的灰度值。即認為離中心點越近的點,其權重係數越大。
雙邊濾波中加入了對灰度資訊的權重,即在鄰域內,灰度值越接近中心點灰度值的點的權重更大,灰度值相差大的點權重越小。此權重大小,則由值域高斯函式確定。
兩者權重係數相乘,得到最終的卷積模板。由於雙邊濾波需要每個中心點鄰域的灰度資訊來確定其係數,所以其速度與比一般的濾波慢很多,而且計算量增長速度為核大小的平方。
引數選擇:
- 空間域sigma選取:
其中核大小通常為sigma的6sigma + 1。因為離中心點3sigma大小之外的係數與中點的係數只比非常小,可以認為此之外的點與中心點沒有任何聯絡,及權重係數為0.OpenCV中預設的計算公式也是如此,OpenCV參考文件內容如下:“對應高斯引數的 Gaussian sigma (標準差). 如果為零,則標準差由下面的核尺寸計算: sigma = (n/2 - 1)*0.3 + 0.8, 其中 n=param1 對應水平核,n=param2對應垂直核.” - 值域sigma選取:
另灰度差△g = abs(gray(xi,yi)- gray(xc,yc)),忽略常數的影響,因此其函式可以簡化為:
總結分析:
-
Sigma越大,邊緣越模糊,極限情況為simga無窮大,值域係數近似相等(忽略常數時,將近為exp(0)= 1),與高斯模板(空間域模板)相乘後可認為等效於高斯濾波。
-
Sigma越小,邊緣越清晰,極限情況為simga無限接近0,值域係數近似相等(接近exp(-∞) = 0),與高斯模板(空間域模板)相乘後,可近似為係數皆相等,等效於源影像。
瞭解了雙邊濾波與高斯濾波的區別,下面就具體看看實現效果吧:
以下示例顯示了使用雙邊過濾器的使用方法,關於具體使用方法和引數說明,參考官方文件《雙邊濾波》:
blur = cv.bilateralFilter(img,9,75,75)
完整程式碼如下:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 雙邊濾波
def imgBilateralFilter():
img = cv.imread('E:\Opencv\Demo\IMG\opencv.png')
blur = cv.bilateralFilter(img,9,75,75)
plt.subplot(121)
plt.imshow(img)
plt.title('Original')
plt.xticks([])
plt.yticks([])
plt.subplot(122)
plt.imshow(blur)
plt.title('Blurred')
plt.xticks([])
plt.yticks([])
plt.show()
if __name__ == '__main__':
imgBilateralFilter()
好了,看一下效果吧:
2D卷積(影像過濾)
與一維訊號一樣,還可以使用各種低通濾波器(LPF),高通濾波器(HPF)等對影像進行濾波。LPF有助於消除噪聲,使影像模糊等。HPF濾波器有助於在影像中找到邊緣。
OpenCV提供了一個函式cv.filter2D來將核心與影像進行卷積。例如,我們將嘗試對影像進行平均濾波。5x5平均濾波器核心如下所示:
操作如下:保持這個核心在一個畫素上,將所有低於這個核心的25個畫素相加,取其平均值,然後用新的平均值替換中心畫素。它將對影像中的所有畫素繼續此操作。試試如下程式碼:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#2d卷積神經網路
def img2D_Averaging():
img = cv.imread('E:\Opencv\Demo\IMG\opencv.png')
kernel = np.ones((5, 5), np.float32) / 25
dst = cv.filter2D(img, -1, kernel)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()
if __name__ == '__main__':
img2D_Averaging()
完成效果圖如下:
相關文章
- Python 影像處理 OpenCV (7):影像平滑(濾波)處理PythonOpenCV
- C++之OpenCV入門到提高006:影像混合C++OpenCV
- opencv 影像腐蝕、影像的膨脹OpenCV
- opencv 影像的入門OpenCV
- OpenCV(影像NaN處理)OpenCVNaN
- C++之OpenCV入門到提高005:005 影像操作C++OpenCV
- Python 影像處理 OpenCV (15):影像輪廓PythonOpenCV
- Python 影像處理 OpenCV (16):影像直方圖PythonOpenCV直方圖
- openCV中的影像處理 3 影像閾值OpenCV
- Python 影像處理 OpenCV (14):影像金字塔PythonOpenCV
- Matplotlib 系列之【繪製函式影像】函式
- opencv 影像的型別轉換、影像的縮放OpenCV型別
- opencv 獲取影像的屬性OpenCV
- Python的OpenCV轉換影像大小PythonOpenCV
- OpenCV_python全屏顯示影像OpenCVPython
- NLP系列學習:資料平滑
- Python 影像處理 OpenCV (5):影像的幾何變換PythonOpenCV
- Python 影像處理 OpenCV (6):影像的閾值處理PythonOpenCV
- C++之OpenCV入門到提高002:載入、修改、儲存影像C++OpenCV
- OpenCV計算機視覺學習(4)——影像平滑處理(均值濾波,高斯濾波,中值濾波,雙邊濾波)OpenCV計算機視覺
- Python 影像處理 OpenCV (1):入門PythonOpenCV
- OpenCV3影像處理筆記OpenCV筆記
- opencv——影像直方圖與反向投影OpenCV直方圖
- Python 影像處理 OpenCV (10):影像處理形態學之頂帽運算與黑帽運算PythonOpenCV
- OpenCV4影像處理--影像查詢表和顏色表OpenCV
- OpenCV與影像處理學習二——影像基礎知識(下)OpenCV
- 【影像處理】基於OpenCV實現影像直方圖的原理OpenCV直方圖
- 基於Opencv的簡單影像處理OpenCV
- python基於opencv 實現影像時鐘PythonOpenCV
- Python opencv 將一張圖片任意 N 等分並儲存_opencv 等分影像PythonOpenCV
- opencv入門系列教學(六)影像上的算術運算(加法、融合、按位運算)OpenCV
- opencv 影像的 ROI、通道的拆分與合併OpenCV
- 嵌入式程式除錯與opencv影像庫除錯OpenCV
- 談談如何使用 opencv 進行影像識別OpenCV
- Python 影像處理 OpenCV (3):影像屬性、影像感興趣 ROI 區域及通道處理PythonOpenCV
- Numpy 加法運算,opencv 加法運算,影像的融合OpenCV
- openCV入門 核心操作 1 影像的基礎操作OpenCV
- OpenCV影像處理學習筆記-Day1OpenCV筆記