1. 程式人生 > 其它 >Python - OpenCV 之影象形態學(膨脹與腐蝕)

Python - OpenCV 之影象形態學(膨脹與腐蝕)

Python - OpenCV 之影象形態學(膨脹與腐蝕)

基於 OpenCV 的影象形態學處理 - 膨脹,腐蝕,開運算,閉運算. 涉及到的 OpenCV 函式 -cv2.erode()cv2.dilate()cv2.morphologyEx()

膨脹和腐蝕是影象形態學的兩個基本操作. 典型應用是在二值影象中的使用,是很多識別技術中重要的中間處理步驟.
在灰度影象中根據閾值同樣可以完成膨脹與腐蝕操作.

1. 原理

二值影象f(x,y) 的膨脹操作,類似於對影象的卷積操作.
需要有個 kernel 操作矩陣,類似於卷積核(filters, kernel),常見的是 3X3 的矩陣. 這是形態學處理的核心.
但與卷積不同的是,如果矩陣中的畫素點有任意一個點的值是前景色,則設定中心畫素點為前景色;否則不變.

影象形態學運算中腐蝕,膨脹,開運算和閉運算:

[1] - 腐蝕是一種消除邊界點,使邊界向內部收縮的過程
可以用來消除小且無意義的物體.

腐蝕演算法:
用 3x3 的 kernel,掃描影象的每一個畫素;
用 kernel 與其覆蓋的二值影象做 “與” 操作;
如果都為1,結果影象的該畫素為1;否則為0.
結果:使二值影象減小一圈.

[2] - 膨脹是將與物體接觸的所有背景點合併到該物體中,使邊界向外部擴張的過程
可以用來填補物體中的空洞.

膨脹演算法:
用 3x3 的 kernel,掃描影象的每一個畫素;
用 kernel 與其覆蓋的二值影象做 “與” 操作;
如果都為0,結果影象的該畫素為0;否則為1.
結果:使二值影象擴大一圈.

[3] - 先腐蝕後膨脹的過程稱為開運算
用來消除小物體、在纖細點處分離物體、平滑較大物體的邊界的同時並不明顯改變其面積.

[4] - 先膨脹後腐蝕的過程稱為閉運算
用來填充物體內細小空洞、連線鄰近物體、平滑其邊界的同時並不明顯改變其面積

2. OpenCV 實現

2.1. 定義 kernel 矩陣

首先定義 kernel 矩陣 - 兩種方式:

[1] - 利用 cv2.getStructuringElement 函式

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))  # 橢圓結構
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3
, 3)) # 十字結構 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 矩形結構
kernel = np.uint8(np.zeros((3, 3)))
for i in range(3):
    kernel[2, i] = 1
    kernel[i, 2] = 1

2.2. 腐蝕和膨脹

cv2.erode() 和 cv2.dilate() 函式

import cv2
import numpy as np
import matplot.pyplot as plt

png = cv2.imread('test.png', 0)

plt.figure()
plt.subplot(1, 3, 1)
plt.imshow(png)
plt.axis('off')

# 定義 kernel 
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10, 10))

# 影象腐蝕
eroded = cv2.erode(png, kernel)
plt.subplot(1, 3, 2)
plt.imshow(eroded) # Eroded Image
plt.axis('off')

# 影象膨脹
dilated = cv2.dilate(png, kernel)
plt.subplot(1, 3, 3)
plt.imshow(dilated) # Dilated Image
plt.axis('off')
plt.show()

2.3. 開運算和閉運算

cv2.morphologyEx() 函式

[1] - 先腐蝕後膨脹叫開運算

常用於去除噪聲

cv2.morphologyEx() 函式:

open_ = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

[2] - 先膨脹後腐蝕叫閉運算

常用於填充前景物體中的小洞,或者前景物體上的小黑點.

lose_ = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

開運算和閉運算不是可逆的.

# --*-- coding:utf-8 --*--
import cv2
import numpy as np
import matplot.pyplot as plt

png = cv2.imread('test.png', 0)

plt.figure()
plt.subplot(1, 3, 1)
plt.imshow(png)
plt.axis('off')

# 定義 kernel 
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 閉運算
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
plt.subplot(1, 3, 2)
plt.imshow(closed) # Closed Image
plt.axis('off')

#開運算
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
plt.subplot(1, 3, 3)
plt.imshow(opened) # Opened Image
plt.axis('off')
plt.show()