圖像輪廓識別基礎:用Python OpenCV一步步實現

1. 環境準備

首先確保安裝了OpenCV和NumPy庫。如果還沒安裝,可以通過pip命令快速安裝:

pip install opencv-python numpy

2. 什麼是圖像輪廓?

圖像輪廓可以理解爲圖像中物體的“邊界線”。比如一張紙上畫了一個正方形,輪廓就是圍繞這個正方形的一圈像素點。識別輪廓的核心作用是定位圖像中的目標物體,比如識別照片中的人臉、圓形物體,或從背景中分離出特定形狀。

3. 輪廓識別的核心步驟

要識別圖像輪廓,通常需要以下4個步驟:
1. 圖像預處理:將圖像轉爲灰度圖並二值化(簡化圖像複雜度)
2. 邊緣檢測:找到圖像中物體的邊界線(比如Canny算法)
3. 輪廓提取:從邊緣中提取出物體的輪廓座標
4. 輪廓篩選與繪製:過濾無用輪廓,只保留目標輪廓並可視化

4. 實戰:識別圖像中的最大輪廓

下面我們用一張簡單的示例圖(比如一張紙上畫了幾個圓形)來演示完整流程。假設圖像名爲shapes.jpg,放在與代碼同目錄下。

步驟1:導入庫並讀取圖像
import cv2
import numpy as np

# 讀取圖像(替換爲你的圖像路徑)
img = cv2.imread("shapes.jpg")
if img is None:
    print("圖像讀取失敗!請檢查路徑是否正確")
    exit()
步驟2:圖像預處理(灰度化+二值化)
  • 灰度化:將彩色圖像轉爲黑白單通道圖像,減少計算量
  • 二值化:將圖像轉爲“純黑白”(0或255),方便後續邊緣檢測
# 轉爲灰度圖
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化:大於127的像素設爲255(白色),否則0(黑色)
# 這裏用THRESH_BINARY_INV反轉黑白,若原圖是白色背景黑色物體,反轉後更易檢測
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
步驟3:邊緣檢測(Canny算法)

Canny算法能高效識別圖像邊緣,核心是通過兩個閾值(低閾值和高閾值)確定邊緣:

# Canny邊緣檢測:閾值1=100,閾值2=200(閾值可根據圖像調整)
edges = cv2.Canny(binary, threshold1=100, threshold2=200)
步驟4:提取輪廓

使用cv2.findContours函數從邊緣中提取輪廓,返回兩個值:
- contours:輪廓列表(每個輪廓是一個座標數組)
- hierarchy:輪廓的層次結構(簡單場景可忽略)

# 查找輪廓:RETR_TREE保留所有輪廓層次,CHAIN_APPROX_SIMPLE壓縮輪廓點
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
步驟5:篩選並繪製輪廓

通常我們只需要保留“大而明顯”的輪廓(比如最大的物體)。這裏通過面積篩選:

# 遍歷所有輪廓,找出面積最大的輪廓
max_area = 0
best_contour = None
for cnt in contours:
    area = cv2.contourArea(cnt)  # 計算輪廓面積
    if area > 1000 and area > max_area:  # 僅保留面積>1000的輪廓(可根據圖像調整)
        max_area = area
        best_contour = cnt

# 繪製輪廓:在原圖上用綠色(0,255,0)繪製輪廓,線寬2
img_contour = img.copy()
cv2.drawContours(img_contour, [best_contour], -1, (0, 255, 0), 2)  # -1表示繪製所有輪廓
步驟6:顯示結果
# 顯示原圖和輪廓圖
cv2.imshow("Original Image", img)
cv2.imshow("Contour Result", img_contour)
cv2.waitKey(0)  # 按任意鍵關閉窗口
cv2.destroyAllWindows()

5. 常見問題與調試技巧

  • 輪廓不完整?:可能是Canny閾值不合適。可嘗試降低threshold1(低閾值)或threshold2(高閾值),或調整二值化方式(比如用THRESH_OTSU自動閾值)。
  • 識別出多餘輪廓?:通過contourArea過濾面積太小的輪廓(比如area > 100),或用cv2.drawContours參數-1改爲僅繪製最大輪廓。
  • 圖像路徑錯誤?:確保cv2.imread的路徑正確,或用絕對路徑(比如"C:/Users/xxx/shapes.jpg")。

6. 擴展:輪廓的更多應用

除了面積篩選,還可以通過輪廓的形狀特徵(如圓形、矩形)或周長進一步識別物體。例如:

# 判斷輪廓是否近似圓形(周長/面積關係)
perimeter = cv2.arcLength(best_contour, closed=True)  # 輪廓周長
area = cv2.contourArea(best_contour)
circularity = 4 * np.pi * area / (perimeter ** 2)  # 圓形度(越接近1越圓)
if circularity > 0.8:
    print("識別到圓形!")

總結

輪廓識別是計算機視覺的基礎技能,通過OpenCV的預處理、邊緣檢測和輪廓提取,就能快速定位圖像中的目標物體。初學者可以從簡單圖像(如幾何圖形)開始練習,逐步嘗試複雜場景(如車牌識別、人臉識別)。關鍵是理解每個步驟的作用,並通過調整參數(如閾值、面積)優化結果。

小夜