Like Share Discussion Bookmark Smile

J.J. Huang   2026-02-04   Python OpenCV 05.特徵與進階篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV 邊緣檢測與輪廓分析

📚 前言

在前一篇我們學會了 魔術棒填充顏色
這一篇要介紹 邊緣檢測 (Edge Detection)輪廓分析 (Contour Analysis),包含常見的 Laplacian、Sobel、Canny 三種方法,並展示如何利用輪廓分析找出影像中的物件邊界。

🔎 Laplacian 邊緣檢測

原理說明

  • Laplacian 是 二階導數運算,偵測影像中灰階值變化最劇烈的地方。
  • 適合快速找出邊界,但容易受雜訊影響。

參數說明

1
cv2.Laplacian(src, ddepth, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
  • src:輸入影像(通常是灰階)。
  • ddepth:輸出影像的深度,常用 cv2.CV_64F 避免溢位。
  • ksize:卷積核大小,必須為正奇數,預設 1。數值越大,邊緣檢測越平滑。
  • scale:縮放因子,調整計算後的梯度值。
  • delta:加到結果上的偏移量。
  • borderType:邊界處理方式,預設 cv2.BORDER_DEFAULT

💻 範例程式

1
2
3
4
5
6
7
8
9
10
11
12
import cv2

img = cv2.imread("test.png") # 部落格頭像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

laplacian = cv2.Laplacian(gray, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

cv2.imshow("Original", img)
cv2.imshow("Laplacian", laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — Laplacian 邊緣檢測,顯示灰階邊界

🔎 Sobel 邊緣檢測

原理說明

  • Sobel 是 一階導數運算,分別計算 水平 (x)垂直 (y) 方向的梯度。
  • 可以強調某一方向的邊緣,常用於影像特徵提取。

參數說明

1
cv2.Sobel(src, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
  • src:輸入影像(通常是灰階)。
  • ddepth:輸出影像的深度,常用 cv2.CV_64F
  • dx:x 方向的導數階數,通常設 1。
  • dy:y 方向的導數階數,通常設 1。
  • ksize:Sobel 核大小,必須為 1、3、5、7。數值越大,邊緣越平滑。
  • scale:縮放因子,調整梯度值。
  • delta:加到結果上的偏移量。
  • borderType:邊界處理方式。

💻 範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import cv2

img = cv2.imread("test.png") # 部落格頭像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)

sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobel = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)

cv2.imshow("Sobel X", sobelx)
cv2.imshow("Sobel Y", sobely)
cv2.imshow("Sobel Combined", sobel)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — Sobel 邊緣檢測,分別顯示水平、垂直與合成邊界

🔎 Canny 邊緣檢測

原理說明

  • Canny 是最常用的邊緣檢測演算法,步驟包含:
    1. 高斯模糊去雜訊
    2. 計算梯度
    3. 非極大值抑制
    4. 雙閾值判斷
    5. 邊緣連接
  • 結果乾淨且穩定,適合後續輪廓分析。

參數說明

1
cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
  • image:輸入影像(必須是灰階)。
  • threshold1:低閾值,用來判斷弱邊緣。
  • threshold2:高閾值,用來判斷強邊緣。
  • apertureSize:Sobel 核大小,預設 3。
  • L2gradient:布林值,若為 True 使用更精確的梯度計算 (L2 norm),預設 False。

💻 範例程式

1
2
3
4
5
6
7
8
9
10
11
import cv2

img = cv2.imread("test.png") # 部落格頭像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

canny = cv2.Canny(gray, 100, 200)

cv2.imshow("Original", img)
cv2.imshow("Canny", canny)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — Canny 邊緣檢測,邊界清晰乾淨

🧠 輪廓函式介紹

在 OpenCV 中,輪廓分析主要依靠兩個函式:

cv2.findContours()

  • 功能:從二值化影像或邊緣檢測結果中,找出所有輪廓。
  • 語法:
    1
    contours, hierarchy = cv2.findContours(image, mode, method)
  • 參數:
    • image:通常是二值化或邊緣檢測後的影像。
    • mode:輪廓檢索方式,例如 cv2.RETR_EXTERNAL (只取外層輪廓)、cv2.RETR_TREE (完整階層)。
    • method:近似方式,例如 cv2.CHAIN_APPROX_SIMPLE (壓縮水平/垂直冗餘點)。

cv2.drawContours()

  • 功能:將偵測到的輪廓繪製到影像上。
  • 語法:
    1
    cv2.drawContours(image, contours, contourIdx, color, thickness)
  • 參數:
    • image:要繪製的影像。
    • contours:由 findContours() 找到的輪廓集合。
    • contourIdx:指定要畫哪一個輪廓,-1 表示全部。
    • color:繪製顏色,例如 (0,255,0)
    • thickness:線條粗細。

✨ 輪廓分析 (Contours)

💻 範例程式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import cv2

img = cv2.imread("test.png") # 部落格頭像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 100, 200)

contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

output = img.copy()
cv2.drawContours(output, contours, -1, (0, 255, 0), 2)

cv2.imshow("Original", img)
cv2.imshow("Contours", output)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:程式碼執行結果 — 輪廓分析,綠色線條標示物件邊界

📊 效果比較

方法 特點 優缺點
Laplacian 二階導數,快速找邊界 容易受雜訊影響
Sobel 一階導數,分方向偵測 可強調水平/垂直邊緣
Canny 綜合演算法,結果乾淨 計算較複雜,但最常用
findContours + drawContours 輪廓偵測與繪製 可進一步分析形狀與面積

⚠️ 注意事項

  • 邊緣檢測前建議先做 高斯模糊,避免雜訊造成誤判。
  • findContours() 的回傳值在不同版本的 OpenCV 可能不同。
  • 輪廓分析常搭配邊緣檢測,建議使用 Canny 作為前處理。

🎯 結語

本篇我們學會了 Laplacian、Sobel、Canny 三種邊緣檢測方法,並理解了 cv2.findContours() 與 cv2.drawContours() 的用法,成功找出影像中的物件邊界。
這些技巧在電腦視覺中非常常見,例如物件偵測、影像分割、形狀辨識等。

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

註:以上參考了
OpenCV Tutorials
OpenCV-Python Tutorials