Like Share Discussion Bookmark Smile

J.J. Huang   2026-01-28   Python OpenCV 03.圖片處理篇:基礎技巧   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV 圖片的侵蝕與膨脹(形態學操作)

📚 前言

在前一篇我們學會了 二值化與閾值處理,能將影像轉換成黑白二值影像。
這一篇要進一步學習 形態學操作(Morphological Transformations),其中最基本的就是 侵蝕(Erosion)膨脹(Dilation)。這些方法能幫助我們去除雜訊、強化影像結構,並在物件偵測與影像分割中扮演重要角色。

註:OpenCV 官方文件常使用字母 J 作為範例影像,因為它的形狀簡單、邊緣清楚,方便觀察侵蝕與膨脹的效果。

🎨 範例圖片


圖:圖片來源 — OpenCV 官方文件:Eroding and Dilating 教學

🧩 結構元素 (Structuring Element)

在進行形態學操作之前,需要先定義一個 結構元素 (kernel),它決定了操作的範圍與形狀。
OpenCV 提供 cv2.getStructuringElement() 來生成結構元素。

方法原型

1
kernel = cv2.getStructuringElement(shape, ksize)

參數說明

  • shape:結構元素的形狀,常見有:
    • cv2.MORPH_RECT → 矩形
    • cv2.MORPH_ELLIPSE → 橢圓
    • cv2.MORPH_CROSS → 十字形
  • ksize:結構元素的大小(寬度與高度),例如 (3,3)

🔍 方法原型:侵蝕與膨脹

侵蝕(Erosion)

1
dst = cv2.erode(src, kernel, iterations=1)

膨脹(Dilation)

1
dst = cv2.dilate(src, kernel, iterations=1)

參數說明

  • src:來源影像,通常是二值化影像。
  • kernel:結構元素(通常使用 cv2.getStructuringElement() 生成)。
  • iterations:操作次數,數值越大效果越明顯。

💻 範例程式:侵蝕與膨脹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import cv2
import numpy as np

# 讀取並轉換成灰階
img = cv2.imread("j.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (5x5 方形)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))

# 侵蝕
erosion = cv2.erode(binary, kernel, iterations=1)

# 膨脹
dilation = cv2.dilate(binary, kernel, iterations=1)

# 顯示結果
cv2.imshow("Original", binary)
cv2.imshow("Erosion", erosion)
cv2.imshow("Dilation", dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()

))
圖:程式碼執行結果 — 原圖、侵蝕與膨脹比較 — OpenCV 官方文件:Morphological Transformations 教學

🔍 形態學組合操作

除了基本的侵蝕與膨脹,OpenCV 還提供五種常見的形態學組合操作,每一種都有明確的定義與用途:

  • 📌開運算(Opening)
    定義:先侵蝕再膨脹
    公式

    1
    Opening = Erosion → Dilation

    作用:去除小的白色雜訊,保留主要結構。

  • 📌閉運算(Closing)
    定義:先膨脹再侵蝕
    公式

    1
    Closing = Dilation → Erosion

    作用:填補小的黑色孔洞,讓筆劃更完整。

  • 📌禮帽運算(Top-Hat)
    定義:原圖減去開運算結果
    公式

    1
    Top-Hat = Original - Opening

    作用:擷取原圖中比「開運算」多出來的亮區細節,常用於強化文字或邊緣。

  • 📌黑帽運算(Black-Hat)
    定義:閉運算結果減去原圖
    公式

    1
    Black-Hat = Closing - Original

    作用:擷取原圖中比「閉運算」少掉的暗區細節,常用於檢測陰影或筆劃空隙。

  • 📌形態學梯度(Morphological Gradient)
    定義:膨脹結果減去侵蝕結果
    公式

    1
    Gradient = Dilation - Erosion

    作用:突顯物體的邊界,常用於邊緣檢測或輪廓強化。

💻 開運算(Opening)範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

# 讀取並轉換成灰階
img_hair = cv2.imread("j_opening.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary_hair = cv2.threshold(img_hair, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (3x3 方形)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))

# 開運算
opening_hair = cv2.morphologyEx(binary_hair, cv2.MORPH_OPEN, kernel)

# 顯示結果
cv2.imshow("Original Hair", binary_hair)
cv2.imshow("Opening Hair", opening_hair)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 開運算效果 — OpenCV 官方文件:Morphological Transformations 教學

💻 閉運算(Closing)範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

# 讀取並轉換成灰階
img_point = cv2.imread("j_closing.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary_point = cv2.threshold(img_point, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (9x9 方形)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))

# 閉運算
closing_point = cv2.morphologyEx(binary_point, cv2.MORPH_CLOSE, kernel)

# 顯示結果
cv2.imshow("Original Point", binary_point)
cv2.imshow("Closing Point", closing_point)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 閉運算效果 — OpenCV 官方文件:Morphological Transformations 教學

💻 禮帽運算(Top-Hat)範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

# 讀取並轉換成灰階
img_tophat = cv2.imread("j_tophat.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary_tophat = cv2.threshold(img_tophat, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (5x5 橢圓)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))

# 禮帽運算
tophat = cv2.morphologyEx(binary_tophat, cv2.MORPH_TOPHAT, kernel)

# 顯示結果
cv2.imshow("Original TopHat", binary_tophat)
cv2.imshow("TopHat Result", tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 禮帽運算效果 — OpenCV 官方文件:Morphological Transformations 教學

💻 黑帽運算(Black-Hat)範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

# 讀取並轉換成灰階
img_blackhat = cv2.imread("j_blackhat.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary_blackhat = cv2.threshold(img_blackhat, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (5x5 橢圓)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))

# 黑帽運算
blackhat = cv2.morphologyEx(binary_blackhat, cv2.MORPH_BLACKHAT, kernel)

# 顯示結果
cv2.imshow("Original BlackHat", binary_blackhat)
cv2.imshow("BlackHat Result", blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 黑帽運算效果 — OpenCV 官方文件:Morphological Transformations 教學

💻 形態學梯度(Morphological Gradient)範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

# 讀取並轉換成灰階
img_gradient = cv2.imread("j_gradient.png", cv2.IMREAD_GRAYSCALE)

# 二值化
_, binary_gradient = cv2.threshold(img_gradient, 127, 255, cv2.THRESH_BINARY)

# 建立結構元素 (3x3 方形)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))

# 形態學梯度
gradient = cv2.morphologyEx(binary_gradient, cv2.MORPH_GRADIENT, kernel)

# 顯示結果
cv2.imshow("Original Gradient", binary_gradient)
cv2.imshow("Gradient Result", gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 形態學梯度效果 — OpenCV 官方文件:Morphological Transformations 教學

📊 形態學操作比較表

操作名稱 原理說明 常見用途 處理流程
開運算 先侵蝕再膨脹 去除白色雜訊 MORPH_OPEN
閉運算 先膨脹再侵蝕 填補黑色孔洞 MORPH_CLOSE
禮帽運算 原圖 - 開運算結果 擷取亮區細節 MORPH_TOPHAT
黑帽運算 閉運算結果 - 原圖 擷取暗區細節 MORPH_BLACKHAT
形態學梯度 膨脹結果 - 侵蝕結果 擷取邊界 MORPH_GRADIENT

這些操作都依賴結構元素的形狀與大小,適合用在文字、邊緣、雜訊處理等場景。

⚠️ 注意事項

在使用 OpenCV 的形態學操作時,有幾個地方要特別注意:

  • Kernel(結構元素)
    Kernel 就像「工具頭」,決定操作的範圍和形狀。

    • 小的 kernel(例如 3x3)只會影響局部細節,適合去除小雜訊。
    • 大的 kernel(例如 9x9)影響範圍大,可以填補孔洞,但也可能破壞細節。
    • 形狀不同也會有差異:矩形效果均勻、橢圓邊緣更平滑、十字形對水平垂直線敏感。
  • 操作次數(iterations)
    數值越大,效果越強烈。但太多次可能讓影像失真,要適度使用。

  • 影像類型
    這些操作通常用在二值化影像(黑白),如果直接用在灰階或彩色影像,結果可能不如預期。

  • 邊界效應
    在影像邊緣,操作可能不完整或偏移,因為 kernel 超出範圍。OpenCV 會自動補邊,但結果仍需檢查。

  • 效能考量
    Kernel 越大、操作次數越多,計算時間也會增加,處理速度會變慢。

  • 應用場景小提醒

    • 開運算:去除小白點雜訊
    • 閉運算:填補黑色孔洞
    • 禮帽:突顯亮區細節
    • 黑帽:突顯暗區細節
    • 梯度:抽取邊界

👉 簡單來說:Kernel 決定「刷子大小和形狀」,操作次數決定「刷幾次」,影像類型和邊界也會影響結果。只要掌握這些,就能更靈活地使用形態學操作。

🎯 結語

這一篇我們學會了 侵蝕與膨脹,並延伸到 開運算、閉運算、禮帽、黑帽、梯度 等五種常見的形態學操作。這些方法能幫助我們去除雜訊、強化影像結構,並在物件偵測與影像分割中扮演重要角色。

在下一篇,我們將進一步學習 馬賽克與羽化效果,探索如何利用這些技巧來柔化影像邊緣或隱藏細節,讓圖片處理更具彈性與創意。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。


註:以上參考了
OpenCV Tutorials
OpenCV-Python Tutorials
getStructuringElement()
Eroding and Dilating
Morphological Transformations