計算機視覺中的開運算(Opening)和閉運算(Closing)是兩種非常重要的形態學(Morphological)圖像處理操作。它們主要用于圖像的去噪、分割、特征提取等任務。這兩種運算都基于兩種更基礎的操作:腐蝕(Erosion)和膨脹(Dilation)。
腐蝕(Erosion)與膨脹(Dilation)
要理解開運算和閉運算,首先需要了解腐蝕和膨脹。在這些操作中,我們使用一個被稱為結構元素(Structuring Element)的核(kernel)來掃描圖像。結構元素是一個小型的、通常是二值的矩陣,它可以有不同的形狀,如正方形、圓形、菱形等。
腐蝕(Erosion)
腐蝕就像它的名字一樣,會“侵蝕”圖像中的前景物體(白色像素)。它的原理是:將結構元素在圖像上滑動,如果結構元素能完全包含在前景像素區域內,那么結構元素中心位置的像素值保持不變(仍為白色);否則,該像素值變為背景(黑色)。
核心作用:
- 收縮前景物體,使細小的物體消失。
- 斷開前景物體之間的細小連接。
- 去除圖像中的小噪點。
可參考:https://blog.csdn.net/www_dong/article/details/151157623
膨脹(Dilation)
膨脹與腐蝕相反,它會“擴張”前景物體。它的原理是:將結構元素在圖像上滑動,如果結構元素與前景像素有任何重疊,那么結構元素中心位置的像素值就變為前景(白色)。
核心作用:
- 擴張前景物體,使物體的輪廓變粗。
- 連接前景物體之間斷開的區域。
- 填充物體內部的小孔洞。
可參考:https://blog.csdn.net/www_dong/article/details/151157814
開運算(Opening)與閉運算(Closing)
開運算和閉運算是腐蝕和膨脹的組合應用,它們通過特定的順序來達到更復雜、更精細的圖像處理效果。
開運算(Opening)
定義: 先進行腐蝕,再進行膨脹。
開運算(A,B)=(腐蝕(A,B)) 膨脹(B)
其中 A 是原始圖像,B 是結構元素。
作用與原理:
- 第一步(腐蝕): 腐蝕操作會移除圖像中所有小于結構元素的孤立噪點和細小連接,同時也會使前景物體收縮。
- 第二步(膨脹): 膨脹操作會恢復腐蝕后前景物體的大小。由于腐蝕已經去除了小噪點,膨脹無法將它們恢復,但會恢復那些較大的、有意義的前景物體。
效果: 開運算的主要作用是去除小的、孤立的噪點,同時平滑物體輪廓。它能有效地將物體從背景中分離出來,特別是當物體被細小的噪點或毛刺污染時。可以形象地理解為,開運算就像一個篩子,把小于“篩孔”(結構元素)的碎屑(噪點)篩掉,而保留了大的顆粒(物體)。
閉運算(Closing)
定義: 先進行膨脹,再進行腐蝕。
閉運算(A,B)=(膨脹(A,B)) 腐蝕(B)
其中 A 是原始圖像,B 是結構元素。
作用與原理:
- 第一步(膨脹): 膨脹操作會填充前景物體內部的小孔洞或裂縫,并連接斷開的物體。
- 第二步(腐蝕): 腐蝕操作會恢復膨脹后物體的大小和輪廓,但由于膨脹已經填充了孔洞,腐蝕無法將它們重新打開,只會使物體輪廓恢復到接近原始狀態。
效果: 閉運算的主要作用是填充物體內部的小孔洞或裂縫,同時連接斷開的物體。它能夠彌合前景物體中的不連續性,使物體輪廓變得平滑。可以形象地理解為,閉運算就像是給物體“打補丁”,把小的破洞和裂縫都修補起來。
opencv實現開運算與閉運算
核心函數
cv2.morphologyEx()
用于執行高級形態學轉換。
cv2.morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=1, borderType=None, borderValue=None)
參數解釋:
src
: 原始輸入圖像(通常是二值圖像)。op
: 要執行的形態學操作類型。對于開運算和閉運算,我們使用:cv2.MORPH_OPEN
:執行開運算。cv2.MORPH_CLOSE
:執行閉運算。
kernel
: 用于操作的結構元素(Structuring Element)。你可以使用cv2.getStructuringElement()
函數來創建它。iterations
: 操作重復的次數,默認為1。增加這個值可以增強效果。
cv2.getStructuringElement()
在執行形態學操作之前,需要定義一個結構元素。cv2.getStructuringElement()
函數可以創建不同形狀和大小的結構元素。
cv2.getStructuringElement(shape, ksize, anchor=None)
參數解釋:
shape
: 結構元素的形狀。常用的形狀有:cv2.MORPH_RECT
: 矩形cv2.MORPH_ELLIPSE
: 橢圓形cv2.MORPH_CROSS
: 十字形
ksize
: 結構元素的大小,以元組(width, height)
的形式指定。
示例
# -*- coding: utf-8 -*-
import cv2
import numpy as np# 創建黑色背景
img = np.zeros((300, 400), np.uint8)# 畫一個大的白色矩形 (主體)
cv2.rectangle(img, (50, 50), (200, 200), 255, -1)# 在矩形中挖黑洞
cv2.circle(img, (100, 120), 15, 0, -1)
cv2.circle(img, (150, 80), 20, 0, -1)# 在矩形下方畫兩個相鄰但斷開的矩形
cv2.rectangle(img, (230, 100), (280, 150), 255, -1)
cv2.rectangle(img, (290, 100), (340, 150), 255, -1)# 在背景添加許多小白點噪聲
for _ in range(150):x, y = np.random.randint(0, 400), np.random.randint(0, 300)img[y, x] = 255# --- 開運算(去噪點) ---
kernel_open = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel_open)# --- 閉運算(填黑洞 + 連接區域) ---
kernel_close = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel_close)# --- 先開運算再閉運算(組合效果) ---
open_then_close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel_close)# 顯示對比
cv2.imshow("Original", img)
cv2.imshow("Opening (Noise Removed)", opening)
cv2.imshow("Closing (Fill holes + Connect)", closing)
cv2.imshow("Open->Close (Clean + Fill)", open_then_close)cv2.waitKey(0)
cv2.destroyAllWindows()
執行效果: