目錄
一、輪廓檢測基礎概念
二、核心 API 詳解:cv2.findContours ()
參數說明:
返回值說明:
三、輪廓檢測實戰步驟
1. 圖像預處理(灰度化與二值化)
2. 查找輪廓
3. 繪制輪廓
四、輪廓的常用屬性與操作
1. 輪廓面積與周長
2. 輪廓篩選與排序
3. 輪廓的外接形狀
4. 輪廓近似
五、總結
在計算機視覺領域,輪廓檢測是一項基礎且重要的技術,它能夠幫助我們識別圖像中的物體邊界,為后續的圖像分析、目標識別等任務提供關鍵信息。本文將基于 OpenCV 庫,詳細介紹輪廓檢測的原理、常用 API 及實戰應用。
一、輪廓檢測基礎概念
輪廓可以理解為圖像中具有相同顏色或灰度的連續點組成的曲線,它是物體邊界的有效表達方式。在進行輪廓檢測前,有一個重要的前提:需要將圖片處理為二值圖像(像素值只為 0 和 255),這是因為輪廓檢測主要基于圖像的邊緣信息,二值化處理能簡化后續的檢測過程。
二、核心 API 詳解:cv2.findContours ()
OpenCV 提供了?cv2.findContours()
?函數用于檢測圖像輪廓,其語法格式如下:
參數說明:
-
img:需要進行輪廓檢測的輸入圖像(必須是二值圖像)
-
mode:輪廓的檢索模式,常用的有以下四種:
cv2.RETR_EXTERNAL
:只檢測外輪廓,忽略所有子輪廓cv2.RETR_LIST
:檢測所有輪廓,但不建立等級關系cv2.RETR_CCOMP
:返回所有輪廓,僅建立兩級層次結構(外輪廓為第 1 級,內部中空輪廓為第 2 級)cv2.RETR_TREE
:返回所有輪廓,建立完整的層級組織結構
-
method:輪廓的近似方法:
cv2.CHAIN_APPROX_NONE
:存儲所有的輪廓點cv2.CHAIN_APPROX_SIMPLE
:壓縮模式,只保留輪廓方向的終點坐標(如矩形僅保留 4 個頂點)
返回值說明:
- image:處理后的圖像(與輸入圖像相關)
- contours:包含所有輪廓的列表,每個輪廓是由邊界點坐標 (x,y) 組成的 numpy 數組
- hierarchy:輪廓的層次結構,每個元素是包含 4 個值的數組?
[Next, Previous, First Child, Parent]
,分別表示:- Next:同一層級的下一條輪廓
- Previous:同一層級的上一條輪廓
- First Child:當前輪廓的第一條子輪廓
- Parent:當前輪廓的父輪廓
注意:在新版 OpenCV(如 4.x 版本)中,該函數返回值為 (contours, hierarchy),可使用?
contours = cv2.findContours(...)[-2]
?兼容不同版本。
三、輪廓檢測實戰步驟
1. 圖像預處理(灰度化與二值化)
輪廓檢測前必須進行預處理,將彩色圖像轉為灰度圖,再進一步轉為二值圖:
import cv2# 讀取原圖
phone = cv2.imread('phone.png')
# 轉為灰度圖
phone_gray = cv2.cvtColor(phone, cv2.COLOR_BGR2GRAY)
# 二值化處理(閾值 120,最大值 255,二值化方式)
ret, phone_binary = cv2.threshold(phone_gray, 120, 255, cv2.THRESH_BINARY)# 顯示處理結果
cv2.imshow('phone_gray', phone_gray)
cv2.imshow('phone_binary', phone_binary)
cv2.waitKey(0)
2. 查找輪廓
使用?cv2.findContours()
?函數檢測輪廓:
# 查找輪廓(建立完整層級,壓縮輪廓點)
_, contours, hierarchy = cv2.findContours(phone_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 打印輪廓信息
print("輪廓層次結構:", hierarchy)
print("輪廓數量:", len(contours))
輪廓層次結構: [[[ 6 -1 1 -1][ 2 -1 -1 0][ 3 1 -1 0][ 4 2 -1 0][ 5 3 -1 0][-1 4 -1 0][ 7 0 -1 -1][ 8 6 -1 -1][-1 7 -1 -1]]]
輪廓數量: 9
3. 繪制輪廓
通過?cv2.drawContours()
?函數可以將檢測到的輪廓繪制在圖像上:
# 函數語法
# cv2.drawContours(image, contours, contourIdx, color, thickness)# 復制原圖避免修改原圖
image_copy = phone.copy()
# 繪制所有輪廓(contourIdx=-1),綠色(0,255,0),線寬 2
cv2.drawContours(image_copy, contours, -1, (0,255,0), 2)
cv2.imshow('contours_result', image_copy)
cv2.waitKey(0)
四、輪廓的常用屬性與操作
1. 輪廓面積與周長
- 輪廓面積:使用?
cv2.contourArea()
?計算 - 輪廓周長:使用?
cv2.arcLength()
?計算(參數?closed=True
?表示閉合輪廓)
# 計算第一個輪廓的面積
area_0 = cv2.contourArea(contours[0])
print("第一個輪廓的面積:", area_0)# 計算第一個輪廓的周長
length = cv2.arcLength(contours[0], closed=True)
print("第一個輪廓的周長:", length)
第一個輪廓的面積: 50716.5
第一個輪廓的周長: 952.4377244710922
2. 輪廓篩選與排序
可以根據輪廓面積等屬性篩選特定輪廓,或對輪廓進行排序:
# 篩選面積大于 10000 的輪廓
large_contours = []
for cnt in contours:if cv2.contourArea(cnt) > 10000:large_contours.append(cnt)# 繪制篩選后的輪廓
image_copy = phone.copy()
cv2.drawContours(image_copy, large_contours, -1, (0,255,0), 3)
cv2.imshow('contours_larger_10000', image_copy)
cv2.waitKey(0)# 按面積降序排序,取最大面積的輪廓
largest_cnt = sorted(contours, key=cv2.contourArea, reverse=True)[0]
image_copy = phone.copy()
cv2.drawContours(image_copy, [largest_cnt], -1, (0,255,0), 3)
cv2.imshow('largest_contour', image_copy)
cv2.waitKey(0)
3. 輪廓的外接形狀
可以計算輪廓的外接圓和最小外接矩形:
# 以外接圓為例(選取第三個輪廓)
cnt = contours[2]
# 計算外接圓
(x, y), r = cv2.minEnclosingCircle(cnt)
# 繪制外接圓
phone_circle = cv2.circle(phone, (int(x), int(y)), int(r), (0,255,0), 2)
cv2.imshow('contour_circle', phone_circle)
cv2.waitKey(0)# 計算最小外接矩形
x, y, w, h = cv2.boundingRect(cnt)
# 繪制矩形
phone_rect = cv2.rectangle(phone, (x, y), (x+w, y+h), (0,255,0), 2)
cv2.imshow('contour_rectangle', phone_rect)
cv2.waitKey(0)
4. 輪廓近似
使用?cv2.approxPolyDP()
?函數可以對輪廓進行近似處理,簡化輪廓形狀:
# 函數語法
# approx = cv2.approxPolyDP(curve, epsilon, closed)# 計算近似精度(取輪廓周長的 0.01 倍)
epsilon = 0.01 * cv2.arcLength(contours[0], True)
# 對第一個輪廓進行近似
approx = cv2.approxPolyDP(contours[0], epsilon, True)# 對比原始輪廓與近似輪廓的點數量
print("原始輪廓點數量:", contours[0].shape[0])
print("近似輪廓點數量:", approx.shape[0])# 繪制近似輪廓
phone_new = phone.copy()
cv2.drawContours(phone_new, [approx], -1, (0,255,0), 3)
cv2.imshow('contour_approx', phone_new)
cv2.waitKey(0)
原始輪廓點數量: 235
近似輪廓點數量: 8
其中,epsilon
?參數決定了近似精度:值越小,近似結果越接近原始輪廓;值越大,輪廓越簡化。
五、總結
本文詳細介紹了 OpenCV 中輪廓檢測的核心技術,包括輪廓檢測的預處理步驟、cv2.findContours()
?函數的使用、輪廓繪制方法以及輪廓的各種屬性計算與操作(面積、周長、篩選、排序、外接形狀、輪廓近似等)。
輪廓檢測在目標識別、圖像分割、物體測量等領域有著廣泛的應用,掌握這些基礎操作是進行更復雜計算機視覺任務的前提。實際應用中,需要根據具體場景選擇合適的輪廓檢索模式和近似方法,以達到最佳的檢測效果。