輪廓查找
簡述
輪廓即是以某種方式表示圖像中的曲線的點的列表,可以把輪廓理解爲一個有序的點集。
OpenCV函數原型
cv2.findContours(img, mode, method)
參數解釋
img | 輸入的原圖片 |
mode |
輪廓檢索模式 RETR_EXTERNAL :只檢索最外面的輪廓; RETR_LIST:檢索所有的輪廓,並將其保存到一條鏈表當中; RETR_CCOMP:檢索所有的輪廓,並將他們組織爲兩層:頂層是各部分的外部邊界,第二層是空洞的邊界; RETR_TREE:檢索所有的輪廓,並重構嵌套輪廓的整個層次; |
method |
輪廓逼近模式 CHAIN_APPROX_NONE:以Freeman鏈碼的方式輸出輪廓,所有其他方法輸出多邊形(頂點的序列)。 CHAIN_APPROX_SIMPLE:壓縮水平的、垂直的和斜的部分,也就是,函數只保留他們的終點部分。 |
輪廓繪製
OpenCV函數原型
cv2.drawContours(image, contours, contourIdx, color, thickness)
參數解釋
image | 輸入的原圖片 |
contours | 已經查找出的多個輪廓 |
contourldx | 需要繪製的輪廓的索引 |
color | 繪製的顏色 |
thickness | 繪製的粗細,如果該參數小於0,則表示填充整個輪廓內的區域 |
注意:該函數會直接在圖片上進行繪製,所以一般要將原圖複製一份,再進行繪製
輪廓特徵
令cnt爲圖像中的一個輪廓
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[8]
面積
cv2.contourArea(cnt)
周長
cv2.arcLength(cnt, True)
注意:第二個參數指定圖形是否閉環,如果是則爲True, 否則只是一條曲線。
輪廓近似
OpenCV函數原型
cv2.approxPolyDP(curve, epsilon, closed)
參數解釋
curve | 需要進行近似的輪廓 |
epsilon | 指定近似精度的參數ε,這是原始曲線與其近似值之間的最大距離。參數越小,兩直線越接近 |
closed | 若爲true,曲線第一個點與最後一個點連接形成閉合曲線,若爲false,曲線不閉合。 |
輪廓的外接矩形
OpenCV函數原型
cv2.rectangle(img, (x, y), (x + w, y + h), color, thickness)
參數解釋
img | 進行繪製的圖片 |
x,y | 輪廓左上角的座標 |
w,h | 輪廓的寬度和高度 |
color | 輪廓顏色 |
thickness | 輪廓線條的粗細 |
關於x,y,w,h的位置關係
x,y ------
| |
| |
| |
--------x+w,y+h
代碼演示
import cv2 as cv
import numpy as np
# 讀入圖片
src = cv.imread('contours.png')
# 轉換成灰度圖
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv.threshold(gray, 129, 255, cv.THRESH_BINARY)
# 查找輪廓
# binary-二值化結果,contours-輪廓信息,hierarchy-層級
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
# 顯示輪廓,tmp爲黑色的背景圖
tmp = np.zeros(src.shape, np.uint8)
res = cv.drawContours(tmp, contours, -1, (250, 255, 255), 1)
cv.imshow('Allcontours', res)
cnt = contours[8]
tmp2 = np.zeros(src.shape, np.uint8)
res2 = cv.drawContours(tmp2, cnt, -1, (250, 255, 255), 2)
cv.imshow('cnt', res2)
# 輪廓特徵
# 面積
print(cv.contourArea(cnt))
# 周長,第二個參數指定圖形是否閉環,如果是則爲True, 否則只是一條曲線.
print(cv.arcLength(cnt, True))
# 輪廓近似,epsilon數值越小,越近似
epsilon = 0.08 * cv.arcLength(cnt, True)
approx = cv.approxPolyDP(cnt, epsilon, True)
tmp2 = np.zeros(src.shape, np.uint8)
# 注意,這裏approx要加中括號
res3 = cv.drawContours(tmp2, [approx], -1, (250, 250, 255), 1)
cv.imshow('approx', res3)
# 外接圖形
x, y, w, h = cv.boundingRect(cnt)
# 直接在圖片上進行繪製,所以一般要將原圖複製一份,再進行繪製
tmp3 = src.copy()
res4 = cv.rectangle(tmp3, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv.imshow('rectangle', res4)
cv.waitKey()
cv.destroyAllWindows()
運行結果