[OpenCV筆記] 10. 關於輪廓的實作
1.關於輪廓的一些認識
1.1.為什麼要實作輪廓?
邊緣檢測雖可檢測出邊緣,但邊緣不一定連續,無法構成一個整體。而影像輪廓是指將邊緣連接起來的整體,用於後續運算。
1.2.實作流程
讀圖 >> 影像二值化 >> 尋找輪廓 >> 繪製輪廓
1.3.尋找影像輪廓
img , contours, hierarchy = cv2.findContours(img, mode, method)
1.3.1.關於輸出
img:原圖之八位元單通道二值化影像
contours:輪廓。每個輪廓對應4個元素來說明目前輪廓的層次關係,[next(後一個輪廓的索引編號), previous(前一個輪廓的索引編號), first_child(第一個子輪廓索引標號), parent(父輪廓索引標號)]。輪廓的層次參數是由mode所決定,不同mode會獲得不同的輪廓編號,獲得的hierarchy也不同。
hierarchy:影像階層。
1.3.2.關於參數
mode:輪廓檢索方式,常見的方式如下:
- cv2.RETR_EXTERNAL:只檢測外輪廓
- cv2.RETR_LIST:檢測到的輪廓,不建立等級關係
- cv2.RETR_CCOMP:檢測所有輪廓並組織成兩級層次結構
- cv2.RETR_TREE:建立一個等級樹結構的輪廓
method:輪廓近似的方法
- cv2.CHAIN_APPROX_NONE:儲存所有輪廓點,相鄰像素間位置差不超過1。
- cv2.CHAIN_APPROX_SIMPLE:壓縮水平、垂直、對角線方向之元素,只保留該方向的終點座標。
1.4.繪製影像輪廓
img = cv2.drawContours(image, contours, contourIndex, color, thickness, lineType, hierarchy,maxLevel, offset)
1.4.1. 參數與輸出結果說明
img:待繪製影像
contours:需繪製的輪廓
contourIndex: 繪製輪廓的索引號,-1表示全部畫出
color:繪製的顏色
thickness:輪廓的粗細,-1表實線
lineType: 繪製線的形式
hierarchy: 輸出的層次資訊
maxLevel: 輪廓層次的深度。若值為0,表僅繪製第0層輪廓
offset:偏移參數,使輪廓偏移到不同的位置而展示出來
實作後的結果說明如下:
下圖為原圖。
<source:OpenCV Sample Image>依序將各圖形的輪廓畫出。
<source:Greatway9999>左圖為二值化後的圖片,供對照用。右圖為將各圖形的輪廓呈現在同張圖上。
<source:Greatway9999>cv2.contourArea() 指令可計算輪廓面積。cv2.arcLength() 指令可計算輪廓長度。輸出結果如下圖所示。
<source:Greatway9999>使用方法請參考以下程式。
1.4.2.範例程式
import numpy as np
import cv2
#img = cv2.imread('pic3.png', cv2.IMREAD_GRAYSCALE)
img = cv2.imread('pic3.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret_binary, img_binary = cv2.threshold(img_gray, 177, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(hierarchy)
cv2.imshow('img',img)
cv2.imshow('img_binary',img_binary)
new_img = img
new_img = cv2.drawContours(new_img, contours, -1, (0, 0, 255), 3)
cv2.imshow('new_img',new_img)
#計算輪廓面積
n = len(contours)
contoursImg=[]
for i in range(n):
print('contours['+str(i)+']面積=', cv2.contourArea(contours[i]))
temp = np.zeros(img.shape, np.uint8)
contoursImg.append(temp)
contoursImg[i] = cv2.drawContours(contoursImg[i], contours, i, (0, 0, 255), 3)
cv2.imshow('contoursImg['+str(i)+']',contoursImg[i])
#計算輪廓長度
countLen = []
for j in range(n):
countLen.append(cv2.arcLength(contours[j], True))
print('第'+str(j)+'的輪廓長度為%d'% countLen[j])
countLenSum = np.sum(countLen)
countLenAverage = countLenSum / n
print('輪廓總長度:',countLenSum)
print('輪廓平均長度:',countLenAverage)
cv2.waitKey()
cv2.destroyAllWindows()
2.輪廓擬合的常見方法
矩形包圍框
最小包圍矩形框
最小包圍圓形
最佳擬合橢圓
最小包圍三角形
---
參考資料:
0 留言