1. 程式人生 > >十八 輪廓發現

十八 輪廓發現

推文:OpenCV-Python教程(11、輪廓檢測)

一、輪廓發現

基於影象邊緣提取的基礎,尋找物件輪廓的方法,所以邊緣提取的閾值選定會影響最終輪廓的發現。

 

操作步驟

  • 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邊緣檢測獲取二值化影象