十八 輪廓發現
阿新 • • 發佈:2018-10-31
一、輪廓發現
是基於影象邊緣提取的基礎,尋找物件輪廓的方法,所以邊緣提取的閾值選定會影響最終輪廓的發現。
操作步驟
- 1.轉換影象為二值化影象:threshold方法或者canny邊緣提取獲取的都是二值化影象
- 2.通過二值化影象尋找輪廓:findContours
- 3.描繪輪廓:drawContours
二、相關函式
1、findContours尋找輪廓
直接使用二值化影象 cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
使用邊緣檢測後的影象 def findContours(image, mode, method, contours=None, hierarchy=None, offset=None):
image:輸入影象,影象必須為8-bit單通道影象,影象中的非零畫素將被視為1,0畫素保留其畫素值,故載入影象後會自動轉換為二值影象。可以通過threshold和canny獲取
mode:輪廓檢索模式
- RETR_EXTERNAL:表示只檢測最外層輪廓,對所有輪廓設定hierarchy[i][2]=hierarchy[i][3]=-1
- RETR_LIST:提取所有輪廓,並放置在list中,檢測的輪廓不建立等級關係
- RETR_CCOMP:提取所有輪廓,並將輪廓組織成雙層結構(two-level hierarchy),頂層為連通域的外圍邊界,次層位內層邊界
- RETR_TREE:提取所有輪廓並重新建立網狀輪廓結構
- RETR_FLOODFILL:官網沒有介紹,應該是洪水填充法
method:輪廓近似方法
- CHAIN_APPROX_NONE:獲取每個輪廓的每個畫素,相鄰的兩個點的畫素位置差不超過1
- CHAIN_APPROX_SIMPLE:壓縮水平方向,垂直方向,對角線方向的元素,值保留該方向的重點座標,如果一個矩形輪廓只需4個點來儲存輪廓資訊
- CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS使用Teh-Chinl鏈逼近演算法中的一種
返回值
ret = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) #RETR_TREE包含檢測內部
- 返回一個元組,內部有三個元素
- <class 'numpy.ndarray'>
- <class 'list'>
- <class 'numpy.ndarray'>
第一個返回值:cloneImage是我們傳入的二值化影象
第二個返回值:contours是一個列表,是輪廓本身,含有輪廓上面的各個點的位置資訊
第三個返回值:heriachy是每條輪廓對應的屬性
2、drawContours繪製輪廓
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None):
1.image:輸入輸出影象,Mat型別即可
2.contours:使用findContours檢測到的輪廓資料,每個輪廓以點向量的形式儲存
3.contourIdx:繪製輪廓的只是變數,如果為負值則繪製所有輸入輪廓(就是i,僅僅表示一個序號)
4.color:輪廓顏色
5.thickness:繪製輪廓所用線條粗細度,如果值為負值,則在輪廓內部繪製
cv.drawContours(image,contours,i,(0,0,255),2) #繪製輪廓
cv.drawContours(image,contours,i,(0,0,255),-1) #填充輪廓
三、程式碼實現
1、使用直接使用閾值方法threshold方法獲取二值化影象來選擇輪廓
import cv2 as cv import numpy as np def contours_demo(image): # 高斯模糊,消除噪聲 dst = cv.GaussianBlur(image,(9,9),15) # 先變灰度影象 gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY) #OTSU大律法獲取二值影象 #args # 輸入影象 # 閾值(為0是全域性自適應閾值, 引數0可改為任意數字但不起作用) # 與THRESH_BINARY和THRESH_BINARY_INV閾值型別一起使用設定的最大值。 # 閾值型別 ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) cv.imshow('binary image',binary) #尋找輪廓(直接輸入二值影象) #args: # 輸入的二值影象 # 輪廓檢索模式 RETR_TREE:提取所有輪廓並重新建立網狀輪廓結構 # 輪廓近似方法 CHAIN_APPROX_SIMPLE:壓縮水平方向,垂直方向,對角線方向的元素,值保留該方向的重點座標,如果一個矩形輪廓只需4個點來儲存輪廓資訊 #return: # 傳入的二值影象(ndarray) # list:輪廓本身,含有輪廓上面各個點的位置資訊 # 每條輪廓對應的屬性(ndarray) #cloneimage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) #RETR_TREE包含檢測內部 cloneImage, contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) # RETR_EXTERNAL檢測外部輪廓 for i ,contour in enumerate(contours): #cv.drawContours(image,contours,i,(0,0,255),2) #繪製輪廓 cv.drawContours(image,contours,i,(0,0,255),-1) #填充輪廓 print(i) cv.imshow('detect image',image) src = cv.imread('circle.png') cv.imshow('input image',src) contours_demo(src) cv.waitKey(0) cv.destroyAllWindows()
如果使用繪製輪廓的話:
2、使用canny邊緣檢測獲取二值化影象