OpenCV 形狀檢測
本教程將討論使用 OpenCV 的 findContours()
和 approxPolyDP()
函式檢測影象中存在的形狀。
使用 OpenCV 的 findContours()
和 approxPolyDP()
函式來檢測影象中存在的形狀
我們可以使用 OpenCV 的 findContours()
和 approxPolyDP()
函式找到影象中存在的形狀。我們可以根據它的角數來檢測形狀。
例如,三角形有 3 個角,正方形有 4 個角,五邊形有 5 個角。
要找到一個形狀的角數,我們必須首先使用 findContours()
函式找到給定影象的輪廓,然後使用 approxPolyDP()
函式找到一個形狀的角或邊數。
我們可以使用 OpenCV 的 findContours()
函式找到給定影象的輪廓,但我們必須在 findContours()
函式中使用二進位制或黑白影象。
要將給定的影象轉換為二進位制,我們必須使用 OpenCV 的 cvtColor()
和 threshold()
函式。
cvtColor()
函式將一種顏色空間轉換為另一種顏色空間,我們將使用它來將 BGR 影象轉換為灰度。threshold()
函式將灰度影象轉換為只有兩個值的二進位制,0 和 255。
我們必須找到 approxPolyDP()
函式的輸出長度以獲取影象的角數,並使用 if-else
語句列印形狀名稱和角數。
我們還可以使用 drawContours()
函式為每個形狀新增不同的顏色。
例如,讓我們檢測 BGR 影象中存在的形狀。請參閱下面的程式碼。
import cv2
import numpy as np
img = cv2.imread("shapes.png")
original = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
ROI_number = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for cnt in cnts:
approx = cv2.approxPolyDP(cnt, 0.01 * cv2.arcLength(cnt, True), True)
print(len(approx))
if len(approx) == 5:
print("Blue = pentagon")
cv2.drawContours(img, [cnt], 0, 255, -1)
elif len(approx) == 3:
print("Green = triangle")
cv2.drawContours(img, [cnt], 0, (0, 255, 0), -1)
elif len(approx) == 4:
print("Red = square")
cv2.drawContours(img, [cnt], 0, (0, 0, 255), -1)
elif len(approx) == 6:
print("Cyan = Hexa")
cv2.drawContours(img, [cnt], 0, (255, 255, 0), -1)
elif len(approx) == 8:
print("White = Octa")
cv2.drawContours(img, [cnt], 0, (255, 255, 255), -1)
elif len(approx) > 12:
print("Yellow = circle")
cv2.drawContours(img, [cnt], 0, (0, 255, 255), -1)
cv2.imshow("image", img)
cv2.imshow("Binary", thresh)
cv2.waitKey()
輸出:
5
Blue = pentagon
6
Cyan = Hexa
8
White = Octa
3
Green = triangle
4
Red = square
14
Yellow = circle
二進位制影象中的形狀應為白色,背景應為黑色。如你所見,輸出影象中形狀的顏色與原始影象中形狀的顏色不同。
OpenCV 的 findContours()
和 approxPolyDP()
函式的引數
findContours()
函式的第一個引數是二值影象,第二個引數是輪廓檢索方法。
我們使用 cv2.RETR_EXTERNAL
,因為我們只需要外部輪廓。第三個引數是用於查詢輪廓的近似方法。
approxPolyDP()
函式的第一個引數是影象的輪廓。第二個是指定逼近精度的引數,第三個用來指定逼近曲線是否閉合。
approxPolyDP()
函式使用 Douglas Peucker 演算法將輪廓形狀近似為另一個形狀。drawContours()
函式用於繪製輪廓。
drawContours()
函式的第一個引數是我們要繪製顏色的影象。第二個引數是輪廓,第三個引數是輪廓的顏色。
第四個引數是線條粗細,如果它的值為負數,顏色將填充形狀。