Python 圖像處理 OpenCV (9):圖像處理形態學開運算、閉運算以及梯度運算

前文傳送門:python

「Python 圖像處理 OpenCV (1):入門」算法

「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)
  • src: 原圖形
  • cv2.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.woshicver.com/

http://www.javashuo.com/article/p-gczjtyau-bq.html

https://blog.csdn.net/hanshanbuleng/article/details/80657148

相關文章
相關標籤/搜索