2024-09-23|閱讀時間 ‧ 約 23 分鐘

[OpenCV][Python]判斷物件的形狀

在OpenCV中可以利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。

本文主要利用cv2.arcLength與cv2.approxPolyDP來判斷三角形,正方形,矩形。檢查是否為圓形,則用通過輪廓面積和邊界框面積的比率來判斷。

根據物件的頂點數與比例,可以粗略地判斷形狀。


結果圖

raw-image

利用 cv2.findContours 判斷物件的形狀,可以通過計算輪廓的某些特徵來實現的。常用的方法包括:

  1. 輪廓周長與面積比
    • 可以計算物件的輪廓周長(cv2.arcLength)和面積(cv2.contourArea),再比較兩者的比率來判斷形狀。不同的形狀具有不同的比率。
  2. 形狀近似 (Approximate Contour)
    • 使用 cv2.approxPolyDP 函數,可以將輪廓近似為多邊形。這樣可以判斷該物件是否是三角形、矩形或圓形:如果頂點數為 3,則是三角形。如果頂點數為 4,且邊長接近,則是矩形。如果頂點數超過 5,則可能是圓形。
  3. 圓形檢測
    • 可以使用輪廓面積與邊界框面積的比值來檢測圓形。如果輪廓面積與邊界框面積非常接近,則物件很可能是圓形。

程式範例

import cv2
import numpy as np

# 讀取圖像並轉換為灰階
image = cv2.imread('圖片路徑')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用cv2.findContours來檢測輪廓
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
for contour in contours:
# 獲取輪廓近似
epsilon = 0.04 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)

# 使用頂點數判斷形狀
if len(approx) == 3:
shape = "Triangle"
elif len(approx) == 4:
# 檢測是否是矩形
(x, y, w, h) = cv2.boundingRect(approx)
aspect_ratio = float(w) / h
if 0.95 <= aspect_ratio <= 1.05:
shape = "Square"
else:
shape = "Rectangle"
else:
# 檢查是否為圓形,通過輪廓面積和邊界框面積的比率判斷
area = cv2.contourArea(contour)
circle_area = np.pi * (radius ** 2)
if 0.8 <= area / circle_area <= 1.2: # 比較輪廓面積與理論圓面積
shape = "Circle"
(x, y), radius = cv2.minEnclosingCircle(contour) #最小外接圓
else:
shape = "Unknown"

# 繪製輪廓和標註形狀
cv2.drawContours(image, [contour], -1, (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(contour) # 重新計算文字放置的位置
cv2.putText(image, shape, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

cv2.imshow('Shape detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


判斷形狀部分

接下來的程式碼對每個輪廓進行處理和判斷:

  1. 遍歷每個輪廓
    for contour in contours:
  2. 獲取輪廓近似
    epsilon = 0.04 * cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, epsilon, True)
    • cv2.arcLength 計算輪廓的周長,並乘以 0.04 來獲得近似精度 epsilon。
    • cv2.approxPolyDP 用於簡化輪廓,將其近似為多邊形,True 表示封閉輪廓。
  3. 形狀判斷
    if len(approx) == 3:
    shape = "Triangle"
    elif len(approx) == 4:
    (x, y, w, h) = cv2.boundingRect(approx)
    aspect_ratio = float(w) / h
    if 0.95 <= aspect_ratio <= 1.05:
    shape = "Square"
    else:
    shape = "Rectangle"
    else:
    • 三角形:如果近似頂點數為 3,則判斷為三角形。
    • 四邊形:計算輪廓的邊界矩形 (x, y, w, h)。計算長寬比 aspect_ratio。如果長寬比接近 1(在 0.95 到 1.05 之間),則判斷為正方形;否則為矩形。
  4. 圓形判斷
    area = cv2.contourArea(contour)
    (x, y), radius = cv2.minEnclosingCircle(contour)
    circle_area = np.pi * (radius ** 2)
    if 0.8 <= area / circle_area <= 1.2:
    shape = "Circle"
    • 輪廓面積:使用 cv2.contourArea 計算當前輪廓的面積。
    • 最小外接圓:使用 cv2.minEnclosingCircle 計算能夠包圍該輪廓的最小圓的圓心 (x, y) 和半徑 radius。
    • 圓形判斷:計算圓的理論面積 circle_area,然後比較輪廓面積與理論圓面積的比率。如果比率在 0.8 到 1.2 之間,則判斷為圓形。
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.