前文傳送門:python
「Python 圖像處理 OpenCV (2):像素處理與 Numpy 操做以及 Matplotlib 顯示圖像」dom
「Python 圖像處理 OpenCV (3):圖像屬性、圖像感興趣 ROI 區域及通道處理」函數
「Python 圖像處理 OpenCV (4):圖像算數運算以及修改顏色空間」ui
「Python 圖像處理 OpenCV (5):圖像的幾何變換」.net
「Python 圖像處理 OpenCV (6):圖像的閾值處理」code
「Python 圖像處理 OpenCV (7):圖像平滑(濾波)處理」blog
「Python 圖像處理 OpenCV (8):圖像腐蝕與圖像膨脹」圖片
前面介紹了圖像形態學的兩種基礎算法,圖像腐蝕和圖像膨脹,本篇接着介紹圖像形態學中的開運算、閉運算以及梯度運算。get
因爲內容的連貫性,請先閱讀前文「Python 圖像處理 OpenCV (8):圖像腐蝕與圖像膨脹」,瞭解清楚圖像的腐蝕與膨脹基礎原理。
否則真的沒辦法理解開運算和閉運算。
第一件事情仍是給圖像增長噪聲,思路沿用以前加噪聲的思路,使用 Numpy 給圖片添加黑白兩種噪聲點,代碼以下:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 img = cv.imread("demo.png", cv.IMREAD_UNCHANGED) source = cv.cvtColor(img, cv.COLOR_BGR2RGB) rows, cols, chn = source.shape # 加噪聲-白點噪聲 for i in range(500): x = np.random.randint(0, rows) y = np.random.randint(0, cols) source[x, y, :] = 255 # 圖像保存 白點噪聲圖像 cv.imwrite("demo_noise_white.jpg", source) print("白點噪聲添加完成") # 從新讀取圖像 img1 = cv.imread("demo.png", cv.IMREAD_UNCHANGED) source1 = cv.cvtColor(img1, cv.COLOR_BGR2RGB) # 加噪聲-黑點噪聲 for i in range(1000): x = np.random.randint(0, rows) y = np.random.randint(0, cols) source1[x, y, :] = 0 # 圖像保存 黑點噪聲圖像 cv.imwrite("demo_noise_black.jpg", source1) print("黑點噪聲添加完成") # 顯示結果 titles = ['White Img','Black Img'] images = [source, source1] # matplotlib 繪圖 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()
圖像開運算其實是一個組合運算,開運算是圖像先進行腐蝕,再進行膨脹的運算。
圖像被腐蝕後,去除了噪聲,可是也壓縮了圖像;接着對腐蝕過的圖像進行膨脹處理,使得剛纔在腐蝕過程當中被壓縮的圖像得以恢復原狀。
下面是一個圖像開運算的流程圖:
開運算的一些特性:
咱們先無論開運算 OpenCV 爲咱們提供的函數是什麼,先使用前面介紹過的圖像腐蝕與膨脹處理看下結果:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 source = cv.imread("demo_noise_white.jpg", cv.IMREAD_GRAYSCALE) # 設置卷積核 kernel = np.ones((5, 5),np.uint8) # 圖像腐蝕 erode_img = cv.erode(source, kernel) # 圖像膨脹 dilate_result = cv.dilate(erode_img, kernel) # 顯示結果 titles = ['Source Img','Erode Img','Dilate Img'] images = [source, erode_img, dilate_result] # matplotlib 繪圖 for i in range(3): plt.subplot(1, 3, i+1), plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
能夠看到降噪的效果仍是不錯的。
接着看 OpenCV 爲開運算提供的函數。
圖像開運算主要使用到的函數是 morphologyEx()
它是形態學擴展的一組函數,而其中的 cv.MORPH_OPEN
對應的是開運算。
使用時語法以下:
dst = cv.morphologyEx(src, cv.MORPH_OPEN, kernel)
咱們再使用 morphologyEx()
函數去從新實現下剛纔的圖像開運算,看下和以前的結果有啥區別:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 source = cv.imread("demo_noise_white.jpg", cv.IMREAD_GRAYSCALE) # 設置卷積核 kernel = np.ones((5, 5),np.uint8) #圖像開運算 dst = cv.morphologyEx(source, cv.MORPH_OPEN, kernel) # 顯示結果 titles = ['Source Img','Dst Img'] images = [source, dst] # matplotlib 繪圖 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()
至少從肉眼的角度上看不出來和以前的方式有啥區別,實際上也沒啥區別。
與開運算相反的是閉運算,閉運算是圖像先膨脹,後腐蝕,它有助於關閉前景物體內部的小孔,或物體上的小黑點。
先看下圖像閉運算的流程圖:
閉運算的一些特性:
首先仍是用 dilate()
和 erode()
函數實現一下圖像閉運算,代碼以下:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 source = cv.imread("demo_noise_black.jpg", cv.IMREAD_GRAYSCALE) # 設置卷積核 kernel = np.ones((5, 5),np.uint8) # 圖像膨脹 dilate_result = cv.dilate(source, kernel) # 圖像腐蝕 erode_img = cv.erode(dilate_result, kernel) # 顯示結果 titles = ['Source Img','Dilate Img','Erode Img'] images = [source, dilate_result, erode_img] # matplotlib 繪圖 for i in range(3): plt.subplot(1, 3, i+1), plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
若是想要使用形態學擴展的函數 morphologyEx()
則須要把裏面的參數換成 MORPH_CLOSE
,一樣,既然是形態學擴展函數,那麼圖像腐蝕和圖像膨脹也有對應的參數:
MORPH_ERODE
MORPH_DILATE
接着仍是使用 MORPH_CLOSE
參數來實現下圖像的閉運算:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 source = cv.imread("demo_noise_black.jpg", cv.IMREAD_GRAYSCALE) # 設置卷積核 kernel = np.ones((5, 5),np.uint8) # 圖像閉運算 dst = cv.morphologyEx(source, cv.MORPH_CLOSE, kernel) # 顯示結果 titles = ['Source Img','Dst Img'] images = [source, dst] # matplotlib 繪圖 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()
圖像形態學的梯度運算和前面的開運算閉運算是同樣的,都是組合函數。
梯度運算其實是圖像膨脹減去圖像腐蝕後的結果,最終咱們獲得的是一個相似於圖像輪廓的圖形。
梯度運算在 morphologyEx()
函數中的參數是 MORPH_GRADIENT
,示例代碼以下:
import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 讀取圖片 source = cv.imread("demo.png", cv.IMREAD_GRAYSCALE) # 設置卷積核 kernel = np.ones((5, 5), np.uint8) # 圖像梯度運算 dst = cv.morphologyEx(source, cv.MORPH_GRADIENT, kernel) # 顯示結果 titles = ['Source Img','Dst Img'] images = [source, dst] # matplotlib 繪圖 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()
若是有須要獲取源碼的同窗能夠在公衆號回覆「OpenCV」進行獲取。
http://www.javashuo.com/article/p-gczjtyau-bq.html
https://blog.csdn.net/hanshanbuleng/article/details/80657148